请问51单片机如何解决多字节串口接收问题

单片向传感器发送多个字节,等待(60s)传感器响应,如果没响应继续发送多个字节;
传感器响应以发送6个字节作为回复,第一个字节为0x23,请问如何设计中断程序接收多个字节??

//***********************串口发送一个字符********************
void SendOneChar(unsigned char ch)
{

SBUF = ch;

}

//***********************串口发送多个字节******number 为字节个数********************
void Send_Data( unsigned char *p,unsigned char number)
{
for(;number!=0;number--)
{
SendOneChar(*p);
p++;
}
}

//***********************串口接收一个字符**************
unsigned char Rec_OneChar(void)
{
unsigned char buffer;
buffer = 0;

while(RI)
{
buffer=SBUF;

}
return buffer;
}

void uart_interrupt(void) interrupt 4 using 0
{

unsigned char i=0;
unsigned char first;

if(RI==1)
{
first=SBUF;

if(first==0x23)
{
for(i=0;i<5;i++)
{
buffer[i]=Rec_OneChar();
RI = 0; //RI清零
}
}

}

if(TI==1)
{
TI=0; //TI清零
}
}

中断函数应该有问题!!

串口的收发可以用查询和中断两个办法来实现。
1、查询方法更适合于半双工机制,编写的思路简单,程序结构简单,在全双工通信中易出问题。
2、中断方法则更高效。你的程序把两种方法混搭使用,容易出错。

以你的程序为例,一旦收到首个23H字符,就停止在中断服务中for循环里面等待5个剩余字符。假设传感器只发了3个字符,你的程序就停止在for循环里面。
以你的程序为例改进,在中断服务接收中,每次接收中断只收1个字符,完成后退出。
void uart_interrupt(void) interrupt 4 using 0
{
static unsigned char i=0;
unsigned char buf;
if(RI==1)
{
buf=SBUF;
switch(i)
{
case 0:
if(buf==0x23)i=1;
break;
case 1:
case 2:
case 3:
case 4:
case 5:
buffer[i-1]=buf;
i++;
if(buf==0x23)
i=1;
if(i==5)
{
do_something_here(buffer);
i=0;
}
break;
default: i=0;break;
}
RI = 0; //RI清零
}
if(TI==1) TI=0; //TI清零
}
这样改符合你的思维习惯吗?实际串口协议解析与协议密切相关,用状态机做比较好。程序中i把它变成状态机的状态,思考一下,改改程序更佳。追问

原来的程序 RI=0时,就应该跳出了 for(i=0;i<5;i++) 这个循环,那么就0x23之后的字节就接收不到了吧??

传感器发送6个字节,第1个为0x23,最后一个为0x0D,最后一个需要校验码??传感器与单片机是两条线相连,应该是全双工,不是半双工。

我把中断和查询两个方法共用?

TI的置0可以修改放到发送一个字符那里···

追答

(1)i!=5,不会跳出。0x23之后字节可以接收到。但只有5个后才会退出中断。
(2)当然可以,在完成所有字节时刻,处理buffer之前,判断即可。
if((i==5)&&(buffer[4]==0xd))
{
do_something_here(buffer);
i=0;
}
(3)两条线就是双工。一来一回,一收一发的意思。双向通信。所谓全与半,是指通信是否同时发生。
(4)按道理,所有的收发都可以放中断里面。比如,我上面改的程序,所有的接收都在中断里面完成。而你的发送是通过查询TI完成的(这部分,我没改,可以放在中断中TI判断里发送)。
(5)你如果非要查询TI发送,更妥的应该是发送前,关闭ES。没必要进中断。

追问

在问一下,两个单片机如何全双工通信,就拿上边的单片机与传感器来说吧,如何通proteus仿真?

追答

传感器部分,你通过虚拟仪器中的虚拟终端来模拟,RXD和TXD与单片机交叉连接,配置恰当的波特率。应答的内容从键盘录入。稍作协议调整,暂时用ASCII字符来测试。

温馨提示:内容为网友见解,仅供参考
第1个回答  2013-06-02
程序编写的,思路不对。
接收,每次中断,只能收一个字节。

楼主的程序,在中断里面,循环接收,这是收不到什么结果的。
你的这次中断,不结束,下次中断就进不来。

