除了通信协议以外,设置数据缓冲区是完善不同速率,或不同系统之间通信的解决方案之一。本文设置了一个环形缓冲区,来接收PC上位机通过串口(COM口)发往STM32下位机的数据,具体代码如下:
//接受数据处理相关定义
#define RxSize 16 //接收缓冲区大小 u8 RxBuffer[RxSize]; //缓冲区定义 u8 RxPut = 0; //接收缓冲区(环形)的当前放人位置 u8 RxGet = 0; //接收缓冲区()的当前取出位置 u8 RxEff = 0; //接收缓冲区(环形)中的元素总数量
//利用去除存入缓冲区数据的冗余信息后,将有用数据存入命令缓存 u8 command[7]; //命令缓存,用于存放收到的命令(最长命令为五个字符,其中加上起始符和结尾符,共7个字符) u8 comm_length; //命令长度,命令解码时用
//接受缓冲区读取函数 u8 Address(u8); void put(u8 z); u8 get(void);
void decode(void);//解码程序 void get_command(u
//函数实现 /******************************************************************************* 环形缓冲区的地址编号计算函数,,如果到达唤醒缓冲区的尾部,将绕回到头部。 环形缓冲区的有效地址编号为:0到 RxSize
*******************************************************************************/ //接受缓冲区地址运算 u8 Address (u8 i) { return (i+1)==RxSize ? 0 : i+1; }
//从环形缓冲区中取一个元素 u8 get(void) { u8 pos; if (RxEff>0) { pos = RxGet; RxGet = Address(RxGet); RxEff--; return RxBuffer[pos]; } else return '~'; //标志缓冲区中的数据被读完
}
//向环形缓冲区中放人一个元素 void put(u8 z) { if (RxEff<RxSize) { RxBuffer[RxPut]=z; RxPut = Address(RxPut); RxEff++; } //else //; //若缓冲区为满,则放弃当前数据 }
//缓冲区的应用 /******************************************************************************* * Function Name : USART1_IRQHandler * Description : This function handles USART1 global interrupt request. * Input : None * Output : None * Return : None *******************************************************************************/ void USART1_IRQHandler(void) //利用串口中断,来填充缓冲区 {
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)//检查EXTI_Line3线路触发请求发生与否,若发生中断目前将不被执行(即保持原先各种操作) { u8 z; z=(u8)( USART_ReceiveData(USART1)& (u8)0xFF);
if(z == '%') //单字符命令处理函数 //联机状态软件控制部分 { para_send((u8)('%'),0); //同意联机 (此处SBUF为发送缓冲器:发送确认信号) while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);//等待发送完成 } else // C为除'%',其他字符(多字符命令处理函数)---先将命令存入缓冲区 { put(z); //字符送入缓冲区 }
/* Clear the USART_IT_RXNE pending bit */ // USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除EXTI线路挂起位,标志当前中断已经发生
} }
在main函数中的while循环中,读取缓冲区数据,并做相关响应 main(void) { #ifdef DEBUG debug(); #endif
/* 调用各外设配置函数,使外设处于工作状态 -----------------------------------*/ /* 写解调体统核心程序 -----------------------------------*/
while(1) { c = get(); //读缓冲区 get_command(c); //命令解析(数码管显示相应命令,并置stopflag以便于下属语句驱动电机) //根据解析代码实现电机运行相关参数设置 if(stopflag==1) //根据解析参数正常运行 { curPosition=GoSteps1(steps,direction,curPosition);
} //按指定方向,连续运行steps步 else if(stopflag==2) //复位代码(向右复位) { stepfm=curPosition - Osteps; curPosition=GoSteps1(stepfm,RIGHT,curPosition); } else if(stopflag==3) //复位代码(向左复位) { stepfm= Osteps-curPosition ; curPosition=GoSteps1(stepfm,LEFT,curPosition);
} else if(stopflag==4) //复位代码(不动) { curPosition=GoSteps1(0,RIGHT,curPosition); } else if(stopflag==5) //单步运行 { curPosition=GoSteps1(1,direction,curPosition); } } }
附录: void get_command(u {
if(c == '@')//命令字开始 { comm_length = 0; } else if(c == '$')//命令字结束 { decode();//执行解命令,对stopflag赋值 } else if((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')) { command[comm_length] = c; //指令字符放入命令缓存 comm_length++; }
else { //空语句 } } 【转自:http://bbs./BLOG_ARTICLE_269940.HTM】
|
|
来自: 昵称25698214 > 《stm32》