单片机实现接收从电脑发送过来的字符串的方法【转】
qcmc 发表于 - 2011-6-23 0:52:00

很多朋友会碰到这个问题:单片机接收从电脑串口发送出来的一串字符串,却只能接收到第一个字符,其他的都丢失了或者是接收到的是乱码,却不知道是什么原因。其实,那是因为,虽然单片机的是全双工串口,但是串口的缓冲区(SBUF)却一般只有一个字节,即1Byte,远没有像电脑串口的缓冲区以KB计算那么大,并且,单片机的处理速度是很有限的,试想一下,假如要求一串字符串以9600bps的速率,一个起始位,一个结束位,无校正位,相当于960Byte/s传输到单片机,单片机要是能够全部接收的话,那么单片机接收和处理一个字节的时间仅为约1ms的时间。这说明了,如果单片机的处理速度不够快,还没有将接收到的上一帧数据及时转送到单片机的RAM中,而电脑串口又传输过来一帧新的数据,这帧新的数据就会把单片机的串口输入缓冲区的SBUF给刷新掉,或者说单片机压根就没有接收到新的一帧数据,造成了数据的丢失或接收到乱码。

如果需要单片机接收到从串口发送过来的一段很长的字符串,并且能够都正常接收和显示,这在网上还找不到例子。

在这里,笔者提供了一种方法,通过单片机内部最高中断等级的中断源不断的查询从电脑串口发送过来的字符,并及时将接收到的字符串通过外接的1602显示屏显示出来。

这里用最为常见的51单片机作为例程,因为51单片机处理速度比较慢,所以需要将电脑串口发送速率调整为最低的600bps,那么单片机端接收和处理一个字符的时间约要求为14ms左右,基本足够了。这个14ms间隔的定时处理和查询工作,由单片机的最高等级内部中断源来控制,以保证电脑发送过来的每个字符单片机都能及时的去处理。

//1602实时显示单片机串口接收到电脑串口发送的字符串
//波特率600bps由T2中断产生,晶振12M
//最高等级中断T0负责定时查询串口输入SBUF
//作者:小宣-天堂雨林博客blog.sina.com.cn/acer Copyright@2009
//接线注释:
//P2.0-P2.7:LCD并行接口P0-P7
//P3.2-P3.4:LCD的RS、RW、E
//P3.0、P3.1:编程串口RXD、TXD

#i nclude <reg52.h>

unsigned char receive[32];
unsigned char k;

sbit rs=P3^2;
sbit rw=P3^3;
sbit e =P3^4;

void delay1ms(unsigned int f)
{
unsigned int i,j;
for(i=0;i<f;i++)
for(j=0;j<120;j++);
}

void receivem(void)
{
while(RI==1)
{
if(k==32){k=0;}
receive[k]=SBUF;
RI=0;
k++;
}
}

void timer_int(void)
{
TMOD=0x11;//00010001

SCON =0x50;
T2CON=0x30;
RCAP2H=0xFD;
RCAP2L=0x8F;

EA=1;
TR0=1;
TR1=0;
TR2=1;
ET0=ET1=ET2=1;
}

void time0(void) interrupt 1 using 1
{
TH0=0xCD;
TL0=0x50;
receivem();//定时将SBUF接收
}

void write_com(unsigned char com)
{
rw=0;
rs=0;
P2=com;
delay1ms(1);
e=1;
delay1ms(1);
e=0;
}

void write_data(unsigned char dat)
{
rw=0;
rs=1;
P2=dat;
delay1ms(1);
e=1;
delay1ms(1);
e=0;
}

void lcd_int(void)
{
rw=0;
e=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x80);
}

void dis(void)
{
unsigned char i;
if(k>0 && k<16)
{
write_com(0x80);
for(i=0;i<k;i++)
{
write_data(receive[i]);
}
}
if(k>=16 && k<32)
{
write_com(0xC0);
for(i=16;i<k;i++)
{
write_data(receive[i]);
}
}
}

void main()
{
timer_int();
lcd_int();
write_com(0x01);
while(1)
{dis();}
}