遇到的问题描述
51单片机使用串口发送数据时出现只循环发送字符串的第一个字符的情况。就算发送的是第一个字符也有时候一直发送。
串口函数代码
参考串口发送注意
#include <reg52.h> //此文件中定义了单片机的一些特殊功能寄存器
void UsartInit()
{
SCON=0X50; //设置为工作方式1
TMOD=0X20; //设置计数器工作方式2,8位自动重装
PCON=0X00; //波特率加倍,最高位控制是否加倍
TH1=0XFa; //计数器初始值设置,注意波特率是4800的
TL1=0XFa;
ET1=0; //关闭定时器1中断
ES=1; //打开串口中断
REN=1; //允许接收
EA=1; //打开总中断
TR1=1; //打开计数器
}
void UART_SendByte(unsigned char Byte)
{ //这里如果没放在中断中而是在主函数进行发送,可能导致接收无法进入中断
//ES=0;
SBUF = Byte;
while (!TI);
TI = 0;
//ES=1;
}
void uartSendString(char *pS)
{
while (*pS) //检测字符串结束标志
{
UART_SendByte(*pS++); //发送当前字符
}
}
分析导致问题的原因
参考程序跑飞问题,串口只显示一个字符
第一种猜想,发送一个字符完成后不能触发TI置位,导致程序停留在将第一个字符在缓冲区,且一直发送。
第二种猜想,程序触发中断后没有对中断进行处理,导致程序跑飞,使得程序从主函数main开始再次执行,也会出现一直打印第一个字符的情况。这种和参考文章程序跑飞问题中的第一种情况很像。
从多次实验来看,在程序添加了对串口的中断函数后,即使没有对发送完成的标志在中断中处理,程序也能正常运行。但一旦去除串口中断函数,那么就会出现重复打印第一个字符的情况。所以认为第二种猜想的可能性更大。
下面是在主函数中添加的中断函数代码
口中断,处理接收和发送问题
void Usart() interrupt 4
{
if (RI == 1) //如果接收标志位为1,接收到了数据
{
if(SBUF=='1')
uartSendString("YOU ARE RIGHT!!\n"); //将受到的数据发回串口
RI = 0; //接收标志位清0
}
}
思考另一种只显示第一个字符的情况
如果在主函数中调用发送字符串的函数,而串口中断出现对发送中断标志TI置零,那么在主函数种的发送字符等待标志位置位可能会永远无法实现,但这种只会发送一次第一个字符。