单片机数据接收缓冲流的设计与实现..doc

  1. 1、本文档共9页,可阅读全部内容。
  2. 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
单片机数据接收缓冲流的设计与实现.

由一个串口接收数据引发的问题与字节缓冲流系统的设计 在一个wifi数据收发项目调试时发现,数据在高速连续发送和接收时,经常出现数据出现了丢失和系统的死机。单片机在接收串口数据时,传统采用中断方法或者查询指定标志位方法接收数据。 查询指定标志位:这种方式通常在main函数的大循环中不断的检测标志位或者等待该标志位来判断是否有数据接收。通常有两种方式: 1:在大循环中 if(标志位成立)表明有数据接收 然后进行数据的处理。 优点: 不会引起整个main函数 线程的阻塞 ;在简单的数据接收项目中可以使用 缺点: 单片机一般都为单线程,复杂的控制中采用操作系统,例如UC/OS;所以,将所以都函数放在main函数大循环中进行轮番处理。整个循环周期时间不确定,其他任务函数可能发生阻塞,不能够保证数据到来时,正好在执行检测指定标志位,从而出现了数据丢失。 2:在大循环中 while(标志位);通过while来等待数据的到来。 优点:数据不会出现丢失,稳定。 缺点:整个main函数主线程出现堵塞,其他函数无法执行,上述所示。 显然:以上两种发送在复杂的控制系统中是不能采用的 ,因此:在没有多任务操作系统时,数据的接收采用中断接收的法式是最佳的。使用中断,可以不用查询和等待的方式接收数据,解决了许多问题。,此时,单片机可以说是多线程执行程序。main函数是一个线程,中断服务子程序是一个线程。中断是前台,main函数是后台。由于是多线程(一般而言),不得不考虑数据的安全性。中断可能随时到来。Main函数会随时被打断,程序计数器寄存器PC指针指向中断函数入口地址,指向中断函数。Main函数在处理数据时被打断,可能会引发数据的丢失。共同访问全局变量时,使用互斥信号量等一些手段保障数据不被修改。设计可能被中断打断的函数时,要注意函数的重入问题,像static等关键字。 字节接收缓冲系统设计的核心思想: 1:前台(即中断)负责接收数据,并不进行处理,将数据放入消息队列中。 2:后台(main函数)负责从消息队列中取出消息,并处理。 3:整个接收系统核心为 队列,可以当做缓冲区;遵循先进先出原则 FIFO 采用队列方式接收数据比较简单,并且实现了缓冲,不会出现数据的丢失。 消息队列核心算法实现: 1:消息队列核心数据结构: typedef struct Queue { unsigned char front; //队列头索引 unsigned char rear; //队列尾索引 unsigned char *pArray;//简易的队列 指向数组 }QueueTypeDef; 2: 判断队列是否为满伪算法 if( (rear + 1) % 数组的元素个数) == front) 3: 判断队列是否为空伪算法 if(rear == front) 4: 将数据加入队列伪算法 if( 队列不为满 ) { pArray[rear] = 数据; rear = (rear + 1) % 数组的长度 } 5: 将数据从队列中取出伪算法 if( 队列不为空) { Val = pArray[front]; front = (front + 1 ) % 数组长度 } 以上是接收最简单的一个字节的队列;ASCII C 编译通过 不依赖于单片机 ;将其加入中断服务子程序中,把接收的数据加入队列中;以stm32 单片机串口中断为例: void USART2_IRQHandler(void) { if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET) { USART_ClearITPendingBit(USART2,USART_IT_RXNE); en_queue(Queue,(uint8_t)USART_ReceiveData(USART2)); //将数据加入消息队列中 } if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET) { USART_ClearFlag(USART2,USART_FLAG_ORE); USART_ReceiveData(USART2); } } Main函数从消息队列中取出数据 unsigned char val; while(1) { if(out_queue(Queue, val)) //从队列中取出数据 { if(i == 16) i=0;

文档评论(0)

wuyuetian + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档