个人笔记,主要内容均来自原文

一个例子来说明 RTOS 的好处。

假设编一个串行通信程序,通信协议为:数据包长度为 NBYTE,起始字节为 STARTBYTE1、STARTBYTE2,最后一个字节为校验和,中间不可能连续出现 STARTBYTE1、STARTBYTE2。

文章目录

  • 第一种方法——在中断中处理协议
  • 第二种方法——使用队列
  • 第三种方法——使用 Small RTOS51
  • 三种方法的比较

第一种方法——在中断中处理协议

原文示例代码:【代码注释为个人理解,仅供参考】

unsigned char Buf[NBYTE - 2];  // NBYTE 为包的最大字节数,除去包头
bit GetRight = 0;// 串行中断
void comm(void) interrupt 4
{static unsigned char Sum, Flag = 0, i;unsigned char temp;if(R1 == 1){R1 = 0;  temp = SBUF;  // 获取串口数据swtich(Flag){case 0:  // 状态0:开始接收并处理串口协议if(temp == STARTBYTE1)  //接收到的数据为包头第一个字节{Flag = 1;  // 进入下一状态}break;case 1:  // 状态1:接收包头第二个字节if(temp == STARTBYTE2)  // 如果是目标字节{Sum = STARTBYTE1 + STARTBYTE2;  // 更新数据包的和i = 0;  // "清空"串口接收数组Flag = 2;  // 进入下一状态break;}  if(temp == STARTBYTE1)  // 如果依然收到的是包头第一个字节,保持当前的状态break;Flag = 0;  // 如果接收到的数据不是包头数据,直接返回到状态0break;case 2:  // 状态2:开始接收数据(非包头)if(temp == STARTBYTE1)  // 如果接收到包头第一个字节(丢弃之前接收到的数据){Flag = 3;  // 进入下一状态break;}Sum += temp;  // 更新校验和if(i >= (NBYTE -3) && Sum == 0)  // 如果接收到的是数据包最后一个字节(校验值),同时判断校验和是否为0,{GetRight = 1;  // 表示数据包处理完毕Flag = 0;  // 状态复位break;}Buf[i++] = temp;  // 如果接收到的不是校验值也不是包头数据,则将其存入串口接收数组break;case 3:  // 状态3:在状态2时接收到包头后才会进入此状态if(temp == STARTBYTE2)  // 接收到包头第二个字节{Sum = STARTBYTE1 + STARTBYTE2;  // 计算校验和Flag = 2;  // 进入状态2i = 0;  // "清空"串口接收数组break;}Sum += STARTBYTE1; // 如果上一个数据并不是包头,而是校验值(凑巧相等),则计算校验和if((i >= (NBYTE - 3)) && Sum == 0)  // 如果上一个接收的数据是数据包的最后一个字节,且校验和为0{GetRight=1;  // 表示数据包处理完毕Flag=0;  // 状态复位break;}}}
}

通过串口中断这种方式处理串口协议,是比较直观和简单的一种处理方式,初学者(比如我)最先想到的就是这种方法了,直接在串口中断完成全部操作。

第二种方法——使用队列

原文示例代码(原代码有些地方我不太理解,自己改了一点):【代码注释为个人理解,仅供参考】

// 串口中断中只完成数据入列
void comm(void) interrupt 4
{if(R1 == 1){R1 = 0;SBUF 入队;}
}unsigned char Buf[NBYTE - 2];  // 串口接收数组,协议最大字节为 NBYTE(包括两个包头字节)//串口处理函数,放在 main() 函数 while 循环的任意位置
unsigned char ReadSerial(unsigned char *cp)
{unsigned char i;unsigned char temp, Sum;temp = 队列中数据个数;if(temp < (NBYTE)) // 还没接收完成(一个数据包)return 0;出队 temp;  // 从队列中取出一个字节if(temp != STARTBYTE1)  // 判断是否为队列首字节return 0;出队 temp;  // 从队列中取出一个字节if(temp != STARTBYTE2)  // 判断是否为队列次首字节return 0;出队 temp;Sum = STARTBYTE1 + STARTBYTE2;  // 首字节的校验和for(i = 0; i < NBYTE - 3; i++)  {出队 temp;*cp++= temp;  // 将出队的数据存入串口缓存数组Sum += temp;  // 计算校验和}出队 temp;  // 取出校验值Sum += temp;if(Sum != 0)  // 校验不通过return 0;return 1;  // 成功返回1
}

队列的方法可以降低中断执行时间,提高系统实时性。

第三种方法——使用 Small RTOS51

原文示例代码:【代码注释为个人理解,仅供参考】

// 串口中断中只完成数据入列
void comm(void) interrupt 4
{OS_INT_ENTER();  // 进入临界区if(R1 == 1){R1 = 0;OSIntSendSignal(RECIVE_TASK_ID);  // 发送一个信号(表示接收到的串口数据)}OSIntExit();  // 退出临界区
}void Receive(void)
{unsigned char temp, temp1, Sum, i;OSWait(K_SIG, 0);  // 等待串口中断发送信号temp = SBUF;  // 读取串口数据while(1){while(1){OSWait(K_SIG, 0)  // 等待串口中断发送信号temp1 = SUBF;  // 读取串口数据if((temp == STARTBYTE1) && (temp1 == STARTBYTE2)) // 判断包头数据break;temp = temp1;}Sum = STARTBYTE1 + STARTBYTE2;  // 计算校验和OSWait(K_SIG, 0);  // 等待串口中断发送信号temp = SBUF;  // 读取串口数据,存入 tmepfor(i = 0; i < NBYTE - 3; i++){OSWait(K_SIG, 0);temp1 = SBUF;  // 读取串口数据,存入 temp1if((temp == STARTBYTE1) && (temp1 == STARTBYTE2)){OSWait(K_SIG, 0)temp = SBUF;i = -1;  // 重新开始循环Sum = STARTBYTE1 + STARTBYTE2;continue;}Buf[i] = temp;  // 将 temp 存入串口接收数组Sum += temp;  // 更新校验和temp = temp1;  // 保存 temp1,下个循环再处理}Sum += temp1;  // 加上校验值,获取校验和if(Sum == 0)OSSendSignal(GET_RIGHT_TASK_ID);  // 串口命令处理完成,发送指定信号。}
}

引入操作系统,那肯定是为了方便任务调度和提高系统实时性,也就是能在处理其他事情的同时,处理串口接收功能。

三种方法的比较

以下内容参考原文

  1. 从可读性和编程容易性:第三种最简单易读,第二种次之(要写队列函数),第一种最差。
  2. 从 RAM 占用方面:第二种占用最大(有队列),第三种较小,第一种最小。
  3. 从中断执行时间方面:第三种最长(不太理解,进出临界区要很长时间?),第一种较长,第二种最短。
  4. 从功能方面看:第三种功能最强(还可以升级,实现超时处理)

如果串口数据发送得太快,第一种方法和第三种方法都会丢弃以前的数据,第二种方法则丢弃后面收到的数据。而且由于第二种方法是先获取整个包,所以在处理一个数据包期间(出现丢包)无法继续处理下一个包,也就是数据处理和接收时串行的关系,而第一种方法和第三种方法数据接收和处理为并行关系。

RTOS 使得实时应用程序的设计和扩展变得容易,不需要大的改动就可以增加新的功能。通过应用程序吧设计分割为若干独立的任务,RTOS 使得应用程序的设计过程大为简化。

Small RTOS51 学习笔记(1)使用 RTOS 的好处相关推荐

  1. RTOS学习笔记--时间片调度

    RTOS学习笔记–时间片调度 本文基于正点原子RTOS开发指南,笔记自用,获取详细信息请关注正点原子官方账号 介绍:在RTOS中,除了按优先级调度之外,还可以按照时间片调度,也就是给每个任务分配一个时 ...

  2. RTOS学习笔记--FreeRTOS的列表和列表项

    RTOS学习笔记–FreeRTOS的列表和列表项 本文基于正点原子RTOS开发指南,笔记自用,获取详细信息请关注正点原子官方账号 列表和列表项的简介 列表是 FreeRTOS 中的一个数据结构,概念上 ...

  3. 学习笔记--RTOS信号量

    学习笔记–RTOS信号量 本文基于正点原子RTOS开发指南,笔记自用,获取详细信息请关注正点原子官方账号 简介:信号量是一种解决同步问题的机制,可以实现对共享资源的有序访问.和linux中的信号量差不 ...

  4. RTOS学习笔记--RTOS系统介绍

    RTOS学习笔记–RTOS介绍 本文基于正点原子RTOS开发指南,笔记自用,获取详细信息请关注正点原子官方账号 RTOS特点:RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时 ...

  5. freeRtos学习笔记 (9) 移植和CPU利用率统计

    freeRtos学习笔记 (9) 移植和CPU利用率统计 使用官方固件移植 首先准备一个能跑的裸机工程 注意,freertos需要使用systick定时器,而stm32HAL库默认使用systick作 ...

  6. C# 学习笔记(9)线程

    C# 学习笔记(9)线程 本文参考博客 C#多线程 https://www.cnblogs.com/dotnet261010/p/6159984.html C# 线程与进程 https://www.c ...

  7. freeRtos学习笔记 (5)事件组

    freeRtos学习笔记 freeRtos事件组 为什么要用事件组? 多任务环境下, 任务.中断之间往往需要同步操作,一个事件发生会告知等待中的任 务,即形成一个任务与任务.中断与任务间的同步.事件可 ...

  8. LIteOS学习笔记-7LiteOS启动流程与编译流程

    LIteOS学习笔记-7LiteOS启动流程与编译流程 LiteOS启动流程 1. 启动方式 2. 启动流程 硬件初始化 内核初始化 调试串口初始化 尝试进行网络连接 启动任务调度 LiteOS编译流 ...

  9. small rtos51学习资料收集

    small rtos51学习资料收集 虽然说small rtos51可能是最简单的操作系统,是学习操作系统最容易入门的,但是,还是有一定难度. 对于一个只学会了51单片机简单开发的工程师来说,也许会熟 ...

最新文章

  1. 关于智能车竞赛总结 | 山东大学(威海) - 山魂五队
  2. 应该增加黑样本还是白样本呢
  3. Flask之threading.loacl方法
  4. Vue 进阶 (二)
  5. git菜单形式的_Idea:Git的常用菜单操作和常用命令
  6. linux把root用户删了,linux root用户没法删除文件
  7. 从控制台读取password - C#
  8. web前端之JavaScript高级程序设计六:事件
  9. 华为HCIE云计算培训笔记第3天
  10. 【网络编程】传输层重点协议详解(UPD+TCP)
  11. 狼派CIY68客制化组装
  12. 最新版2020.11版本Anaconda百度网盘提取下载
  13. html+JavaScript 实现贪吃蛇程序
  14. python3 selenium模块Chrome设置代理ip的实现
  15. dell710服务器.维护,DellR710硬件及维护手册.pdf
  16. (转)被讨厌的勇气--目录
  17. micropython驱动lcd触摸屏_Micropython之萝卜狗远程门禁控制系统
  18. moocpython程序设计答案_中国大学MOOC免费答案_Python程序设计答案第七章节答案
  19. ARM 汇编的操作 设置CPU寄存器BASEPRI
  20. 戴尔7040linux改装win7,戴尔OptiPlex 3060台式机win10改win7系统(完美支持usb)

热门文章

  1. E+H流量计之Proline Promass F 300 科氏力质量流量计概述
  2. 手写帝国之崛起 -- Unity游戏开发篇(总述)
  3. 什么是半导体,半导体包括哪些
  4. 读书清单(2011/01 - 2011/12)
  5. Day010---java中的字符串处理,字符串格式化及日期格式化。
  6. unity shader 颜色混合渐变
  7. 我在她心中到底是什么呢?
  8. HTTP数据请求的方式:fetch与ajax(XMLHttpRequest)与axios
  9. 爬虫(5)-- 动态网页下载
  10. swing-基础Layout布局