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. mapreduce 变量共享

    mapreduce 全局变量共享 在编写MapReduce程序时,经常会遇到这样的问题,全局变量如何保存?如何让每个处理都能获取保存的这些全局变量?使用全局变量是不可避免的,但是 在MapRdeuce ...

  2. c# 数据请求方式提供

    营销平台数据请求介绍 项目介绍: 前端使用 WPF,采用MVVM模式  后端数据库采用的sqlite 依靠本地化运行   后期可能会采用WebApi   因为WPF都是自学的 所以 代码方面写的可能不 ...

  3. 微信企业微信调试JS神器vConsole

    在js页面上放以下代码 <script src='https://cdn.bootcss.com/vConsole/3.3.2/vconsole.min.js'></script&g ...

  4. 使用Kafka Connect创建测试数据生成器

    在最近的一些项目中,我使用Apache Kafka开发了一些数据管道.在性能测试方面,数据生成总是会在整个活动中引入一些样板代码,例如创建客户端实例,编写控制流以发送数据,根据业务逻辑随机化有效负载等 ...

  5. Linux设置SSH隧道连接

    因为安全考虑,服务器防火墙对某些端口进行了限制,原先通过客户端工具可以连接的端口,现在不能连接了,需要通过设置SSH隧道才可以,记录如下.

  6. 实验代码:const* 和 const&

  7. HeRaNO's NOIP CSP Round Day 2 T2 PESTC

    对于我这种菜鸡来说还是挺有迷惑性的. 在考场发现答案问的是跟最值有关的数量,想到二分,结果果然具有单调性,考虑二份答案+验证 其实什么反转什么的,可以不用去管他,对于长度小于二分答案mid的道路,不去 ...

  8. Node.js 中 exports 和 module.exports 的区别

    每一个模块中都有一个 module 对象, module 对象中有一个 exports 对象 我们可以把需要导出的成员都放到 module.exports 这个接口对象中,也就是 module.exp ...

  9. 输入url之后经历什么?

    一.浏览器查找输入域名的IP地址(拿到 IP) 1.查找浏览器缓存(浏览器一般会缓存DNS记录一段时间,一般为2-30分钟). 2.查找系统缓存(即hosts文件,有没有对应的IP) 3.以上都没有的 ...

  10. 内网漫游之SOCKS代理大结局

    0×01 引言 在实际渗透过程中,我们成功入侵了目标服务器.接着我们想在本机上通过浏览器或者其他客户端软件访问目标机器内部网络中所开放的端口,比如内网的3389端口.内网网站8080端口等等.传统的方 ...