注意搞清楚串口的数据寄存器和移位寄存器区别,TI和RI标志位是通过数据寄存器的状态来置位的,参考江科大的ppt。
unsigned char rx_buf[10];
/*----------------------------
发送串口数据
----------------------------*/
void SendData(unsigned char dat)
{
while (busy); //等待前面的数据发送完成
busy = 1;
SBUF = dat; //写数据到UART数据寄存器TDR
}
/*----------------------------
发送字符串
----------------------------*/
void SendString(char *s)
{
while (*s) //检测字符串结束标志
{
SendData(*s++); //发送当前字符
}
}
/*----------------------------
UART 中断服务程序写法1
-----------------------------*/
void Uart() interrupt 4
{
if (RI) //接收完成 RDR空了,可以读了
{
RI = 0; //清除RI位
rx_buf[rx_cnt++]=SBUF; //从RDR读数据
if(rx_buf[rx_cnt-1]=='\n') //假设指令以\n结尾
{
flag_uart=1; //flag=1的时候就处理rx_buf里面接收的数据
rx_cnt=0;
}
}
if (TI) //发送完成 TDR空了,可以写了
{
TI = 0; //清除TI位
busy = 0; //清除标志
}
}
/*----------------------------
UART 中断服务程序写法2
-----------------------------*/
void Uart() interrupt 4
{
if (RI) //接收完成 RDR空了,可以读了
{
RI = 0; //清除RI位
rx_buf[rx_cnt++]=SBUF; //从RDR读数据
if(rx_cnt==10) //假设接收数据是固定长度,10个
{
flag_uart=1;
rx_cnt=0;
}
}
if (TI) //发送完成 TDR空了,可以写了
{
TI = 0; //清除TI位
busy = 0; //清除标志
}
}
问题:若想接收的是固定长度的3个字节的数据,如果我们先发送了1个字节错误的a,接着又发了3字节正确的bcd,那么rx_buf数组里面的是abc,就去处理了,这时候是错误的指令,没办法接收bcd。
解决办法:串口接收闲时判断
- 在定时器中断里,对串口接收的空闲时间开始计时,如果到50ms,则情空rx_buf和rx_cnt;
- 在串口接收服务函数里,重置串口接收空闲计时。
- 原因:电脑端连续发送N个字节,那么2个字节之间的间隔小于50ms。