原创 基于STM32芯片环形缓冲区的构建(IAR EWARM环境)

2009-10-8 20:57 5771 5 6 分类: MCU/ 嵌入式

除了通信协议以外,设置数据缓冲区是完善不同速率,或不同系统之间通信的解决方案之一。本文设置了一个环形缓冲区,来接收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


       {


                       //空语句


       }


}

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户131114 2009-10-11 08:32

环形fifo的最简单形式,不过没有考虑多任务的情况下加上保护

tengjingshu_112148725 2009-5-18 18:04

我也是经常遇到这个错误
相关推荐阅读
用户187843 2009-10-08 13:58
用 STM32 来驱动ZLG7289(多键盘数码管驱动芯片)
利用STM32来驱动ZLG7289(最多驱动8位数码管,64个独立键盘),驱动代码如下:<?xml:namespace prefix = o ns = "urn:schemas-microsof...
用户187843 2009-10-08 13:44
STM32芯片的时钟和端口配置
对STM32进行软件开发时,最基本的就是对STM32芯片进行时钟和端口配置,然后是对项目所用到的片上资源进行配置并驱动,下面给出时钟和端口配置代码,该代码几乎涵盖了片上所有时钟和端口配置项目,可根据自...
用户187843 2009-10-08 13:19
电子类专业课程 中英问对照
https://static.assets-stash.eet-china.com/album/old-resources/2009/10/8/cce31911-8444-4259-a1b8-84aa...
用户187843 2009-10-08 12:52
vc++ 串口开发代码
应用程序中串口相关代码摘录如下:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> v...
用户187843 2009-10-08 12:37
VC++应用程序中 一种全局变量的实现方式
这是应用程序的公有数据类部分,变量的名具有针对性,若需要基于这个方式构造你所需要的公有类,将变量名或函数名替换即可。<?xml:namespace prefix = o ns = "urn:sc...
EE直播间
更多
我要评论
1
5
关闭 站长推荐上一条 /3 下一条