第一个字节为0x23,需要判断出来。

当收到了第一个字节为0x23,之后的每次中断,再顺序存放收到的数据。
第2个回答  2017-08-07
你好!串口接收,不是采用for循环,要顺序接收,然后存入数组
第3个回答  2013-05-20

这是我最近毕设写的用于计算机与单片机通信的   如接收到上位机命令则发送三个字节  接收用中断方法  发送用查询方法   仅供参考

请问51单片机如何解决多字节串口接收问题
串口的收发可以用查询和中断两个办法来实现。1、查询方法更适合于半双工机制,编写的思路简单,程序结构简单,在全双工通信中易出问题。2、中断方法则更高效。你的程序把两种方法混搭使用,容易出错。以你的程序为例,一旦收到首个23H字符,就停止在中断服务中for循环里面等待5个剩余字符。假设传感器只发...

...51单片机串口通讯多字节接收的问题.劳烦您了~~
写1个接收中断处理函数,INT8U Branch_RxBuf[10];INT8U Num_RxData;void int_Isr (void){ INT16U iTemp;INT8U bFSKValue;EXTINT = 0x01;iTemp=Read_Modem(STATUS);if(iTemp&0x0040){ \/\/ 接收中断 bFSKValue=(INT8U)Read_Modem(RX_DATA_BYTE); \/\/ 读Recieve Data Register 读取...

51单片机如何进行多字节串口接收?!!!
串口的收发可以用查询和中断两个办法来实现。1、查询方法更适合于半双工机制,编写的思路简单,程序结构简单,在全双工通信中易出问题。2、中断方法则更高效。你的程序把两种方法混搭使用,容易出错。以你的程序为例,一旦收到首个23H字符,就停止在中断服务中for循环里面等待5个剩余字符。假设传感器只发...

51单片机接收PC机发来的多字节数据怎么处理
其实,这种处理,与接收一个字节的处理方式很相似,只是需要先保存一帧数据,再处理执行。

51单片机串口通信 数据大于八位(256)怎么办 一旦超过就失真啦 能分开传...
不知道你说的是不是这样的溢出失真。而每一次接收后就会使RI相应置1,SBUF缓存着刚刚接收的一个字节数据,要及时转存处理,要不然下次发送\/接收又会被新的数据代替。就这样一个一个字节的重复就形成许多字节的连续收发。串口这东西很好用的,通信也很方便的很多地方会用到。

51单片机从电脑串口接收10字节的数据,程序用c语言
bit UART_ReadByte(uchar *p_data,bit data_mode) \/\/串口读字节函数,返回值0 无数据,1 有数据,将data_mode模式(ASCII_Mode或HEX_Mode)转成Hex结果存到p_data指向地址 { if(!UART_ReFlag) return FALSE;\/\/若无新数据,则返回 0(无数据)UART_ReFlag=FALSE;\/\/否则,清 串口接收标志位 if(...

avr单片机串口接收多字节数据怎么处理?我自己只能接收单字节数据。
接收数据一定是一个字节一个字节接收的,接收多个字节一般的方法是使用接收缓冲的方法完成,具体的讲至少需要两个变量:一个是接收缓冲字符串,例如RXBuffer[];一个是缓冲区指针RXBufPoint。收到一个字符,令RXBuffer[RXBufPoint++] = UDR这样就可以了,在收到足够的字节的时候通知主程序处理。记住:...

单片机串口调试时,为什么收发的数据总是有错,而且错误是固定的,比如...
串口通信的每个字节的起始位都是同步的基准,所以速率误差不会累积到下个字节去。也许是驱动电路或者软件问题,比如接受缓冲区溢出等,可以用通用的串口调试软件测试一下

单片机串口通信接收多个字节错误
串口通信,每次,只能是一个字节,即:0~255。0~65535,就要用两次。0~65536,就要用三次。这么多字节的传送,楼主是怎么发送的?希望能解决您的问题。

单片机如何接收多位数数据
声明一个全局变量数组,进入接收中断后,将SBUF存入数组里面,每存入一次,数组标号增加1;长时间没有中断或者接收到结束信号,读出数组里存储的值,并清空计数器和数组,准备进入下一次接收。

相似回答