串口收发处理——编程方法(原创)
2016-02-29 18:09
190 查看
对于通信相关代码编程,保证 及时、稳定、处理效率高,是很关键的。所以通常采用中断接收方式,并且中断处理函数尽量简短。 然而在我的工作中看到些:在中断中做很多工作,比如处理包的错误处理,解析,最终又将正确的有用信息拷贝到全局变量中,甚至还处理其他应用层的东西。 其实这样对于裸跑的mcu来说,main中的主循环就不高效了。 下面代码,将只对串口接收处理接收操作哦,在main的主循环去解析接收的内容; comm_deal() 中以状态机的方式处理:等待接收(包头判断)、接收中(长度符合或有包尾、加接收超时)、接收处理(对包的正确性判断,以及应用处理、错误提示等);这样看是不是方便、高效很多呢!而且逻辑清晰! 对于包长固定的通讯格式,可以从接收长度上判断有没有收发完成;而对于多种格式的数据包结构,往往还是加个接收超时 T_WAST 判断较好(虽然这要求发送短包之间的间隔 T_WAST至少) 其实发送也可以采用中断的发送: 开启发送中断,讲发送内容放在buff_send[]中,在发送第一个字节。再跳到中断,在中断中发送其他内容。
#define MAX_CHAR_NUM 1064 struct USART{ volatile unsigned short haveAcceptedLen;//接收字符数 unsigned short conIndex;//消费指针 unsigned short proIndex;//生产指针 unsigned long acceptTimer; unsigned long readTimer; unsigned char bufOverErr; unsigned char acceptBuf[MAX_CHAR_NUM]; }; extern struct USART m1USART;//串口1的结构 /*------------------------ brif:从接收缓存内读取一个字节 input: none output: none --------------------------*/ struct USART m1USART;//串口的结构 unsigned char UartROneData(USART_TypeDef* USARTx,struct USART* pUSART ) { unsigned char val; val=pUSART->acceptBuf[pUSART->conIndex]; pUSART->conIndex =(pUSART->conIndex+1)%(MAX_CHAR_NUM); /* Disable the USART0 Receive interrupt */ USART_ITConfig(USARTx, USART_IT_RXNE, DISABLE); pUSART->haveAcceptedLen =pUSART->haveAcceptedLen -1; /* ENABLE the USART0 Receive interrupt */ USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); return val; } unsigned char UartRData(USART_TypeDef* USARTx ,struct USART* pUSART,unsigned char *mRBuf,unsigned short needRNum)// unsigned char needRNum { unsigned short rlen; pUSART->readTimer = Tick_1ms; rlen = 0; while(1) { if(pUSART->haveAcceptedLen) { *(mRBuf+rlen) =UartROneData(USARTx,pUSART); rlen++; if(rlen>=needRNum) break; } if((Tick_1ms-pUSART->readTimer)>100) {//超时,发送超时错误 return 1;//err } } return 0; } void UART_ClearRxBuf(struct USART *pUSART) { pUSART->haveAcceptedLen=0; pUSART->proIndex=0; pUSART->conIndex=0; } /** * @brief This function handles USART1 interrupt request. * @param None * @retval None */ void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_RXNE); m1USART.acceptBuf[m1USART.proIndex] = (uint8_t)USART_ReceiveData(USART1); m1USART.proIndex =(m1USART.proIndex+1)%MAX_CHAR_NUM; m1USART.haveAcceptedLen = m1USART.haveAcceptedLen+1; if(m1USART.haveAcceptedLen> MAX_CHAR_NUM) { m1USART.bufOverErr = 1; m1USART.haveAcceptedLen = 0; m1USART.conIndex = m1USART.proIndex; } m1USART.acceptTimer=Tick_1ms; } } /************应用部分 main.c*************/ KeyData g_keydatabuf[MAX_KEY_NUM]={0}; u8 CMD_status=CMD_WAIT; u32 CMD_delay; u8 bufData[MAX_CHAR_NUM];// 用于中转 u16 g_len; void comm_deal(void) { u16 i; u8 n,cmd1,cmd2; u16 sum; u16 tmp16; u8 pool[4]={0}; char Pstr[6]="\0"; switch(CMD_status) { case CMD_WAIT: if(m1USART.haveAcceptedLen>=2) { cmd1=UartROneData(USART1, &m1USART); cmd2=UartROneData(USART1, &m1USART); if(cmd1==HEAD1&&cmd2==HEAD2) { CMD_status=CMD_RECV; CMD_delay=Tick_1ms; //? Usart1_SendByte(0xDD); } else { UART_ClearRxBuf( &m1USART); //? Usart1_SendByte(0xEE); } } break; case CMD_RECV: if((m1USART.haveAcceptedLen+2)>=4) { g_len=m1USART.acceptBuf[m1USART.conIndex+1];//高8bit g_len=(g_len<<8)+m1USART.acceptBuf[m1USART.conIndex];//低8bit if((m1USART.haveAcceptedLen+2)>=g_len) { UartRData(USART1, &m1USART, bufData, g_len-2);//从包长度开始读取 CMD_status=CMD_DEAL; } } else if(Tick_1ms-m1USART.acceptTimer>150)//超过50Ms, 没有接收,清空重新接收 { UART_ClearRxBuf( &m1USART); CMD_status=CMD_WAIT; //? Usart1_SendByte(0xAA); } break; case CMD_DEAL: sum = GetSum(bufData,(g_len-4)); sum=0xFFFF-(sum + HEAD1 +HEAD2); tmp16 = (bufData[g_len-3]<<8) + bufData[g_len-4]; if(sum==tmp16)//校验和正确 { switch(bufData[2]) { case CMD_READ: //? Usart1_SendByte(0xBB); break; case CMD_SET: //? Usart1_SendByte(0xCC); setting_save(); break; case CMD_ERR://错误码, 表示上控收到错误的下控包 if(bufData[3]==E_CMD)//下控发送包错误 { //? Usart1_SendByte(0xEF); my_memset(pool, 0, 4); setting_sendback(CMD_READ, (u8 *)pool, 4); } else ; break; default: break; } } else//校验和错误,上控包错误 { //? Usart1_SendByte(0xED); my_memset(pool, 0, 4); setting_sendback(CMD_ERR, (u8 *)pool, 4); } UART_ClearRxBuf(&m1USART); CMD_status=CMD_WAIT; break; } }
相关文章推荐
- Java数组之间的互相转换
- C语言指针
- tftpd32 工具中的 dhcp tftp 使用说明
- Java HashMap的工作原理和实现
- C++多态与指针的强制转换
- 为什么学C++比C#的长期风险低
- laravel5.0 升级到 laravel5.1
- Windows英文版GitHub客户端使用操作流程图文攻略教程现没中文版
- python Json模块
- java并发
- Java集合:Vector使用详解及源码分析
- Java自定义的类加载器
- 2012年第三届蓝桥杯C/C++省赛 微生物增殖
- Spring Data JPA教程:审计(一)
- Java中字符流的主要操作归纳
- java 文件读取
- c++类的隐式转换与强制转换重载详解
- pp看书笔记---C#高级编程第九版 第九章 【字符串和正则表达式】
- Windows server 08R2 IIS7 创建FTP 包括ftp的账号密码设置
- 向已知信号添加噪声——matlab仿真