0、通常,嵌入式软件(这里指单片机系统)的框架千变万化,有带rtos的,也有裸机的。

0.1、写过带系统的,也写过裸机的,这里总结一下两个类型的框架,记录下自己的心得,主要是文字描述,框架图可以后期添加。

1、freertos框架
1.1、使用标准库,网上有很多一直教程,也有现成移植好的,如果自己使用,可以在config文件下,自己需要根据项目的大小进行系统的裁剪,这方面的教程有很多,官方的,原子的,野火的等等。

1.2、使用hal库,可以直接使用freertos的中间件,在代码中,cubemx其实已经把freertos的接口函数封装了一遍,以至于和原来的freertos的接口函数不一样的,但是实现的功能是一样的,这个宗旨是不能变的。项目中通常采用1000hz的调度频率。

但是使用的方法有些不一样,比如延时函数等,这个可以参考stm32方面的教程,文档名称是《STM32 嵌入式操作系统介绍》(或《STM32RTOS培训_嵌入式操作系统介绍》)这个文档介绍了基本的使用方法。尤其是接口函数的使用。英文也有:

https://arm-software.github.io/CMSIS-FreeRTOS/General/html/index.html

1.3、在cubemx中,可以进行系统的裁剪,可以分配多少空间给任务,默认是128字(128×4个字节),最后可以看看还剩多少空间,根据项目的任务数量来具体分配,还有信号量队列,互斥量,软件定时器一般不怎么用,用的最多的是信号量(用于任务或中断的同步),互斥量(临界区的数据保护)。

1.4、开发中,首先要将信号量,任务先建立,没有中断的芯片驱动可以首先初始化。
如果外部芯片有中断的,可以最后初始化,因为如果初始化后,芯片就会产生一个外部中断,从而调用信号量,但是此时你却没有初始化信号量,从而导致死机,这个一定要注意!

1.5、可以使用一个开始任务,把外设初始化、任务创建放在里面,结束后,删除自己即可。

1.6、中断基本上使用信号量来同步,这个比标志位更方便,在任务中判断信号量是否有新,无效则一直等待,也可以设置一个等待时间,一般都是一直等待,这样任务可以挂起,不影响其他任务的运行,这个裸机是有区别的,而且不用清零标志位。

1.7、任务的周期不能太短,100ms基本上ok,50ms也行的,但是这个任务不能长期执行,否则将导致其他任务饥饿,得不到系统运行的时间。

1.8、任务里面尽量不要使用for循环,可以使用计数器的方式代替,比如一个周期只采样一个通道,这个是比较好的方法,否则for循环会导致占用很多cpu资源,导致其他任务无法运行,或者一个任务,只执行了一半的程序。

1.9、任务基本上采用时间片的方式,其实就是将每个任务的优先级设置为一样,这样系统就会在1ms的时刻运行一次某个任务,下1ms运行下一个任务(就是任务切换),直到所有任务都各自运行了1ms,从头开始运第一个任务。这样基本上不用作临界资源的保护动作。

假如,任务1的延时时间是100ms,程序需要运行30ms,任务2的延时时间是50ms,程序需要运行40ms。那么cpu先在前60ms,间隔运行任务1、任务2,每次运行1ms,60ms后,任务1已经运行完毕,进入挂起态。任务2继续运行,运行到70ms后,任务2也运行完毕,进入挂起态,之后到80ms后重新运行任务2。

可以看看下面的示意图。只说明了大概意思,时间点可能不准确,大家也可以提提意见。

2、软件框架:

通信方式使用tcp协议或者modbus协议。
tcp的物理介质是网线,要注意,交叉线和直连线。
modbus使用rs485的总线,使用rtu方式。

2.1总的框架是:应用逻辑使用java实现,在pc或高级的cpu处理器(可以跑linux这种),单片机实现底层的驱动。

2.2、上位机下发一条指令——>单片机串口接收到数据——>检查数据合法性——>置位相关的标志位——>进行一次设备的操作——>清零相关的标志位——>结束

2.3、串口接收结合定时器的方法,modbus就是使用的这种,3.5T以上如没有数据了,说明一帧数据已经结束。可以进行数据解析了。

2.4、使用标志位的目的是,命令来一次,我单片机只操作一次设备,众所周知,rtos中单片机有好几个死循环的,一直在运行的,因此标志位清零后,就达到了目的,以免频繁的操作设备。有的需要自动控制的,那么,就要合理添加标志位,因此标志位的使用比较关键的,要好好规划。

3、另外一种用的较多的是状态机的方法。
通常我们在使用按键的时候会使用状态机的思想,状态机的思想,我最先是在FPGA的课程中用到,后面就陆续在网上看到这单片机中也经常使用的。因此我在任务中,经常使用到,尤其是与外部设备进行通信的过程中。

3.1、一般串口通信我会分如下几个步骤:

空闲态——这个状态没有任何发送和接收

接收态——数据正在接收,同时定时器在该状态中,判断是否已经有4ms的超时,超时了,立即转为“完成态”,并触发一个接收中断,告知单片机可以处理数据解析,这个时刻可以锁定串口不再接收新的数据,等完成处理,发送回上位机后(如果有必要这个步骤),再开启接收的功能,这样可以创造单片机有一个“数据解析处理”的单独的时间,当然前提是:上位机只有接收到单片机的数据后,才能发送下一条数据。

3.2、当然还可以添加一些其他的状态:
超时
数据帧错误
超载状态
基本上6个状态已经可以够用了,比较健壮的。

