串口发送与接收

最近刚学ucos-II,想利用ucos-ii中的任务调度来实现数据包处理功能,数据包采用stm32串口收发。具体思路如下:

1、用串口1发送数据包,串口2接收。
2、滴答定时器判接收超时。
3、接收超时则进入数据处理任务。

先写串口部分。
发送数据包函数:

void USART1_Send_Message(u8 *SendData,u8 len)
{
  while(len--)
   {
     USART_SendData(USART1,*SendData++);
     while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)
   }
}

串口2接收中断:

u8 *RES;
void USART2_IRQHandler(void)
{
     if(USART_GetITStatus(USART2,USART_IT_RXNE))
     {
      *RES= USART_ReceiveData(USART2); 
      }
}

开始调试,断点打在中断函数第一个括号,发现进不了,查了半天才发现问题出在
这里写图片描述
错在时钟使能上,导致USART2无法接收数据。 改正后,断点打在中断能进去,但是运行完报硬件错误中断,把U8* res放进中断函数后,好了。原因不值,估计涉及野指针,明天补充。。。
接昨天内容,在能接受到字节数据后,断点打在接收中断函数,发现会漏数据,一开始以为是时钟或者中断优先级问题,后来将断点打在串口发送函数中,漏字节现象消失。

由于在具体项目中,串口接收中断基本不回去直接处理字节数据,而是等缓冲区满了之后再将数据存入内存。因此中断要修改成接收不定长数据包形式。

串口部分修改后如下:

void USART1_Send_Message(u8 *SendData,u8 len)
{
  while(len--)
  {  
      USART_ClearFlag(USART1, USART_FLAG_TC);
      USART_SendData(USART1, *SendData++);
      while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  }
    return;
}

void USART2_IRQHandler(void)
{
 u8 res;
 static u8 first_byte=0;         
 static u8 which_buff=0;          

 if(USART_GetITStatus(USART2,USART_IT_RXNE)) 
     {   
     switch(first_byte)               //接收到首字符
     {
     case  0:                          
                res= (u8)USART_ReceiveData(USART2);
                if(res==0x7A)        //首字符为0x7A     
                    {                             
                    if_start_systick=1;  //进入滴答定时器中断    
                    first_buff[usart_RecIndex++]=res;  
                    first_byte=1;      //非首字符标志     
                    data_comed=1;     //新数据标志,滴答定时器中断计数值清零     
                    return;
                    }
               break; 
     case  1:                    //接收到非首字符           
           data_comed=1;         //新数据标志,滴答定时器中断计数值清      
           if(USART_GetFlagStatus(USART2, USART_FLAG_ORE) != RESET)  
                 {
                    (void)USART_ReceiveData(USART2);//溢出
                    return;
                 }
          else
                 {
                switch(which_buff)  //选择接收数据存放数组          
                   {
                    case first_buff_flag:         
                    if(usart_RecIndex >= BUF_SIZE)//第一个数组满  
                        {
                        which_buff=second_buff_flag; 
                        OSSemPost(sem_dpacket);//申请信号量,进入任务处理
                        usart_RecIndex=0;    //字符位置清零
                        second_buff[usart_RecIndex++]=(u8)USART_ReceiveData(USART2);
                        }
                    else
                        {
                        first_buff[usart_RecIndex++]=(u8)USART_ReceiveData(USART2);
                        }
                    break;

                    case second_buff_flag:   //第二个数组
                    if(usart_RecIndex >= BUF_SIZE)//第二个数组满
                        {
                        which_buff=first_buff_flag;
                        OSSemPost(sem_dpacket);
                        usart_RecIndex=0;
                        first_buff[usart_RecIndex++]=(u8)USART_ReceiveData(USART2);
                        }
                        else
                        {
                        second_buff[usart_RecIndex++]=(u8)USART_ReceiveData(USART2);
                        }
                        break;

                        default :break;
                        }
                    }   
                break;
                default : break;
                }
          }
     }

滴答定时器判超时:

void SysTick_Handler(void)
{   
    static u8 tim_cnt=0;     //中断计数器
    if(delay_osrunning==1)                      
    {

        OSIntEnter();                           //½øÈëÖжÏ
        OSTimeTick();                           //µ÷ÓÃucosµÄʱÖÓ·þÎñ³ÌÐò      
        if(if_start_systick) //若接收到有效数据 
        {   
            if(tim_cnt>=30)   //无数据时长达到30x5=150ms,认为此次接收完成
            {
                tim_cnt=0;
                if_start_systick=0; 
                OSSemPost(sem_dpacket);  //进入任务处理        
            }
            else
            {
                if(data_comed==1)   //5ms内有新数据
                {
                    tim_cnt=0;      //计数器清零
                    data_comed=0;   //标志清零
                }
                else
                {
                    tim_cnt++;   //5ms内无新数据
                }
            }
      }
        OSIntExit();            
    }

    return;
}

任务处理函数处理数据包:

//此任务未做数据处理,简单将接受数组中的数据取出并在LCD显示
void dpacket_task(void *pdata)
{ 
    u8 err;
    u8 i;
    u8 x_loc;
     while(1)
    {
        OSSemPend(sem_dpacket,0,&err);
        if(usart_RecIndex==sizeof(buf))
        {
       memcpy(packetdata,first_buff,usart_RecIndex);
             for(i=0;i<=usart_RecIndex-1;i++)
             {
                 x_loc=20*i+10;
                 LCD_ShowxNum(x_loc,140,(u16)first_buff[i],3,16,1);
             }          
        }       
    }           
}

注:此任务没有长数据包进行验证。

展开阅读全文

没有更多推荐了,返回首页