我编写了一个简单的程序,从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);
}
}
/*********************************************************/ |