很多STM32单片机初学者都是从裸机开始的,裸机确实也能开发出好的产品。但是,作为一个嵌入式软件工程师,况且用的并不是51那种低端单片机,如果只会用裸机开发产品,那肯定是不够的。
要从裸机的思维转变到 RTOS(Real Time Operating System)的思维,其实需要一个过程,而且开始的一段时间会很痛苦。但过一段时间理解了一些内容,能写一些Demo之后,你会发现其实RTOS也不难。
现在 FreeRTOS 在CubeMX工具中可以直接配置并使用,相当方便。
为什么需要 RTOS
为什么我们需要RTOS?就像最开始学C编程时,老师告诉我们,指针很重要,那时你肯定有一个大的疑问,指针到底有什么好?
心里一直犯嘀咕着:不用指针不一样把程序编出来了?现在想想看C语言没了指针,是不是“寸步难行”呢。
回到正题,我们到底为什么需要RTOS?
一般的简单的嵌入式设备的编程思路是下面这样的:
main
{
{处理事务1};
{处理事务2};
{处理事务3};
。..。..。
{处理事务N};
}
isr_server
{
{处理中断};
}
这是最常见的一种思路,对于简单的系统当然是够用了,但这样的系统实时性很差。
比如“事务1”如果是一个用户输入的检测,当用户输入时,如果程序正在处理事务1下面的那些事务,那么这次用户输入将失效,用户的体验是“这个按键不灵敏,这个机器很慢”,而我们如果把事务放到中断里去处理,虽然改善了实时性但会导致另外一个问题,有可能会引发中断丢失,这个后果有时候比“慢一点”更加严重和恶劣!
又比如事务2是一个只需要1s钟处理一次的任务,那么显然事务2会白白浪费CPU的时间。
改进思路
看到上面裸机开发的局限了吗?
这时,我们可能需要改进我们的编程思路,一般我们会尝试采用“时间片”的方式。这时候编程会变成下面的方式:
main
{
{事务1的时间片到了则处理事务1};
{事务2的时间片到了则处理事务2};
。..。..。
{事务N的时间片到了则处理事务N};
}
time_isr_server
{
{判断每个事务的时间片是否到来,并进行标记};
}
isr_server
{
{处理中断};
}
可以看到,这种改进后的思路,使得事务的执行时间得到控制,事务只在自己的时间片到来后,才会去执行。但这种方式仍然不能彻底解决“实时性”的问题,因为某个事务的时间片到来后,也不能立即就执行,必须等到当前事务的时间片用完,并且后面的事务时间片没到来,才有机会获得“执行时间”。
这时候我们需要继续改进思路,为了使得某个事务的时间片到来后能立即执行,我们需要在时钟中断里判断完时间片后,改变程序的返回位置,让程序不返回到刚刚被打断的位置,而从最新获得了时间片的事务处开始执行,这样就彻底解决了事务的实时问题。
我们在这个思路上,进行改进,我们需要在每次进入时钟中断前,保存CPU的当前状态和当前事务用到的一些数据,然后我们进入时钟中断进行时间片处理,若发现有新的更紧急的事务的时间片到来了,则我们改变中断的返回的地址,并在CPU中恢复这个更紧急的事务的现场,然后返回中断开始执行这个更紧急的事务。
使用 RTOS 的好处
上面那段话,对于初学者来说,可能有些不好理解。
事实上,这是因为要实现这个过程是有些复杂和麻烦的,这时候我们就需要找一个操作系统(OS)帮我们做这些事了,如果你能自己用代码实现这个过程,事实上你就在自己写操作系统了。
其实从这里也可也看出,操作系统的原理其实并不那么神秘,只是一些细节你很难做好。我们常见的RTOS基本都是这样的一个操作系统,它能帮你完成这些事情,而且是很优雅的帮你完成!
事实上,RTOS的用处远不止帮你完成这个“事务时间片的处理”,它还能帮你处理各种超时,进行内存管理,完成任务间的通信等。
有了RTOS,程序的层次也更加清晰,给系统添加功能也更方便,这一切在大型项目中越发的明显!
关键字:STM32 单片机开发
引用地址:
STM32 单片机开发中的 RTOS应用分析
推荐阅读最新更新时间:2024-11-01 23:53
STM32开发笔记78: 2种STOP模式的唤醒方法
单片机型号:STM32L053R8T6 前面已有多篇开发笔记详细阐述了STM32 STOP模式的进入和唤醒方法,如果自发唤醒一般选用RTC方法,其调用的程序如下: Target.EnableLowPower(); //使能超低功耗 Target.Rtc.EnterStopRtcMode(10); //进入低功耗,时间10秒 EnableLowPower使能了超低功耗。EnterStopRtcMode通过RTC方式进入STOP模式,后面的参数指定的是唤醒时间,也就是进入STOP模式后,10秒唤醒。 唤醒后做的事情还很多,最主要的是时钟变换,这在开发笔记STM32开发笔记74: STM32L0低功耗唤醒后的时
[单片机]
STM32 Cubemax(三)——时序读写完成称重传感器+HX711的使用
前言 因为在一个项目中使用到了称重传感器,在此记录一下其使用方法还有一些需要注意的地方。 首先介绍一下使用的传感器 HX711——一款专用于电子秤的A/D转换芯片 称重传感器(使用的这一款量程200KG) 一、接线 买到传感器后,可以看到后面尾巴引出了5条线 **其中黄线在单片机处理里面是不需要的,不需要接。 ** 如果大家买的是我上图的那一款HX711,那么可以直接按照上面的英文指示接线。 照着颜色接就完事了,RED接红线,BLK接黑线。 但还有几款HX711上面没有这个颜色提示,那也没有关系。 一般如下 接完了HX711和称重传感器,下一步就是接HX711和单片机 这里 DAT和CLK为自己
[单片机]
意法半导体STM32智能无线模块加快创新互联产品开发
意法半导体STM32智能无线模块加快创新互联产品开发 I-care 集团在Wi-care智能工业预测性维护系统中采用STM32WB5MMGH6无线模块 2022年11月7日,中国 ----服务多重电子应用领域、全球排名前列的半导体公司意法半导体(STMicroelectronics,简称ST;)通过开发智能无线模块帮助工业企业提高制造效率,减少资源浪费和环境污染。STM32WB5MMGH6无线模块是为工业4.0应用专门设计,可以降低用意法半导体创新的无线微控制器开发强大用例的难度,如,I-care 集团的智能设备状态监测。 该模块为使用Bluetooth Low Energy、Zigbee、Thread等主流标准开发
[嵌入式]
stm32-BootLoader程序和app程序合并烧录
我前面的文章有说过,如何制作BootLoader和app程序,但是需要烧录2个hex文件,整个程序才可以正常运行。 那如果是量产烧录2次程序是非常耗时间的,通过查阅一些资料,可以把两个hex文件合并成一个hex文件。 hex文件的格式不做解释,有兴趣可以百度一下,很多大神说过。 我亲自做了2款合并软件 一个是dos界面的 一个是MFC界面的 先看看dos界面的使用 运行合并程序之前: 运行合并程序之后: 这里面多了一个合并的hex,只要烧录这个hex文件,整个程序就包括了BootLoader和app了。 实测烧录进芯片是可以完美运行的。 MFC版本 分别选择BootLoader.h
[单片机]
STM32学习—如何选择各个电路部分的主要芯片
电路设计的基本过程一般是这样的:需求分析——元件选型——原理图设计——PCB设计——焊接调试。 ▼需求分析: 在这里,主要是确定小车需要哪些模块、外设或接口。首先,STM32最小系统是必须的,这是小车控制的核心。然后小车的两个轮子需要两个H桥驱动和编码器接口。需要陀螺仪感知小车的姿态(包括倾角,转向角,角速度等)。需要一些调试和指示用的外设(蜂鸣器,LED等)。需要电源电路为系统供电。需要电池电压采集电路来实时采集电池电压,做低压报警,防止电池过放。需要下载接口和调试用的串口。基本就是根据自己想要实现功能,然后确定需要那些部分的电路。 ▼元件选型: 为需要的各个部分电路选择元件,一般来说,主要是选择何种型号、什么封装的芯片
[单片机]
浅析STM32的hex文件
前段时间需要用到BIN文件 随便把HEX文件也了解了一下 参考查阅了一些网上资料,如有雷同除了巧合还有借鉴参考。。。 正题:HEX文件格式如下 0x3a 0x0d 0x0a 分析下面具体例子 :020000040800F2 : 这个就是 0x3a ,也就是冒号 02 这个就是说明这行数据区的数据内容长度,也就是数据内容为两个字节在后面的 0800 那里 0000 这个是数据要送往的地址 要看具体数据类型 04 解释整行数据的数据类型,主要有这几种 '00' Data Record 数据 '01' End of File Record 文件结束标志 '02' Extended
[单片机]
STM32(RFID)阶段二(读序列,修改金额)
前一段时间进行了USART2串口添加,接收协议改写的工作。这一次就可以利用之前的接收和发送代码来完成miniSTM32单片机与RFID读写器的通信,实现IC卡充值和扣费的操作。资料支持:串口通信数据的LCD显示,中断嵌套等等。 字符串显示使用 sprintf() 函数,中断嵌套修改中断优先级。 demo2功能:IC卡设置成自动返回卡号和块数据,读一次;IC卡一接触到读写器,就向读写器发送卡号和指定块数据。接收数据显示在TFTLCD上,在中断函数中,设置KEY1为加100操作,KEY0为减100操作;每一次修改数额,都将钱数刷新一次,并显示通信接收数据包。 上代码: rfid.c #include r
[单片机]
STM32 ucos 下添加CAN模块
1.CAN IO RX TX 的设定和重映射 GPIO_PinRemapConfig(GPIO_Remap2_CAN, ENABLE); //端口重映射到PD0,PD1 2.clock CAN IO CLOCK 的开启 、*-------gpio for can------------*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE); CAN 自身CLOCK 的开启、 /* CAN Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN
[单片机]