串口(UART0)之UC/OS(二)

一.串口接收数据在UC/OS设计中应注意的问题

1.    串口通信的数据接收过程:

1>  UART 接收FIFO接收到预定字节后触发中断

2>  ISR读取接收到的内容并保存

3>  经过一次或若干次ISR完成一个通信帧的接收(拼装通信帧)

4>  处理和解释通信内容

5>  根据处理结果触发其他任务

2.    串口数据接收程序设计时,应该考虑的问题:

1>即使以上的操作过程很简单,也最好不要把它全部安排在ISR中完成,如果放在一起的话,就会给UART0通信带来危机(此处具体请看前面的文章)。

2>所以要安排一个与ISR关联的“串口接收”任务来完成后面的工作。再创建一个帧缓冲区。在接收的过程中,将接收到的内容写入帧缓冲区。接收完一帧后,处理和解释过程需要读帧缓冲区的内容。

3>将写帧缓冲区的操作安排在ISR中完成,读帧缓冲去的操作安排在串口接收任务中完成。

4>由于ISR和串口接收任务是并发程序单元,存在资源同步问题,故需要对帧缓冲区进行互斥访问。

二.设计ISR与串口接收任务之间的通信方法:

1. ISR的主要功能是响应异步事件,该异步事件将触发一系列操作。ISR设计的基本原则是:尽可能简短。

2.ISR与关联任务的通信方式有两种类型:信号型和数据型。

1>当使用信号量进行通信时,ISR只完成发送信号量的工作,表示事件已经发生,通过信号量的同步功能触发关联任务。

2>当使用数据进行通信时,ISR需要完成对异步事件的信息进行采集工作,然后使用消息邮箱(或消息队列)将数据发送给关联任务,由关联任务完成后续数据处理工作。

3>做项目时常见的三种情况:

Ø  触发ISR的事件不包含数据:不需要对事件进行信息采集。此时,ISR使用信号量与关联任务进行通信。