3.3、同时还可以添加一个状态机,用于描述一个通信状态是否完成。我这里添加了一个事件的状态机:
初始态——数据没有发送、没有接受
完成态——对应于串口的超时、数据帧错误、超载状态、完成态,这样可以告知单片机,一个时间已经完成,可以进行后续的工作。这个在我单片机要发送两次串口任务中使用到,因为要发送两次停机命令,有两个欧姆龙温控器(modbus控制)。

小结:rtos的框架,基本上使用任务+信号量+状态机,就可以解决中小型的项目,而且有一个优点,任务之间耦合性较低,时间控制方面也是比较好的,基本上有的地方可以不用定时器了,编写代码更加省心,比如点led灯,在裸机里面,必须要使用定时器。

效率方便,代写完裸机后,在进行总结一下。

stm32软件编程的框架及注意事项——rtos篇的更多相关文章

  1. 中兴软件编程规范C/C++

    Q/ZX 深圳市中兴通讯股份有限公司企业标准 (设计技术标准) Q/ZX 04.302.1–2003      软件编程规范C/C++                               20 ...

  2. STM32 C++编程 004 Adc (数模转换)类

    使用 C++ 语言给 STM32 编写一个 Adc 类 我使用的STM32芯片:STM32F103ZET6 我们使用的STM32库版本:V3.5.0 注意: 想学习本套 STM32 C++编程 的专栏 ...

  3. php用什么软件编程

    准备好好学习学习PHP了吗?那么你首先应该考虑用什么开发工具(IDE).市面上有很多这类工具,收费的有,免费的也有,选择起来并不轻松. 如果你说PHP编程用基础的文本编辑软件就可以了,比如用记事本.是 ...

  4. 《Data-Intensive Text Processing with mapReduce》读书笔记之二:mapreduce编程、框架及运行

    搜狐视频的屌丝男士第二季大结局了,惊现波多野老师,怀揣着无比鸡冻的心情啊,可惜随着剧情的推进发展,并没有出现期待中的屌丝奇遇,大鹏还是没敢冲破尺度的界线.想百度些种子吧,又不想让电脑留下污点证据,要知 ...

  5. STM32软件复位(基于库文件V3.5)

    源:STM32软件复位(基于库文件V3.5) void SoftReset(void) { __set_FAULTMASK(); // 关闭所有中端 NVIC_SystemReset();// 复位 ...

  6. Java 并发编程——Executor框架和线程池原理

    Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务 ...

  7. gin框架使用注意事项

    gin框架使用注意事项 本文就说下这段时间我在使用gin框架过程中遇到的问题和要注意的事情. 错误处理请求返回要使用c.Abort,不要只是return 当在controller中进行错误处理的时候, ...

  8. (转)java并发编程--Executor框架

    本文转自https://www.cnblogs.com/MOBIN/p/5436482.html java并发编程--Executor框架 只要用到线程,就可以使用executor.,在开发中如果需要 ...

  9. Java 并发编程——Executor框架和线程池原理

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

随机推荐

  1. mybatis:updatebyexample与updateByExampleSelective

    MyBatis,通常逆向工程工具生成接口和xml映射文件用于简单的单表操作. 有两个方法: updateByExample 和 updateByExampleSelective  ,作用是对数据库进行 ...

  2. [原创]Python免杀ShellCode加载器(Cobaltstrike/Metasploit)

    0x001 原理 采用分离法,即将ShellCode和加载器分离.方法较LOW但免杀. 本文主要将ShellCode转成HEX,再通过加载器执行ShellCode. PS: 何为SC加载器,即专门用于 ...

  3. python提取批量文件内的指定内容

    目标文件夹: 文件内容: 实现代码: # -*- coding:utf-8 -*- # __author__ :kusy # __content__:get ssr info from html fi ...

  4. Sitecore 8.2 数据库权限设置

    在我的一个项目中,客户决定改变基础设施.在这个过程中,我得到了一些新的东西需要学习.在本文中,我将分享有关Sitecore数据库权限的经验. 在将数据库从一个服务器移动到另一个服务器时,您需要检查提供 ...

  5. 在C++中调用FFTW

    FFTW是一个可以进行可变长度一维或多维DFT的开源C程序库,是目前最快的FFT算法实现. 本文简述了在Windows平台上,如何在C++中调用FFTW,所使用的IDE为Visual Studio 2 ...

  6. php redis扩展安装步骤

    因为redis不是php技术自带的技术,因此我们如果要通过php程序来操作redis,需要redis设计者提供对应的操作接口(函数类)我们使用phpredis.tar.gz文件在源码编译生成一个red ...

  7. 在Apache中安装php5.6 & php7.3

    1.下载 httpd-2.4.41-win64-VC15.zip.php5.6 +  vc11.  php7.3  + vc14-16 2.配置httpd,在 httpd.conf L180 添加如下 ...

  8. Scala Type Parameters 1

    类型参数 表现形式:在名称后面以方括号表示, Array[T] 何处使用 class 中,用于定义变量.入参.返回值 class Pair[T, S](val first: T, val second ...

  9. 论文笔记:LightGBM: A Highly Efficient Gradient Boosting Decision Tree

    引言 GBDT已经有了比较成熟的应用,例如XGBoost和pGBRT,但是在特征维度很高数据量很大的时候依然不够快.一个主要的原因是,对于每个特征,他们都需要遍历每一条数据,对每一个可能的分割点去计算 ...

  10. 命令创建.net core3.0 web应用详解(超详细教程)

    原文:命令创建.net core3.0 web应用详解(超详细教程) 你是不是曾经膜拜那些敲几行代码就可以创建项目的大神,学习了命令创建项目你也可以成为大神,其实命令创建项目很简单. 1.cmd命令行 ...