这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » UART串口通信问题

共8条 1/1 1 跳转至

UART串口通信问题

菜鸟
2008-07-31 09:58:17     打赏
UART串口通信,我用中断读取的方式一串连续的数据,系统RESET后这串数据能收到,但是第二串时,U0RBH 为0x90,提示产生上溢错误。请问,这个错误是怎么产生的,(这个错误是不是,U0RB寄存器有数据但没有读取,第二个数据又接收完成了,而产生的),应该怎么样去避免,有错误后只能清除错误标志才能正常读取数据吗?



关键词: 串口     通信     问题    

菜鸟
2008-07-31 11:29:16     打赏
2楼

每次用16位变量读取UiRB。只有这样才能清除高位的标志。
下面是读数的中断程序:
#pragma interrupt UART0Recv
VOID    UART0Recv( )
{
     SINT16 temp_data;
     temp_data = u0rb;
     if ( temp_data < 0 )   //总错误标志为1
     {
           //错误处理,如果有
     }
     else
     {
          dataBuf0[buf0Ptr] = (UINT8) temp_data;
          buf0Ptr ++;
          if(buf0Ptr > MAX_DATA_NUM)
          {
                 buf0Ptr = 0;
          }
     }
}


菜鸟
2008-07-31 13:42:17     打赏
3楼

谢谢回复!
我有程序也是按你上面写的,
void INT_Receive_UART0(void)
{
  unsigned short tempdata;

  tempdata = u0rb;
  if (sum_u0rb==0)   
     {
  Rece_UART0[Rece_Count] = tempdata;
  if (Rece_UART0[Rece_Count]==BT_LF)  //end flag
     {
      if (Rece_Count > 2){
    Rece_Count = 0;
    return;
   }
  } 
  Rece_Count++;
     if (Rece_Count > BT_RECV_MAXLENGTH){
        Rece_Count = 0; 
  }           
   }else{  //clear flag
        Rece_Count = 0;       
     re_u0c1=0;
     _Wait4NOP;
     re_u0c1=1;
   }         
}
上面的错误处理,要re_u0c1=0,才能清除,这样操作对串口接收有没有影响。
一般是怎么清除错误标志的


菜鸟
2008-07-31 14:52:07     打赏
4楼

你说的不错,部分错误标志(总错误标志和溢出错误标志)的确只能通过初始化串口(SiMR = 0x00或者RE_UiC1 = 0)来清除。但是格式错误和校验错误通过读高8位就行了。
但是在你这里,是溢出错误0x90XX,对吧?

一般溢出错误主要是由于MCU的速度较慢造成的。
看看你的CPU时钟(不是主时钟)和UART的波特率的比值。
UART 的波特率 = fn/16/UiBRG,如果CPU和UART都使用同样的时钟源,比如f1,也就是说在两个连续的数据中,CPU只能执行10 x 16 x (UiBRG + 1)条指令(汇编级的单周期连续指令)。虽然你采用了中断,但是进入中断和退出中断都需要花时间。

建议如下:
一、使用高速中断(如果允许中断嵌套的话,只能对一个中断函使用
        #pragma interrupt /B UART1Recv
        "/B"表示在中断中使用另一组寄存器,而不压栈保存,差不多能比不使用"/B"的中断节省32个周期。

二、简化你的中断程序
        在外面来判断

三、由于你的数据串是连续的,可以考虑一下方案,第一个数据使用中断,随后的使用查询直至收满一包。
VOID    UART1Recv( )
{
    int temp_data;
    int time_out = 10000; //设定超时
    temp_data = u0rb;      //第一个数
    if (temp_data >= 0)     //接受正确
    {
         Rece_UART0[0] = (char)temp_data;
         while((char)temp_data != BT_LF) //如果不是数据包结尾
         {
             if(ri_u0c1)   //如果有新数据
             {
                   temp_data = u0rb;      //收一个数
                   if (temp_data < 0)
                   {
                         break; //接收错误
                   }
                   else
                   {
                         Rece_UART0[Rece_Count] = (char)temp_data;
                         Rece_Count ++
                         time_out = 10000; //重新设定超时
                         if(Rece_Count > BT_RECV_MAXLENGTH)
                         {
                                 break; //接收buffer已经满了,但是还没有收到结束码
                         }
                   }
             }
             //超时判定
             if(time_out > 0)
             {
                  time_out --;
             }
             else
             {
                 break; //超时
             }
         }
         //接受完成或者错误
         re_u0c1 = 0; //关闭接受,以清除标志
         ir_s0ic = 0;    //清除中断标志
         Rece_Count = 1; //第一个数是直接写的Rece_UART0[0],所以是从1开始
         re_u0c1 = 1; //重新允许接受
     }
}
 
       


菜鸟
2008-07-31 15:12:13     打赏
5楼
非常感谢你详细的分细,我的见意很好。
上面说的溢出错误应该是在其它的中断处里时,而产生的。

高工
2012-02-17 10:07:58     打赏
6楼
我也一直用/B在中断中

菜鸟
2012-02-18 21:11:26     打赏
7楼
这是哪款单片机的的寄存器啊?

院士
2012-02-19 11:10:41     打赏
8楼
我居然还没有遇到过这样的错误。
楼主的情况是如何发生的?谢谢楼主分享了

共8条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]