上位机发送字符串,单片机接收无法识别,新手入门求助...
#include <at89x51.h>#define kai 0;
#define guan 1;
unsigned char table;
unsigned char flag;
unsigned char a;//a用来存放串口接收到的数据
unsigned char b;//b用来存放串口接收到的数据
sbit a0=P2^0;
sbit a1=P2^1;
main()
{
TMOD=0x20;//定时器1使用初值自动重装方式,方式2
TH1=0xfd;
TL1=0xfd;//9600波特率初值
TR1=1;//允许定时器计数
SM0=0;//方式1设置
SM1=1;
REN=1; //允许串口接收
EA=1;//开总中断
ES=1;//开串口中断
while(1)
{
a=table;
b=table;
if(flag==1){
if(a==49&&b==49)
{
a0=kai;
SBUF=1;
flag=0;
}
else if(a==49&&b==48)
{
a1=kai;
SBUF=2;
flag=0;
}
else ;
}
}
}
void serial () interrupt 4
{
unsigned char i;
if(RI)
{
RI=0;
for(i=0;i<2;i++)
{
while(!RI);
table=SBUF;
flag=1;
}
}
if(TI)
{
TI=0;
}
}以上就是程序啦。现在遇到这么一个问题。上位机发送字符11。进入if(a==49&&b==49)。发送10 有时候进入这个,有时候进入if(a==49&&b==48)。发送1有时候也会进入if(a==49&&b==49)。反正就是很乱。如果把flag==1去掉。又正常。这个是为什么。我觉得问题应该出在中断上,我刚学中断,一直没搞懂,现在还是没搞懂,求助。
本帖最后由 snic_k 于 2012-12-29 18:33 编辑
接收数据处理有问题,不够严密。
收到第一个数据时,如果有数据丢失,则会造成数据混乱。
例:当你发送11时,第一位丢失,只收到1,因你的程序中断中要死等第二位,所以当你在发送第二次数据11或10时,收到11或10的第一位,刚好与上次收到的1组成了11,第二次发送的11或10的第二位看情况,有可能丢失,也有可能可以被正确收到。总之就是数据结构乱了。
建议:
1、中断中最好收到一个数据就存入相应的table中,不要等待第二个数据。接收完后在主程序中再去判断数据长度等。
2、数据传输有可能因某些因素导致数据丢失,最好加上引导码,如第一个数据发送0XA5,第二个发送0x5A等,单片机收到数据首先判断第一个第二个数据是否是0XA55A,如不是则收到的数据做丢弃处理,这样可以保证所收到的数据不会乱掉。如此可以解决像我刚上面所提到的因丢数据造成的数据结构混乱。
这个,你说的思路我明白,程序上怎么写呢。比如引导码,不太懂。 snic_k 发表于 2012-12-29 18:32 static/image/common/back.gif
接收数据处理有问题,不够严密。
收到第一个数据时,如果有数据丢失,则会造成数据混乱。
学习了,很详细~ 51757517@qq.com 发表于 2012-12-29 20:00 static/image/common/back.gif
这个,你说的思路我明白,程序上怎么写呢。比如引导码,不太懂。
字头 0XA5 判断一下,是了继续做下一个判断,不是这组全扔掉,做其他事情,过会再回来判断还是不是0XA5,不是再扔掉,到字头是0XA5了,判断下一个字节~~~我是这么干过~~ 51757517@qq.com 发表于 2012-12-29 20:00 static/image/common/back.gif
这个,你说的思路我明白,程序上怎么写呢。比如引导码,不太懂。
引导码不就是相当于多发送了一个或两个字节的数据么。。。。比如你原来是发送11程12两个数据,现在加上两字节的的引导码。那就是一次发送四个数据嘛。。
稍微改了下。。
#include <at89x51.h>
#define kai 0;
#define guan 1;
unsigned char table;
unsigned char flag;
unsigned char a;//a用来存放串口接收到的数据
unsigned char b;//b用来存放串口接收到的数据
sbit a0=P2^0;
sbit a1=P2^1;
//----------------------------------------------
//增加部份
unsigned char DataLen;
//----------------------------------------------
main()
{
TMOD=0x20;//定时器1使用初值自动重装方式,方式2
TH1=0xfd;
TL1=0xfd;//9600波特率初值
TR1=1;//允许定时器计数
SM0=0;//方式1设置
SM1=1;
REN=1; //允许串口接收
EA=1;//开总中断
ES=1;//开串口中断
//----------------------------------------------
// 增加部份
DataLen = 0x00;
//----------------------------------------------
while(1)
{
if(flag==1)
{
if(a==49&&b==49)
{
a0=kai;
SBUF=1;
}
else if(a==49&&b==48)
{
a1=kai;
SBUF=2;
}
else ;
flag = 0;
}
}
}
void serial () interrupt 4
{
if(RI)
{
if(DataLen > 1)
{
table = SBUF;
//判断一帧数据是否接收完毕
if(++DataLen > 3)
{
DataLen = 0x00;
flag = 1;
}
}
else
{
table = SBUF;
if(++DataLen == 0x02)
{
// 已接收到大于2字节数据,判断引导码是否正确
if((table != 0xA5) || (table != 0x5A))
{
// 引导码不正确,接收数据长度指针置0
DataLen = 0x00;
}
}
}
}
TI = 0;
RI = 0;
} 谢谢~~我先试一下,吸收一下。{:victory:} 出现个问题。我上位机发送的是字符串ASCII码。怎么让转换成0xA5 16进制。 我用上位机发16进制。A55A0101 进不了循环。 怪事
页:
[1]