打印
[51单片机]

串口通信误码率很高,求帮助

[复制链接]
3408|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zzuliyang|  楼主 | 2015-5-25 10:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我编写了一个简单的程序,从PC机上接收简单的数据进行处理后将获得的number值显示在1602上,但接收到的数据误码率很高,波特率我调到了2400,还是误码失步,请帮忙,程序如下:
#include <reg52.h>
#include <intrins.h>
#define uchar  unsigned char
#define uint   unsigned int
sbit LCD_RS = P2^4;            
sbit LCD_EN = P2^2;
sbit LCD_WR = P2^3;
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

#define RED_HIGH_LEVEL 118   //阈值上限
#define RED_LOW_LEVEL 115//阈值下线

uchar data  RXDdata[ ] = {0x20,0x20,0x20 };
uchar temp,buf,m,count;
uint  shuju=0;
uint  number=0;

uint DownState = 0;
uint UpState = 0;
uint Rising标志寄存器 = 0;
uint Failing标志寄存器 = 0;

bit   playflag=0;
uchar code  cdis1[ ] = {"  DATA NUMBER:  "};
uchar code  cdis2[ ] = {"                "};
/**********************************************************
延时子程序
**********************************************************/
void delay1(uint ms)
{
   uchar k;
   while(ms--)
   {
     for(k = 0; k < 120; k++);
   }
}
/******************************************************************/
/*                                                                */
/*检查LCD忙状态                                                   */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。     */
/*                                                                */
/******************************************************************/
bit lcd_busy()
{                          
    bit result;
    LCD_RS = 0;
//    LCD_RW = 1;
    LCD_EN = 1;
    delayNOP();
    result = (bit)(P0&0x80);
    LCD_EN = 0;
    return(result);
}
/*******************************************************************/
/*                                                                 */
/*写指令数据到LCD                                                  */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                             */
/*                                                                 */
/*******************************************************************/
void lcd_wcmd(uchar cmd)
{                          
//  while(lcd_busy());
    LCD_RS = 0;
    LCD_WR = 0;
    LCD_EN = 0;
    _nop_();
    _nop_();
    P0 = cmd;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;  
}
/*******************************************************************/
/*                                                                 */
/*写显示数据到LCD                                                  */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。                               */
/*                                                                 */
/*******************************************************************/
void lcd_wdat(uchar dat)
{                          
//   while(lcd_busy());
    LCD_RS = 1;
    LCD_WR = 0;
    LCD_EN = 0;
    P0 = dat;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;
}
/*******************************************************************/
/*                                                                 */
/*  LCD初始化设定                                                  */
/*                                                                 */
/*******************************************************************/
void lcd_init()
{
    delay1(15);   
    lcd_wcmd(0x01);      //清除LCD的显示内容            
    lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x0c);      //开显示,显示光标,光标闪烁
    delay1(5);
    lcd_wcmd(0x01);      //清除LCD的显示内容
    delay1(5);
}
/*******************************************************************/
/*                                                                 */
/*  设定显示位置                                                   */
/*                                                                 */
/*******************************************************************/
void lcd_pos(uchar pos)
{                          
  lcd_wcmd(pos | 0x80);  //数据指针=80+地址变量
}
/*********************************************************
  发送数据函数
*********************************************************/
void senddata(uchar dat)
{
     SBUF =dat;
     while(!TI);
     TI = 0;
}
/*********************************************************
  串行中断服务函数
*********************************************************/
void  serial() interrupt 4
{
   ES = 0;                //关闭串行中断
   RI = 0;                //清除串行接受标志位
   buf = SBUF;            //从串口缓冲区取得数据
   senddata(buf);
   if(buf!=0x0D)
   {   
     if(buf!=0x0A)
     {
       temp =buf;
       if(count<3)
       {         
         RXDdata[count]=temp;
         count++;
if(count==3)
playflag=1;
       }
     }
   }
   ES = 1;    //允许串口中断
}
/*********************************************************
  数据显示函数
*********************************************************/

