C51单片机串口通信

我想使用89S52单片机做一个控制LED灯的实验,要求为:PC通过串口工具发送指令控制单片机,让其点亮或熄灭LED即可;
我尝试过发单字节是可以实现的,比如发 00给单片机,LED灯亮,发FF,LED灯灭;
我现在的问题是:比如我要发送多个字节来控制LED灯就不行了,例如:发送“1b 30 01”LED1点亮,发送“1b 30 02” LED1熄灭,发送“1b 31 01”LED2点亮,发送“1b 30 02”LED2熄灭;
请问如何才能实现同时发送多字节及识别出来?最好有详细的代码,谢谢!

可以通过缓冲区或者switch语句来实现
字符命令的话一般要buff区缓冲数据最后一次处理
这样的只要switch语句就可以解决了。
在串口中断加入如下代码:

void UARTInterrupt(void) interrupt 4//串口中断
{
static unsigned char cont;//接收计数

unsigned char temp;//临时变量

if(RI)
{
RI = 0;
switch(cont)
{

case 0:if(SBUF==0x1b){cont=1;return;}//检测第一个起始码

case 1:temp=SBUF-'0';temp=1<<temp;cont=2;return;//获取要点亮的LED号

case 2:if(SBUF-1)P1&=~(temp);else P1|=temp;cont=0;return;//判断点亮还是熄灭

}

}
else
TI = 0;
}追问

你好,我按你上面说的把代码加上去了,但是好像没有看到有效果喔?请帮忙指正,谢谢!

追答

#include
void InitUART(void)
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD;
TL1 = TH1;
PCON = 0x00;
EA = 1;
ES = 1;
TR1 = 1;
}
void input(unsigned char str)
{
static unsigned char cont;//接收计数
static unsigned char temp;//临时变量
switch(cont)
{
case 0:
if(str==0x1b)//检测第一个起始码
{cont=1;
return;}
case 1:
temp=str-0x30;//获取要点亮的LED号
temp=cont<<temp;
cont=2;
return;
case 2:
if(str-1)//判断点亮还是熄灭
P1|=temp;
else //P1口输出指定数据
P1&=~temp;
cont=0;
return;
}
}
void main(void)
{
InitUART();
while(1);
}
void UARTInterrupt(void) interrupt 4//串口中断
{
if(RI)
{
RI = 0;
input(SBUF);
}
else
TI = 0;
}

温馨提示:答案为网友推荐,仅供参考
第1个回答  2012-11-21
串口助手因为没有握手信号的关系,所以发送数据是没有等待的,因此,单片机端接受需要开辟缓冲区才可以保证数据不丢失。用C的话就,你就用一个数组来做就OK了。
#include<reg51.h>
#define uchar unsigned char
uchar getdat[16],getp,putp;
sbit LED=P1^0;
void serisr() interrupt 4
{
if(RI)
{
RI=0;
getdat[putp]=SBUF;
putp++;
putp&=0x0f;
}
}
main()
{
uchar comd[5],i;
TMOD=0x20;
SCON=0x50;
TH1=0xfd;
TL1=0xfd;
TR1=1;
EA=1;
getp=putp=0;
while(1)
{
if(getp!=putp)
comd[i]=getdat[getp];
i++;
getp++;
getp&=0x0f;
}
if(i==2)
{
i=0;
if((comd[0]==0x1b))&&(comd[1]==0x31)&&(comd[2]==0x01))LED=0;
if((comd[0]==0x1b))&&(comd[1]==0x30)&&(comd[2]==0x02))LED=1;
}
}追问

你好,我试了把你上面的代码下载到芯片里面测试,但好像LED灯不能受PC的控制喔,请帮忙指正,谢谢!

追答

#include
#define uchar unsigned char
uchar getdat[16],getp,putp;
sbit LED=P1^0;
void serisr() interrupt 4
{
if(RI)
{
RI=0;
getdat[putp]=SBUF;
putp++;
putp&=0x0f;
}
}
main()
{
uchar comd[5],i;
TMOD=0x20;
SCON=0x50;
TH1=0xfd;
TL1=0xfd;
TR1=1;
EA=1;
getp=putp=0;
while(1)
{
if(getp!=putp)
{
if((getdat[getp]==0x1b)||(i>0))
{
comd[i]=getdat[getp];
i++;
}
getp++;
getp&=0x0f;
}
if(i==2)
{
i=0;
if((comd[0]==0x1b))&&(comd[1]==0x31)&&(comd[2]==0x01))LED=0;
if((comd[0]==0x1b))&&(comd[1]==0x30)&&(comd[2]==0x02))LED=1;
}
}

第2个回答  2012-11-21
你这个是这样的,你检测两个和检测三个的长度改了吗? 我的意思是,如果你检测00两位的数组长度没有变, 那么你发三次就会变成01. 另外一种可能是,串口发送的时候,空格是不计的。电脑发送的,你程序里面判定要有空格了。 发你判定接受数据代码上来
第3个回答  2012-11-21
如果每隔一段时间led亮灭一次的话,比如亮一秒灭一秒吧,你可以定时1秒,送个高电平给口线,然后再定时1秒,把高电平取反给口线,如此循环就行了。
第4个回答  2012-11-21
不是很简单吗?在接收中断里面加个计数器,接收完3个字节数据后再对数据进行处理。
相似回答