串口问题 我在AIcube里面创建了1个串口发现永不了大哥们看看
#include "config.h"u8 Rec_Dat; //接收缓冲区
u8 Rec_Num = 0; //接收计数
B_TX2_Busy=0;
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 串口2中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART2_ISR(void) interrupt UART2_VECTOR
{
//<<AICUBE_USER_UART2_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
if (UART2_CheckTxFlag()) //判断串口发送中断
{
UART2_ClearTxFlag(); //清除串口发送中断标志
}
if (UART2_CheckRxFlag()) //判断串口接收中断
{
UART2_ClearRxFlag(); //清除串口接收中断标志
Rec_Dat = S2BUF;
}
//<<AICUBE_USER_UART2_ISR_CODE1_END>>
}
////////////////////////////////////////
// 串口2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART2_Init(void)
{
#ifdef BAUDRATE
#undef BAUDRATE
#endif
#define BAUDRATE (9600)
#define T2_RELOAD (65536 - (SYSCLK / BAUDRATE + 2) / 4)
UART2_SwitchP4243(); //设置串口数据端口: RxD2 (P4.2), TxD2 (P4.3)
//UART2_Timer2BRT(); //串口2固定选择定时器2作为波特率发生器
TIMER2_TimerMode(); //设置定时器2为定时模式
TIMER2_1TMode(); //设置定时器2为1T模式
TIMER2_SetPrescale(0); //设置定时器2的8位预分频
TIMER2_SetReload16(T2_RELOAD); //设置定时器2的16位重载值
TIMER2_Run(); //定时器2开始运行
UART2_EnableRx(); //使能串口2接收数据
UART2_Mode1(); //设置串口2为模式1 (8位数据可变波特率)
UART2_SetIntPriority(0); //设置中断为最低优先级
UART2_EnableInt(); //使能串口2中断
Rec_Num = 0;
B_TX2_Busy = 0;
//<<AICUBE_USER_UART2_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_UART2_INITIAL_END>>
}
void Uart2_SendStr( u8 *puts ) //串口数据发送函数
{
for (; *puts != 0;puts++) //遇到停止符0结束
{
S2BUF = *puts;
B_TX2_Busy = 1;
while(B_TX2_Busy);
}
}
void Usart2_RunTask(void)
{
if( Rec_Num >= 6 ) //是否接收到了6位以上的数据
{
if(( Rec_Dat == 0x02 ) && ( Rec_Dat == 0x02 ) ) //末尾判断
{
if( ( Rec_Dat == 0x05 ) && ( Rec_Dat == 0x04 ) && ( Rec_Dat == 0x03 ) && ( Rec_Dat == 0x01 ))
{
P40 = 0;
P00 = 0;
Uart2_SendStr( "打开成功!\r\n" );
}
else if( ( Rec_Dat == 0x01) && ( Rec_Dat == 0x02 ) && ( Rec_Dat == 0x03 ) && ( Rec_Dat == 0x04 ) && ( Rec_Dat == 0x05 ))
{
P40 = 1;
P00 = 1;
Uart2_SendStr( "关闭成功!\r\n" );
}
Rec_Num = 0;
}
}
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
针对您提供的串口通信代码及使用问题,经分析存在以下技术问题需要修正:
一、基础语法错误修正
1. 头文件引用错误
原始代码:#include "configh"
修正建议:检查头文件命名规范,确认是否存在拼写错误
修正代码:#include "config.h" // 注意文件扩展名完整性
2. 变量声明不规范
原始代码:BTX2Busy=0;
修正建议:补充变量类型声明
修正代码:u8 BTX2Busy = 0; // 添加数据类型说明
3. 接收缓冲区管理
原始代码:
c
u8 RecDat;
u8 RecNum = 0;
修正建议:增加缓冲区溢出保护机制
修正代码:
c
define MAXRECLEN 50
u8 RecDat;
u8 RecNum = 0;
二、中断服务程序优化
1. 发送中断冗余处理
原始代码:
c
if (UART2CheckTxFlag()) {
UART2ClearTxFlag();
}
优化建议:若无发送中断需求应关闭相关中断
修改方案:移除发送中断处理代码
2. 接收数据处理优化
原始代码:
c
RecDat = S2BUF;
改进方案:增加缓冲区边界检查
修正代码:
c
if(RecNum < MAXRECLEN){
RecDat = S2BUF;
} else {
// 可添加缓冲区溢出标志
}
三、串口初始化配置建议
建议补充完整初始化函数:
c
void UART2Init(void)
{
UART2Configure(UART2Mode1,
UART2BRTUseBGR,
UART2BRT115200,
UART2RIEnable | UART2TIEnable);
EA = 1; // 开启总中断
ENABLEUART2; // 使能串口2
}
四、关键配置检查清单
1. 时钟源配置
确认系统时钟与波特率计算匹配:
c
// 示例波特率计算公式:
// Baud = SYSclk / (256)
2. 引脚复用配置
检查GPIO初始化代码:
c
// 确保已配置UART2对应引脚模式
GPIOInit(UART2TXPIN, GPIOModeAFPP);
GPIOInit(UART2RXPIN, GPIOModeIPU);
3. 中断向量确认
核对芯片手册确认:
c
// 不同芯片中断向量可能有差异
void UART2ISR(void) interrupt X // X需与实际中断号一致
五、调试建议
1. 基础测试流程:
c
// 发送测试函数
void UART2SendTest(void)
{
UART2SendString("AT\r\n");
while(BTX2Busy); // 等待发送完成
}
// 接收状态查询
void CheckRecData(void)
{
if(RecNum > 0){
UART2SendData(RecDat, RecNum);
RecNum = 0;
}
}
2. 示波器检测要点:
测量TX引脚信号波形
验证波特率误差(应
[本文内容由国芯人工智能辅助生成,仅供参考] //<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: uart.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-05-12) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h"
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
u8 B_TX2_Busy = 0;
u8 Rec_Dat; //接收缓冲区
u8 Rec_Num = 0; //接收计数
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
BOOL fPrintfBusy;
////////////////////////////////////////
// 串口2中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART2_ISR(void) interrupt UART2_VECTOR
{
//<<AICUBE_USER_UART2_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
if (UART2_CheckTxFlag()) //判断串口发送中断
{
UART2_ClearTxFlag(); //清除串口发送中断标志
fPrintfBusy = 0; //清除printf发送忙标志
B_TX2_Busy = 0;
}
if (UART2_CheckRxFlag()) //判断串口接收中断
{
UART2_ClearRxFlag(); //清除串口接收中断标志
Rec_Dat = S2BUF;
}
//<<AICUBE_USER_UART2_ISR_CODE1_END>>
}
////////////////////////////////////////
// 串口2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void UART2_Init(void)
{
#ifdef BAUDRATE
#undef BAUDRATE
#endif
#define BAUDRATE (9600)
#define T2_RELOAD (65536 - (SYSCLK / BAUDRATE + 2) / 4)
UART2_SwitchP4243(); //设置串口数据端口: RxD2 (P4.2), TxD2 (P4.3)
//UART2_Timer2BRT(); //串口2固定选择定时器2作为波特率发生器
TIMER2_TimerMode(); //设置定时器2为定时模式
TIMER2_1TMode(); //设置定时器2为1T模式
TIMER2_SetPrescale(0); //设置定时器2的8位预分频
TIMER2_SetReload16(T2_RELOAD); //设置定时器2的16位重载值
TIMER2_Run(); //定时器2开始运行
UART2_EnableRx(); //使能串口2接收数据
UART2_Mode1(); //设置串口2为模式1 (8位数据可变波特率)
UART2_SetIntPriority(0); //设置中断为最低优先级
UART2_EnableInt(); //使能串口2中断
fPrintfBusy = 0; //清除发送数据忙标志
//<<AICUBE_USER_UART2_INITIAL_BEGIN>>
// 在此添加用户初始化代码
Rec_Num = 0;
B_TX2_Busy = 0;
P2 = 0x0F;
//<<AICUBE_USER_UART2_INITIAL_END>>
}
////////////////////////////////////////
// 重写printf字符发送重定向函数
// 入口参数: dat (printf函数待打印的字符)
// 函数返回: 需要返回入口参数的数据
////////////////////////////////////////
char putchar (char dat) //将串口2和printf函数绑定
{
while (fPrintfBusy);
UART2_SendData(dat);
fPrintfBusy = 1;
return dat;
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
void Uart2_SendStr( u8 *puts ) //串口数据发送函数
{
for (; *puts != 0;puts++) //遇到停止符0结束
{
while(B_TX2_Busy);
S2BUF = (*puts);
B_TX2_Busy = 1;
}
}
void Usart2_RunTask(void)
{
if( Rec_Num >= 6 ) //是否接收到了6位以上的数据
{
if(( Rec_Dat == 0x02 ) && ( Rec_Dat == 0x02 ) ) //末尾判断
{
if( ( Rec_Dat == 0x05 ) && ( Rec_Dat == 0x04 ) && ( Rec_Dat == 0x03 ) && ( Rec_Dat == 0x01 ))
{
P40 = 0;
P00 = 0;
P2 = ~P2;
Uart2_SendStr( "打开成功!\r\n" );
}
else if( ( Rec_Dat == 0x01) && ( Rec_Dat == 0x02 ) && ( Rec_Dat == 0x03 ) && ( Rec_Dat == 0x04 ) && ( Rec_Dat == 0x05 ))
{
P40 = 1;
P00 = 1;
P2 = ~P2;
Uart2_SendStr( "关闭成功!\r\n" );
}
Rec_Num = 0;
}
}
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
楼主这种写法,keil编译器居然会产生死循环代码阻塞,离谱啊~
奇怪知识点++
SJMP自己跳自己:
SJMP自己跳自己:
正确代码:
ercircle 发表于 2025-5-15 00:31
楼主这种写法,keil编译器居然会产生死循环代码阻塞,离谱啊~
奇怪知识点++
#include "usart.h"
#include "io.h"
u8 Rec_Dat; //接收缓冲区
u8 Rec_Num = 0; //接收计数
bit B_TX2_Busy=0;
void Uart2_Isr(void) interrupt 8
{
if (S2CON & 0x02) //检测串口2发送中断
{
S2CON &= ~0x02; //清除串口2发送中断请求位
B_TX2_Busy = 0;
}
if (S2CON & 0x01) //检测串口2接收中断
{
S2CON &= ~0x01; //清除串口2接收中断请求位
//S2BUF
Rec_Dat = S2BUF;
}
}
void Uart2_Init(void) //9600bps@24.000MHz
{
P_SW2 |= 0x01; //UART2/USART2: RxD2(P4.6), TxD2
S2CON = 0x50; //8位数据,可变波特率
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0x8F; //设置定时初始值
T2H = 0xFD; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x01; //使能串口2中断
Rec_Num = 0;
B_TX2_Busy = 0;
}
void Uart2_SendStr( u8 *puts ) //串口数据发送函数
{
for (; *puts != 0;puts++) //遇到停止符0结束
{
S2BUF = *puts;
B_TX2_Busy = 1;
while(B_TX2_Busy);
}
}
void Usart2_RunTask(void)
{
if( Rec_Num >= 6 ) //是否接收到了6位以上的数据
{
if(( Rec_Dat == 0x02 ) && ( Rec_Dat == 0x02 ) ) //末尾判断
{
if( ( Rec_Dat == 0x05 ) && ( Rec_Dat == 0x04 ) && ( Rec_Dat == 0x03 ) && ( Rec_Dat == 0x01 ))
{
P40 = 0;
P00 = 0;
Uart2_SendStr( "打开成功!\r\n" );
}
else if( ( Rec_Dat == 0x01) && ( Rec_Dat == 0x02 ) && ( Rec_Dat == 0x03 ) && ( Rec_Dat == 0x04 ) && ( Rec_Dat == 0x05 ))
{
P40 = 1;
P00 = 1;
Uart2_SendStr( "关闭成功!\r\n" );
}
Rec_Num = 0;
}
}
}这个代码就可以
小熊熊 发表于 2025-5-15 10:08
#include "usart.h"
#include "io.h"
是的,换了存储类型汇编代码就变了
测试代码优化级别6以上会引发此问题:
问题复现工程:
建议标题改为keil编译优化导致代码死循环问题。
这问题已经和AiCube、串口没关系了。 使用volatile关键字修饰也可以规避此类问题 ercircle 发表于 2025-5-15 10:58
使用volatile关键字修饰也可以规避此类问题
#include "config.h"
u8 Rec_Dat; //接收缓冲区
u8 Rec_Num = 0; //接收计数
volatileB_TX2_Busy = 0;
好像还是不行 {:shuai:}