ucos系统中串口驱动

目的: 编写串口驱动文件,包括串口初始化、串口收、串口发送、(串口发送缓冲区空、串口接收缓冲区满)

最终实现的目的是各个应用程序不必关心串口的实现,仅仅分别向发送缓冲区完整的写入数据;同时让串口设备自行从发送缓冲区中取数,并从串口发出;串口接收到的数据自行存入接收缓冲区中,每收到一个字节,向等待接收缓冲区数据的应用程序发信号,各个应用程序运行。


应用程序从串口发送命令后,依靠串口接收发送消息挂起本身,等待数据到达,若有数据且正确,继续进行应用程序;若有数据但不正确,发送消息表明数据错误,结束任务;若无数据,发送消息表明超时,结束任务。或者串口数据到达,发送消息到数据处理任务。


模型建立:

简述

1、默认使用串口进行数据采集的应用程序处于挂起态,等待消息邮箱并进入运行态;

各个任务被一个专属于串口采集的消息邮箱挂起,依据消息邮箱中的值决定哪个任务进入运行态;消息邮箱的值来源于定时器或者网络数据或者GUI任务;进入运行态后,分别调用数据封装函数,将封装后的数据写入发送缓冲区中;任务被接收缓存区的消息邮箱阻塞,并设置超时时间。

struct TxBufType
{
u8 buf[200];//数据存储空间或者是一个地址
OS_EVENT *mutex; //本存储空间的互斥锁
u8 base;//数据起始地址,存储数据时,从这里开始;当存储的数据长度大于200-base时,并且下边的 size大于数据长度,表明一部分数据存储在数据末端,另一部分存储在顶端
u8 size;//空闲区长度
};

2、写入发送缓冲区的过程:各个应用程序在封装数据完毕后,被发送缓冲区的互斥锁阻塞;当发送缓冲区空闲,检查是否有足够的空间。

有,将数据复制base开始的数据区;当到了数组末尾,将数据剩余部分存储在数据区首端,重置base和size后释放互斥锁,将之前的base和数据长度作为消息发到到串口发送任务的消息队列中。

无,则继续被互斥锁阻塞,重复进行N次,N次还不行,则报错退出,回到被消息邮箱阻塞位置。

3、串口发送任务被消息队列阻塞;当消息队列中有数据,提取其中的base和size,需要从发送缓冲区中提取从base开始,size长度的数据,并使用串口发送。在从发送缓冲区提取的时候,需要得到发送缓冲区的互斥锁,确保缓冲区没有被锁(可能被其他任务加锁);这里需要一直等待得到锁,得到锁后,从串口发送数据,将数据发送后,重置发送缓冲区的base和size,释放互斥锁;延时N后,继续被消息队列阻塞,延时的作用是多个设备从一个串口进行数据收发,要增加延时,避免识别包错误。

4、串口接收函数被接收缓冲区的互斥锁阻塞;当有串口数据后

接收缓冲区空闲:直接将数据存储至缓冲区,更新base和size;发送消息邮箱,应用任务恢复,检查数据是否完整正确,正确,则完成了整个流程;当任务超时或者数据不正确,报错退出。

接收缓冲区不空闲:暂存数据,等待释放互斥锁;


重点:多个任务并发的对发送缓冲区操作,缓冲区较大,偶尔可以允许多个任务将数据写入发送缓冲区,需要注意的是当多个任务将数据写入后,串口发送任务执行的比较慢,发送完一个任务的数据,锁定发送缓冲区,释放发送缓冲区的相应空间,解锁;等待一个时间间隔(依据协议而定);进行下一次发送

3、串口接收到数据直接写入接收缓冲区中,接收到每一个字节,都要发消息邮箱激活各个等待此串口数据的应用程序;应用程序收到消息,运行后,检查接收缓存中的数据,是否正确。

重点:应用程序如何实现继续等待信号?接收缓冲区中的数据针对应用程序没有合法的头和尾,怎么办?交给应用程序处理




随想:

串口发送流程:应用程序(可能是多个)将数据写到串口发送缓冲区(可被多任务共享,注意数据完整性,任务独占缓存)中;串口发送缓冲区中的数据应该通过一个函数f()(何时通知,是应用程序将所有数据都写入缓冲区再通知?还是只要缓冲区中有数据就通知?还是检测到缓冲区不为空,然后逐个发送)逐个从串口发送出去(发送完成再调用f());

串口接收流程:串口中断中有数据到达,调用一个函数g()实现了将数据存入接收缓冲区中;缓冲区非空,通知


你可能感兴趣的:(ucOS)