小熊熊 发表于 2025-5-14 22:21:12

串口问题 我在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>>




国芯人工智能 发表于 2025-5-14 22:23:00

针对您提供的串口通信代码及使用问题,经分析存在以下技术问题需要修正:

一、基础语法错误修正
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引脚信号波形
验证波特率误差(应

[本文内容由国芯人工智能辅助生成,仅供参考]

ercircle 发表于 2025-5-15 00:26:19

//<<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>>




ercircle 发表于 2025-5-15 00:31:38

楼主这种写法,keil编译器居然会产生死循环代码阻塞,离谱啊~
奇怪知识点++



SJMP自己跳自己:


SJMP自己跳自己:


正确代码:


小熊熊 发表于 2025-5-15 10:08:33

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;
                }
        }
}这个代码就可以

ercircle 发表于 2025-5-15 10:32:37

小熊熊 发表于 2025-5-15 10:08
#include "usart.h"
#include "io.h"



是的,换了存储类型汇编代码就变了

ercircle 发表于 2025-5-15 10:46:03


测试代码优化级别6以上会引发此问题:

问题复现工程:

ercircle 发表于 2025-5-15 10:49:06

建议标题改为keil编译优化导致代码死循环问题。
这问题已经和AiCube、串口没关系了。

ercircle 发表于 2025-5-15 10:58:13

使用volatile关键字修饰也可以规避此类问题

小熊熊 发表于 2025-5-15 11:21:12

ercircle 发表于 2025-5-15 10:58
使用volatile关键字修饰也可以规避此类问题


#include "config.h"
u8 Rec_Dat;                //接收缓冲区
u8 Rec_Num = 0;                //接收计数
volatileB_TX2_Busy = 0;
好像还是不行 {:shuai:}
页: [1] 2 3 4
查看完整版本: 串口问题 我在AIcube里面创建了1个串口发现永不了大哥们看看