除了通信协议以外,设置数据缓冲区是完善不同速率,或不同系统之间通信的解决方案之一。本文设置了一个环形缓冲区,来接收PC上位机通过串口(COM口)发往STM32下位机的数据,具体代码如下:
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
//接受数据处理相关定义
#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<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />8 c); //识别命令格式,并存入命令缓冲区
//函数实现
/*******************************************************************************
环形缓冲区的地址编号计算函数,,如果到达唤醒缓冲区的尾部,将绕回到头部。
环形缓冲区的有效地址编号为: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(u8 c) //识别命令格式,并存入命令缓冲区command[comm_length]
{
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
{
//空语句
}
}
用户131114 2009-10-11 08:32
tengjingshu_112148725 2009-5-18 18:04