Ø  触发ISR的事件是包含数据的低频事件:将数据采集的工作放在关联任务中完成,(产生的时刻延迟与采样周期相比可以忽略不计,对采集数据的质量没有影响。此时,ISR使用信号量与关联任务进行通信,从而简化了ISR。

Ø  触发ISR的事件是包含数据的中高频事件:数据采集的工作放在关联任务中完成时,产生的时延与采样周期相比不能忽略不计时,对采样数据的质量有影响。此时,关联任务从消息邮箱中得到消息的数据,并完成后续处理工作。

Ø  触发ISR的事件是包含数据的非周期高频率事件:对于非周期高频事件,其最短事件间隔可能小于一个事件数据处理的耗时,如果使用消息邮箱进行通信,就可能会出现数据丢失现象。此时,数据采集的工作应该在ISR中完成,由ISR使用具有数据缓冲功能的消息队列与关联任务进行通信。关联任务从消息队列中得到消息的数据,并完成后续处理工作。

注意:具体采用那一种方式来实现ISR与串口接收任务之间的通信要视具体情况而定。

以下用信号量和消息队列两种方式来实现串口接收编程

三.   UC/OS串口接收数据编程

通过一个程序来分析UC/OS串口接收数据设计和实现

程序设计目标:

用串口中断接收上位机发送的8字节数据,再把它们传送给上位机。

u 用信号量的方式

1.系统有那些任务组成

1>  启动任务

2>  接收任务

3>  接收中断服务例程

4>  发送任务

2.各任务之间的关系

3.启动任务流程:

l  定义各种通信工具(例如:信号量)

l  系统硬件初始化

l  初始化UART0

l  创建各个任务

l  创建各种通信工具

l  删除自己

程序:

/**********************************************************************                            Task0(启动任务)********************************************************************/void Task0    (void *pdata){pdata = pdata;              TargetInit();                         //硬件初始化                                                UART0_Init(115200);                 //初始化串口Sem_SendFlag   =  OSSemCreate(0);  //创建发送信号量Sem_StartFlag  =  OSSemCreate(1);   //创建开始信号量OSTaskCreate(Task1,(void *)0, &TaskStk1[TaskStkLengh - 1],4);  //创建接收任务OSTaskCreate(Task2,(void *)0, &TaskStk2[TaskStkLengh - 1],5);  //创建发送任务OSTaskDel(OS_PRIO_SELF);           //删除自己  }

4.接收任务流程

l  等待开始信号量

l  处理和解释通信内容(本程序较简单,不涉及)

程序:

/********************************************************************Task1(接收任务)********************************************************************/void Task1     (void *pdata){uint8 err;pdata = pdata;while(1){OSSemPend(Sem_StartFlag,0,&err);  //等带开始信号量//以下可以根据具体业务来编写处理和解释通信内容}}

5.串口中断接收流程:

l  关中断

l  清除串口中断标志位

l  清除中断控制寄存器

l  接收数据放入缓冲区

l  开中断

l  发送发送信号量

程序:

/*********************************************************** 名    称:           UART0_Exception* 功    能:           串口接收中断* 入口参数:           无* 出口参数:        无**********************************************************/void  UART0_Exception(void){uint8 i;uint32 data;OS_ENTER_CRITICAL();data = U0IIR;                            //清除中断表示寄存器标志VICVectAddr = 0;                         //清除中断for(i=0; i<8; i++){rcv_buf[i] = U0RBR;        // 读取FIFO的数据}OS_EXIT_CRITICAL();OSSemPost(Sem_SendFlag);          //发送发送信号量}

6.发送任务流程

l  等待发送信号量

l  发送数据

l  发送开始信号量

程序:

/************************************************************                            Task2(发送任务)**********************************************************/void Task2    (void *pdata){uint8 i,err;pdata = pdata;while(1){OSSemPend(Sem_SendFlag,0,&err);       //等待发送信号量for(i = 0;i < 8; i++)UART0_SendByte(rcv_buf[i]);    //通过轮训方式来发送串口数据OSSemPost(Sem_StartFlag);           //发送开始信号量}                   }

发送数据函数:

/*********************************************************** 名    称:            UART0_SendByte* 功    能:            向串口发送字节数据,并等待发送完毕。* 入口参数:            data              要发送的数据* 出口参数:            无**********************************************************/void   UART0_SendByte(uint8 data){U0THR = data;                while(0 == (U0LSR & 0x40));}

u 用消息队列接收数据的方式

1.    系统有那些任务组成

1>启动任务

2>接收任务(中调用一个接受处理函数)

3>接收中断服务例程

4>发送任务

2.    各任务之间的关系

3.启动任务流程:

l  定义各种通信工具(例如:信号量)

l  系统硬件初始化

l  初始化UART0

l  创建各个任务

l  创建各种通信工具

l  删除自己

程序:

/********************************************************************Task0(启动任务)********************************************************************/void Task0    (void *pdata){pdata = pdata;              TargetInit();                            //硬件初始化                                               UART0_Init(115200);                    //初始化串口Sem_SendFlag   =  OSSemCreate(0);     //创建发送信号量Sem_StartFlag  =  OSSemCreate(1);      //创建开始信号量ReMsg_Qeue = OSQCreate(&MsgGrp_Buf[0],10);    //创建消息队列OSTaskCreate(Task1,(void *)0, &TaskStk1[TaskStkLengh - 1],4); //创建接收任务OSTaskCreate(Task2,(void *)0, &TaskStk2[TaskStkLengh - 1],5); //创建发送任务OSTaskDel(OS_PRIO_SELF);                           //删除自己}

4.接收任务流程

l  等待开始信号量

l  处理接收数据

l  发送发送信号量

程序:

/**********************************************************************                            Task1(接收任务)********************************************************************/void Task1    (void *pdata){uint8 err;pdata = pdata;while(1){OSSemPend(Sem_StartFlag,0,&err);  //等待开始信号量UART0_RcvData(rcv_buf,2);        //接收数据OSSemPost(Sem_SendFlag);         //发送发送信号量}}

处理接收数据函数:

/********************************************************************* 名    称:           Rcv_Data* 功    能:           rcv_buf:接收中断返回后的数据   count :控制中断次数* 入口参数:           无* 出口参数:           无********************************************************************/void UART0_RcvData(uint8 *rcv_buf,uint8 count){uint8 i;uint8 j;uint32 rcv_data;uint8 err;for(j = 0;j < count;j++){//等待消息队列rcv_data = (uint32)(uint32 *)OSQPend(ReMsg_Qeue,0,&err);if(0x11223344 == rcv_data)                     {rcv_data = 0x12345678;}     //将每条消息分解为4字节,存入帧缓冲区for(i = 0;i < 4;i++){rcv_buf[4*j+3-i] = (uint8)(rcv_data&0xff);rcv_data >>= 8;}}}

5.串口中断接收流程:

l  关中断

l  清除串口中断标志位

l  清除中断控制寄存器

l  接收4字节数据拼装成32为地址

l  发送消息邮箱

l  开中断

程序:

/********************************************************************* 名    称:           UART0_Exception* 功    能:           串口接收中断* 入口参数:           无* 出口参数:      无********************************************************************/void  UART0_Exception(void){uint8 i;uint32 data;OS_ENTER_CRITICAL();data = U0IIR;                                                 //清除中断表示寄存器标志VICVectAddr = 0;                                       //清除中断for(i = 0;i < 4;i++){data = (data << 8) | U0RBR;        //将接受四字节数据拼装成32位地址}if(0x00000000 == data){data = 0x11223344;                 //防止00000000地址不能发送}OSQPost(ReMsg_Qeue,(void *)data);          //发送该地址到消息邮箱OS_EXIT_CRITICAL();}

6.发送任务流程

l  等待发送信号量

l  发送数据

l  发送开始信号量

程序:

/************************************************************                            Task2(发送任务)**********************************************************/void Task2    (void *pdata){uint8 i,err;pdata = pdata;while(1){OSSemPend(Sem_SendFlag,0,&err);       //等待发送信号量for(i = 0;i < 8; i++)UART0_SendByte(rcv_buf[i]);    //通过轮训方式来发送串口数据OSSemPost(Sem_StartFlag);           //发送开始信号量}                   }

发送数据函数:

/*********************************************************** 名    称:            UART0_SendByte* 功    能:            向串口发送字节数据,并等待发送完毕。* 入口参数:            data              要发送的数据* 出口参数:            无**********************************************************/void   UART0_SendByte(uint8 data){U0THR = data;                while(0 == (U0LSR & 0x40));}

UART0串口编程(六):串口(UART0)之UC/OS(二)UC/OS下的串口接收任务编程相关推荐

  1. Esp8266 进阶之路25【高级篇】深聊下esp8266的串口 Uart 通讯中断编程,为您准备好了 NONOS 版本 和 RTOS 系统的串口驱动文件。(附带Demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 序号 SDK版本 内容 链接 1 nonos2.0 搭建 ...

  2. UART0串口编程(五):串口编程(UART0)之UC/OS(一)UC/OS下的串口发送任务编程

    UART0串口编程(五) 串口编程(UART0)之UC/OS(一) 一.在UC/OS中设计串口程序所要考虑的问题 1.     串口通信数据以帧为单位进行处理,如果需要接收大量数据,则帧缓冲区规模必然 ...

  3. 串口通信协议和Linux下的串口编程

    一.串口通信介绍: 串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节,尽管比按位字节(byte)的并行通信慢,但是串口可以使用一根线发送数据的同时 ...

  4. linux下的串口编程

    本文转自:http://www.cnblogs.com/jason-lu/articles/3173988.html 做人个人学习使用,绝无侵权之意.如果侵权,请尽快联系,谢谢. Linux下串口编程 ...

  5. C语言串口编程收发数据 并实现AT指令的收发 可变参数控制串口属性 树莓派4G模块

    文章目录 一. Linux下串口编程的流程 1.打开串口 2. 串口初始化 2.1 常用函数总览 2.2 初始化 3. 串口的读写 4. 串口关闭 二.代码--串口编程实现自发自收 三.可变参数控制串 ...

  6. C——Linux下的串口编程

    原 C--Linux下的串口编程 2017年06月06日 19:30:50 C_Aya 阅读数:11537 <span class="tags-box artic-tag-box&qu ...

  7. 串口编程之三:VMware虚拟机下的串口调试

    Windows为宿主机,VMware虚拟机中安装了 Linux,也可以在 Linux 下编写程序对串口发送消息.原理同样是利用虚拟串口软件VSPM 将COM3与COM4连接后通过串口调试器捕获.下面会 ...

  8. windows下的串口编程,串口操作类封装

    以往都是在嵌入式设备中经常操作串口,或者使用QT的串口类.在Win32中处理串口也是有办法的,操作文件的打开和读写进行串口的操作.使用ReadFile.WriteFile函数. 基本步骤 使用Win3 ...

  9. asp.net下的串口编程

    最近,公司这边有几个新的项目即将启动!因为公司主要是做电力载波通信产品,诸如集中控制器,路灯控制器等.在应用软件这部分基本上就我一个人,其他相关文档还在整理中.应用软件部分,主要就是和集中控制器通信, ...

最新文章

  1. ACMMM2017 | 电子科大斩获最佳论文!中科院自动化所多媒体计算组获得IEEE期刊最佳论文!
  2. android点击textview后选择,android - 单击后,ClickableSpan TextView保持选中状态 - SO中文参考 - www.soinside.com...
  3. 【渝粤题库】广东开放大学 计算机网络 形成性考核
  4. python时间序列预测不连续怎么办_python – 不连续的时间序列在x轴上绘制日期
  5. 为QT的Webkit 编写插件
  6. CocoaPods打包静态库
  7. Java 工程师成神之路 | 2019正式版
  8. 使用django-admin 上传-下载 文件
  9. 利用SusuCMS快速创建网站(一)
  10. java抢红包_Java 用Redis 实现抢红包功能
  11. 使用redis碰到maxmemory
  12. 大数据技术原理与应用课后题(林子雨)
  13. vue---lodash的使用
  14. 如何通过photoshop制作保存*.ico的图标文件教程
  15. PV-RCNN: Point-Voxel Feature Set Abstraction for 3D Object Detection(group的是关键点周围的体素,而不是周围的点)
  16. Gensim学习笔记-1--理解corpora.Dictionary
  17. 历代名人、学者对商鞅的评价
  18. linux fprintf sprintf 函数
  19. docx 转换成html转pdf,python3将docx转换成pdf,html文件,pdf转doc文件
  20. 企业生产经营相关英文及缩写之(1)--供应链/物料控制

热门文章

  1. Oracle 数据表误删恢复 Flashback
  2. java对象 Java中 VO、 PO、DO、DTO、 BO、 QO、DAO、POJO的概念
  3. PopupWindow的使用
  4. 个人阅读作业Week7
  5. Tomcat启动报错 Could not reserve enough space for object heap
  6. 叹西安2014中秋节雨天
  7. 可拖拽的ImageButton
  8. NOIP 2017 d2t2 70points
  9. EIGRP协议邻居详解及故障实战分析
  10. SourceTree的基本使用