void  chuli()
{
   if(playflag)
  
  {shuju=(RXDdata[0]-48)*100+(RXDdata[1]-48)*10+(RXDdata[2]-48);

   if((DownState==0)&&(UpState==0))    //第一次进入均为零,上下限哪个先到就设定为哪个状态
              {
                if(shuju<=RED_LOW_LEVEL)
                {
                    DownState = 1;  // 设定状态是在下面
                }       
                else if(shuju>=RED_HIGH_LEVEL)
                {
                    UpState = 1;    // 设定状态是在上面
                }
            }
       else if((shuju>=RED_HIGH_LEVEL) && (DownState==1))     // 超过上限,而且之前状态是在下面
        {
        UpState = 1;
        DownState = 0;
        Rising标志寄存器 = 1;  //切换状态,设定上升标志
        }
       else if((shuju<=RED_LOW_LEVEL) && (UpState==1))        // 超过下限,而且之前状态是在上面
      {
        DownState = 1;
        UpState = 0;
        Failing标志寄存器 = 1; //切换状态,设定下降标志
       }
            
      /********** 累计圈数 **********/        
      if((Failing标志寄存器==1)&&(Rising标志寄存器==1))      // 一次上升,一次下降,即指针转过一次。两标志不区分先后
     {
        Failing标志寄存器 = 0;
        Rising标志寄存器 = 0;
        number++;

}
}
}
  
void  play()
{
   if(playflag)
   {
     //shuju=(RXDdata[0]-48)*100+(RXDdata[1]-48)*10+(RXDdata[2]-48);
     lcd_pos(0x40);           //设置位置为第二行
     for(m=0;m<16;m++)
     {
        lcd_wdat(cdis2[m]);      //清LCD1602第二行
        delay1(5);
        }
           lcd_pos(0x40);           //设置位置为第二行
           //lcd_wdat(RXDdata[0]);
           //lcd_wdat(shuju/1000+0x30);
           lcd_wdat(number%1000/100+0x30);
       lcd_wdat(number%1000%100/10+0x30);
           lcd_wdat(number%1000%100%10+0x30);
  }
  delay1(5);
     playflag=0;              
     count=0x00;
     for(m=0;m<3;m++)      
     {
      RXDdata[m]=0x20;         //清显存单元   
      delay1(5);
      }               
}
/*********************************************************
  主函数
*********************************************************/
void main(void)
{
    P0 = 0xff;
    P2 = 0xff;         
   
    SCON=0x50;           //设定串口工作方式
    PCON=0x00;           //波特率不倍增
    TMOD=0x20;           //定时器1工作于8位自动重载模式, 用于产生波特率
    EA=1;
    ES = 1;              //允许串口中断
    TL1=0xf4;
    TH1=0xf4;             //波特率9600
    TR1=1;
    lcd_init();
    lcd_pos(0x00);        //设置显示位置为第一行
    for(m=0;m<16;m++)
    {
        lcd_wdat(cdis1[m]);   //显示字符
        delay1(5);
        }
    lcd_pos(0x40);        //设置显示位置为第二行
    for(m=0;m<3;m++)
    {
        lcd_wdat(cdis2[m]);   //显示字符            
         delay1(5);
        }
    while(1)        
    {
      chuli();
          play();
          delay1(5);      
    }
}
/*********************************************************/

相关帖子

沙发
JY-DX-JY| | 2015-5-25 11:23 | 只看该作者
你可以写一个简单测试程序,从串口接收到数据后,原封不动的发回去,看看怎么样。

使用特权

评论回复
板凳
nbsmaps| | 2015-5-25 12:19 | 只看该作者
你先确定,是显示不对,还是串口不对,我粗看,显示还没完成,是不是串口第二个数据已到了!

使用特权

评论回复
地板
ningling_21| | 2015-5-25 12:51 | 只看该作者
硬件有没有问题?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