单片机数据接收缓冲流的设计与实现.doc_第1页
单片机数据接收缓冲流的设计与实现.doc_第2页
单片机数据接收缓冲流的设计与实现.doc_第3页
单片机数据接收缓冲流的设计与实现.doc_第4页
单片机数据接收缓冲流的设计与实现.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

由一个串口接收数据引发的问题与字节缓冲流系统的设计在一个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 Queueunsigned char front; /队列头索引unsigned char rear; /队列尾索引unsigned char *pArray;/简易的队列 指向数组 QueueTypeDef; 2: 判断队列是否为满伪算法if( (rear + 1) % 数组的元素个数) = front) 3: 判断队列是否为空伪算法if(rear = front) 4: 将数据加入队列伪算法if( 队列不为满 )pArrayrear = 数据;rear = (rear + 1) % 数组的长度 5: 将数据从队列中取出伪算法if( 队列不为空)Val = pArrayfront; 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;LCD_print(1,i,val); /显示取出的数据i+;./其他任务 .以上算法思路是以接收最简单的一个字节为例:当然可以接收更复杂的数据,数据结构如下typedef struct Message /消息数据结构 u8 clientID; /客户端名u8 messgeLength; /消息长度 u8 message_strMessageSize; /存放消息的数组MessageTypeDef;typedef struct Queue /消息队列 数据结构 u8 front; /队列头 u8 rear;/队列尾 + 1 MessageTypeDef messageMessQueueSize; /消息 BOOL (*postMessage)(MessageTypeDef dat ); /消息进列 BOOL (*getMessage)(MessageTypeDef * datAddr);/消息出列 MessQueue;MessageTypeDef;这个数据结构中 构造了接收数据的格式 并不是前面最简单的一个字节,根据实际接收数据的需要来构造数据结构,当然在中断函数中要进行数据的处理,也可以放在主函数中处理数据,中断中依然是将字节放入消息队列中。主函数处理完数据后在放入另一个消息队列中,由其他函数处理数据,多级消息队列。以下是带特定格式的消息数据处理:buffbuff_index = USART_ReceiveData(USART2);/将接收的数据(1个字节)放入缓冲区/if(buff0 = 0x2B) /校验数据头/buff_index+;/else/buff_index = 0;/if(buff_index = 8) /获取数据尾/length = (buff7 - 0x30) + 1 + buff_index; / 计算数据尾索引/if(buff_index = length)/ length = 200; /buff_index = 0;/receive = TRUE; /数据接收完成/DISABLE_WIFI_RX_IRQ(); /附: 字节缓冲流系统源码:文件 : queue.h#ifndef _QUEUE_H_#define _QUEUE_H_#ifndef bool#define bool unsigned char#define true 1#define false 0#endif#define QueueArraySize32 /队列长度 (字节) typedef struct Queueunsigned char front; /队列头 unsigned char rear; /队列尾+1 unsigned char *pArray; /指向字节数组 QueueTypeDef;extern QueueTypeDef Queue;extern unsigned char queueArrayQueueArraySize; void queue_Init(QueueTypeDef *pQ, unsigned char *array); /初始化 bool full_queue(QueueTypeDef *pQ); /满 bool emput_queue(QueueTypeDef *pQ); /空 bool en_queue(QueueTypeDef *pQ, unsigned char val); /入队列bool out_queue(QueueTypeDef *pQ, unsigned char *dat); /出队列#endif文件:queue.c#include queue.hQueueTypeDef Queue;unsigned char queueArrayQueueArraySize; void queue_Init(QueueTypeDef *pQ, unsigned char *array)Queue.front;Queue.rear;pQ-pArray = array;pQ-front = 0;pQ-rear = 0;bool full_queue(QueueTypeDef *pQ)if(pQ-rear + 1) % QueueArraySize = pQ-front)return true;elsereturn false; bool emput_queue(QueueTypeDef *pQ)if(pQ-front = pQ-rear)return true;elsereturn false;bool en_queue(QueueTypeDef *pQ, unsigned char val)if(full_queue(pQ)return false;else*(pQ-pArray)+(pQ-rear) = val;/pQ-pArraypQ-rear = val;pQ-rear = (pQ-rear + 1) % QueueArraySize;return true;bool out_queue(QueueTypeDef *pQ, unsigned char *dat)if(emput_queue(pQ)return false;else*dat = pQ-pArraypQ-front;pQ-front = (pQ-front + 1) % QueueArraySize;return true;附:复杂数据接收缓冲流实现1:文件:queue.h#ifndef _QUEUE_H_#define _QUEUE_H_#ifndef BOOL#define BOOLunsigned char#define TRUE1#define FALSE0#endif#define MessageSize10 /消息长度 (字节) #define MessQueueSize20 /队列长度 sizeof( MessageTypeDef)typedef unsigned char u8;typedef unsigned int u16;typedef struct Message /消息数据结构 u8 clientID; /客户端名u8 messgeLength; /消息长度 u8 message_strMessageSize; /存放消息的数组MessageTypeDef;typedef struct Queue /消息队列 数据结构 u8 front; /队列头 u8 rear;/队列尾 + 1 MessageTypeDef messageMessQueueSize; /消息 BOOL (*postMessage)(MessageTypeDef dat ); /消息进列 BOOL (*getMessage)(MessageTypeDef * datAddr);/消息出列 MessQueue; extern MessQueue mess_queue; void MessageQueueInit(void); /初始化 BOOL full_queue(void) ;/判断是否为满 BOOL emput_queue(void);/判断是否为空 BOOL en_queue(MessageTypeDef message) ;/入列 BOOL out_queue(MessageTypeDef *message); /出列 #endif2:文件:queue.c#include queue1.hMessQueue mess_queue; /定义消息队列 void MessageQueueInit(void) /初始化 mess_queue.front = 0;mess_queue.rear = 0;mess_queue.postMessage = en_queue;mess_queue.getMessage = out_queue;BOOL full_queue(void) /判断队列是否为满 if( (mess_queue.rear + 1) % MessQueueSize = mess_queue.front ) / rear + 1 = front return TRUE;elsereturn FALSE; BOOL emput_queue(void) /判断队列是否为空 if(mess_queue.front = mess_queue.rear) /front = rearreturn TRUE;elsereturn FALSE; BOOL en_queue(MessageTypeDef message) /入列 if(full_queue() /判断队列是否为满 return FALSE;elseu8 i = 0;(&(mess_queue.messagemess_queue.rear)-clientID = message.clientID;(&(mess_queue.messagemess_queue.rear)-

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论