大老们帮忙看一下这个单片机串口屏程序是否正常 用的是陶晶驰的串口
现在的问题是点击屏幕 单片机没有输出 #include "config.h"#define U8 unsigned char
U8 rec_Dat;
U8 rec_num = 0;
void Uart1_Isr(void) interrupt 4
{
if (TI) //检测串口1发送中断
{
TI = 0; //清除串口1发送中断请求位
}
if (RI) //检测串口1接收中断
{
RI = 0; //清除串口1接收中断请求位
}
}
void Uart1_Init(void) //9600bps@24.000MHz
{
P_SW1 = (P_SW1 & ~0xc0) | 0x40;
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xCC; //设置定时初始值
TH1 = 0xFF; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
ES = 1; //使能串口1中断
rec_Dat=S2BUF;
}
// 处理接收到的数据
void usart1_RunTask(void)
{
if (rec_num >= 6)
{
if ((rec_Dat == '\n') && (rec_Dat == '\r'))
{
if ((rec_Dat == 'O') && (rec_Dat == 'P') &&
(rec_Dat == 'E') && (rec_Dat == 'N'))
{
P20 = 0; // 设置P0的值
}
}
rec_num = 0; // 处理完数据后重置计数器
}
}
针对您提供的代码及故障现象分析,程序存在以下几处关键问题需要修正:
一、串口中断服务函数缺陷
原中断服务函数存在数据丢失风险:
c
void Uart1Isr(void) interrupt 4
{
if (TI) { TI = 0; }//清除发送中断
if (RI) { RI = 0; }//清除接收中断但未读取数据
}
问题分析:
在检测到接收中断标志RI=1时,未从SBUF寄存器中读取数据,导致接收数据丢失。
修正方案:
c
void Uart1Isr(void) interrupt 4
{
if (RI) {
RI = 0;
recDat = SBUF;//保存接收数据
if (recnum >= 60) recnum = 0; //防止溢出
}
if (TI) { TI = 0; }
}
二、UART1初始化函数错误
1. 错误的数据寄存器访问
代码中误用S2BUF(UART2缓冲区):
c
recDat=S2BUF;//错误:UART1应使用SBUF
修正方案:
删除该行代码。初始化函数仅需配置硬件,不应主动读取数据。
2. 波特率计算验证
根据代码注释//9600bps@24000MHz,实际晶振频率可能为24.000MHz。
计算定时器1重载值:
TH1 = 256 - (Fosc / 12 / 16 / Baudrate)
= 256 - (24,000,000 / 12 / 16 / 9600)
≈ 256 - 13.02 ≈ 243 (0xF3)
当前配置TH1=0xFF会导致实际波特率偏低(约6250bps),建议修正为:
c
TL1 = 0xF3;//修正波特率参数
TH1 = 0xF3;
三、全局中断未启用
代码中未开启全局中断使能位EA,导致中断无法触发。
补充初始化代码:
c
void Uart1Init(void)
{
//原有配置代码...
EA = 1;//开启全局中断
}
四、数据协议处理逻辑优化
当前数据处理条件if (recnum >= 6)缺乏协议完整性校验:
1. 陶晶驰串口屏通常采用帧结构(如:AA CMDLEN CMD ... CKSUM 0F 0F)
2. 建议增加帧头、长度、校验和等检测逻辑
改进示例:
c
void usart1RunTask(void)
{
if (recnum >= 4) {//假设最小帧长4字节
if (recDat == 0xAA && recDat == 0x0F && recDat == 0x0F) {
//校验通过后处理数据
recnum = 0;//复位接收指针
}
}
}
五、硬件排查建议
1. 物理层验证
确认TXD(单片机)与RXD(屏幕)交叉连接
测量信号电平是否符合标准(3.3V/5V匹配)
使用示波器捕获波形,验证实际波特率
2. 陶晶驰配置检查
通过USART HMI工具确认控件事件是否绑定正确指令
检查屏幕工程中设置的波特率与代码是否一致
六、完整修正代码
c
include "config.h"
define UARTBUFLEN 60
volatile U8 recDat;
volatile U8 recnum = 0;
void Uart1Isr(void) interrupt 4
{
if (RI) {
RI = 0;
recDat = SBUF;
if (recnum >= UARTBUFLEN) recnum = 0; //循环缓冲
}
if (TI) TI = 0;
}
void Uart1Init(void) //9600bps@24.000MHz
{
PSW1 = (PSW1 & ~0xC0) | 0x40; //切换UART1到P3.0/P3.1
SCON = 0x50; //8位数据+可变波特率
AUXR &= ~0x40;//定时器1时钟12T模式
TMOD &= 0x0F; //定时器1模式设置
TL1 = 0xF3; //波特率重载值
TH1 = 0xF3;
TR1 = 1; //启动定时器1
ES = 1; //使能串口中断
EA = 1; //开启全局中断
}
void ProcessTouchEvent(void)
{
if (recnum >= 4) { //示例协议:AA CMD 0F 0F
if (recDat==0xAA && recDat==0x0F && recDat==0x0F) {
//TODO: 触发对应操作
SBUF = 0x01; //示例:通过串口发送响应
while(!TI);//等待发送完成
TI = 0;
recnum = 0; //清空缓冲区
}
}
}
七、调试建议
1. 最小系统验证
通过短接单片机的TXD与RXD引脚,测试自发自收是否正常。
2. 指令监控
使用USB转TTL工具连接屏幕串口,通过PC端串口助手确认屏幕实际输出数据。
3. LED辅助调试
在中断服务函数中添加GPIO翻转代码,通过示波器观察中断触发频率。
以上修正可系统性解决通信异常问题。若仍存在故障,建议重点排查硬件链路阻抗匹配问题。
[本文内容由国芯人工智能辅助生成,仅供参考] 还是不行 不知道哪里出了问题哦
小熊熊 发表于 2025-5-9 18:33
还是不行 不知道哪里出了问题哦
我接的是1.61.7
你可以先用串口助手和屏联调一下试试 代码不完整,且中断里没什么读写操作。建议用例程先测试 感觉不对劲啊 多了好多符号 ercircle 发表于 2025-5-9 20:51
代码不完整,且中断里没什么读写操作。建议用例程先测试
#define BAUDRATE (9600)
#define T2_RELOAD (65536 - (SYSCLK / BAUDRATE + 2) / 4)
UART1_SwitchP1617(); //设置串口数据端口: RxD (P1.6), TxD (P1.7)
UART1_Timer2BRT(); //选择定时器2作为串口1波特率发生器
TIMER2_TimerMode(); //设置定时器2为定时模式
TIMER2_1TMode(); //设置定时器2为1T模式
TIMER2_SetPrescale(0); //设置定时器2的8位预分频
TIMER2_SetReload16(T2_RELOAD); //设置定时器2的16位重载值
TIMER2_Run(); //定时器2开始运行
UART1_EnableRx(); //使能串口1接收数据
UART1_Mode1(); //设置串口1为模式1 (8位数据可变波特率)
UART1_SetIntPriority(0); //设置中断为最低优先级
rec_num = 0;
UART1_EnableInt(); //使能串口1中断
//<<AICUBE_USER_UART1_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_UART1_INITIAL_END>>
}
void usart1_RunTask(void)
{
if(rec_num >= 6)
{
if((rec_Dat == 0x01) && (rec_Dat == 0x02))
{
if((rec_Dat == 0x03) && (rec_Dat == 0x04) && (rec_Dat == 0x05) && (rec_Dat == 0x06))
{
P20 = 0; // 设置P0的值
}
}
rec_num = 0; // 处理完数据后重置计数器
}
} 小熊熊 发表于 2025-5-10 20:21
这样子能接受到串口数据吗 小熊熊 发表于 2025-5-10 20:21
void UART1_ISR(void) interrupt UART1_VECTOR
{
//<<AICUBE_USER_UART1_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
if (UART1_CheckTxFlag()) //判断串口发送中断
{
UART1_ClearTxFlag(); //清除串口发送中断标志
}
if (UART1_CheckRxFlag()) //判断串口接收中断
{
UART1_ClearRxFlag(); //清除串口接收中断标志
}
rec_Dat = SBUF;
//<<AICUBE_USER_UART1_ISR_CODE1_END>>
}
页:
[1]
2