代码中printf
无法正常输出以及接收逻辑不响应的问题,主要源于中断与查询方式的冲突和接收标志位未正确设置,具体分析和修正如下:
printf
失效:串口中断与sendByte
查询逻辑冲突printf
依赖putchar
,而putchar
调用sendByte
发送字符。sendByte
使用查询方式(while(!TI)
等待发送完成),但你同时开启了串口中断(ES=1
):
SBUF
发送完成时,TI
会被硬件置 1,此时会触发串口中断,进入uart_ISR
。TI=0
(清除发送标志位),但此时sendByte
中的while(!TI)
还未退出 —— 中断提前清零TI
,导致while
循环永远等待(TI
已被清 0),sendByte
被卡死,最终printf
无法输出。recv_flag
未被正确置位在uart_ISR
中,接收数据后仅读取了SBUF
到recv_data
,但未设置recv_flag=1
。
main
函数中if(recv_flag==1)
的条件永远不成立,导致接收后的数据处理逻辑(+1 回发、打印)无法执行。#include "uart.h"
#include <stdio.h> // 确保包含stdio.h,支持printf
unsigned char recv_data;
unsigned char recv_flag = 0;
void UartInit(void) //4800bps@11.0592MHz
{
PCON &= 0x7F; // 波特率不倍速
SCON = 0x50; // 8位数据,允许接收(方式1)
TI = 0; // 初始化清除发送标志位
RI = 0; // 初始化清除接收标志位
TMOD &= 0x0F; // 清除定时器1模式位
TMOD |= 0x20; // 定时器1为8位自动重装方式
TL1 = 0xFA; // 4800bps初值(正确)
TH1 = 0xFA; // 重装值
ET1 = 0; // 禁止定时器1中断
TR1 = 1; // 启动定时器1
EA = 1; // 打开总中断
ES = 1; // 打开串口中断
}
// 发送单个字节(关键:发送时关闭串口中断,避免TI被提前清零)
void sendByte(unsigned char dat)
{
ES = 0; // 关闭串口中断,防止TI被中断服务程序清零
SBUF = dat;
while(!TI); // 等待发送完成
TI = 0; // 手动清除发送标志位
ES = 1; // 恢复串口中断
}
void sendString(unsigned char *dat)
{
while(*dat != '\0')
{
sendByte(*dat++);
}
}
// 重写putchar,供printf调用
char putchar(char c)
{
sendByte((unsigned char)c);
return c;
}
// 串口中断服务程序
void uart_ISR() interrupt 4
{
if(RI) // 接收中断
{
RI = 0; // 清除接收标志位
recv_data = SBUF; // 读取接收数据
recv_flag = 1; // 置位接收完成标志(关键修正)
}
if(TI) // 发送中断(仅清除标志,不做其他操作)
{
TI = 0;
}
}
主函数
#include <REGX52.H>
#include "Delay.h"
#include "uart.h"
#include <stdio.h> // 确保包含stdio.h
void main()
{
UartInit();
printf("wait for serial communication test start\r\n");
printf("please send a frame of data\r\n");
while(1)
{
if(recv_flag == 1)
{
recv_flag = 0;
recv_data += 1; // 接收数据+1
sendByte(recv_data); // 回发+1后的数据
printf("\r\n");
printf("%bd\r\n", recv_data); // 打印+1后的数据
}
}
}
printf
失效:
在sendByte
中添加ES=0
和ES=1
,发送时临时关闭串口中断,避免中断服务程序提前清零TI
,确保while(!TI)
能正常等待发送完成。uart_ISR
的接收部分添加recv_flag=1
,让main
函数能检测到接收完成事件,执行后续处理。stdio.h
头文件,否则printf
可能无法被编译器识别。四、其他方式
只在中断中处理 接收后加1 发送出的数据, 不单独调用 sendbyte函数
void uart_ISR() interrupt 4
{
if(RI)
{
recv_data=SBUF;
SBUF=recv_data+1;
RI=0;
}
if(TI)
{
TI=0;
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。