找回密码
 立即注册
查看: 457|回复: 34

串口问题 我在AIcube里面创建了1个串口发现永不了大哥们看看

[复制链接]
  • 打卡等级:偶尔看看II
  • 打卡总天数:26
  • 最近打卡:2025-06-16 10:35:34
已绑定手机

12

主题

65

回帖

330

积分

中级会员

积分
330
发表于 2025-5-14 22:21:12 | 显示全部楼层 |阅读模式
  1. #include "config.h"
  2. u8 Rec_Dat[50];                //接收缓冲区
  3. u8 Rec_Num = 0;                //接收计数
  4. B_TX2_Busy=0;
  5. //<<AICUBE_USER_INCLUDE_BEGIN>>
  6. // 在此添加用户头文件包含
  7. //<<AICUBE_USER_INCLUDE_END>>
  8. //<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
  9. // 在此添加用户全局变量定义、用户宏定义以及函数声明
  10. //<<AICUBE_USER_GLOBAL_DEFINE_END>>
  11. ////////////////////////////////////////
  12. // 串口2中断服务程序
  13. // 入口参数: 无
  14. // 函数返回: 无
  15. ////////////////////////////////////////
  16. void UART2_ISR(void) interrupt UART2_VECTOR
  17. {
  18.     //<<AICUBE_USER_UART2_ISR_CODE1_BEGIN>>
  19.     // 在此添加中断函数用户代码
  20.     if (UART2_CheckTxFlag())            //判断串口发送中断
  21.     {
  22.         UART2_ClearTxFlag();            //清除串口发送中断标志
  23.     }
  24.     if (UART2_CheckRxFlag())            //判断串口接收中断
  25.     {
  26.         UART2_ClearRxFlag();                 //清除串口接收中断标志
  27.                 Rec_Dat[Rec_Num++] = S2BUF;
  28.     }
  29.     //<<AICUBE_USER_UART2_ISR_CODE1_END>>
  30. }
  31. ////////////////////////////////////////
  32. // 串口2初始化函数
  33. // 入口参数: 无
  34. // 函数返回: 无
  35. ////////////////////////////////////////
  36. void UART2_Init(void)
  37. {
  38.        
  39. #ifdef BAUDRATE
  40. #undef BAUDRATE
  41. #endif
  42. #define BAUDRATE        (9600)
  43. #define T2_RELOAD       (65536 - (SYSCLK / BAUDRATE + 2) / 4)
  44.     UART2_SwitchP4243();                //设置串口数据端口: RxD2 (P4.2), TxD2 (P4.3)
  45. //  UART2_Timer2BRT();                  //串口2固定选择定时器2作为波特率发生器
  46.     TIMER2_TimerMode();                 //设置定时器2为定时模式
  47.     TIMER2_1TMode();                    //设置定时器2为1T模式
  48.     TIMER2_SetPrescale(0);              //设置定时器2的8位预分频
  49.     TIMER2_SetReload16(T2_RELOAD);      //设置定时器2的16位重载值
  50.     TIMER2_Run();                       //定时器2开始运行
  51.     UART2_EnableRx();                   //使能串口2接收数据
  52.     UART2_Mode1();                      //设置串口2为模式1 (8位数据可变波特率)
  53.     UART2_SetIntPriority(0);            //设置中断为最低优先级
  54.     UART2_EnableInt();                  //使能串口2中断
  55.     Rec_Num = 0;
  56.         B_TX2_Busy = 0;
  57.     //<<AICUBE_USER_UART2_INITIAL_BEGIN>>
  58.     // 在此添加用户初始化代码
  59.     //<<AICUBE_USER_UART2_INITIAL_END>>
  60. }
  61. void Uart2_SendStr( u8 *puts )                //串口数据发送函数
  62. {
  63.     for (; *puts != 0;  puts++)     //遇到停止符0结束
  64.     {
  65.         S2BUF = *puts;
  66.         B_TX2_Busy = 1;
  67.         while(B_TX2_Busy);
  68.     }       
  69. }
  70. void Usart2_RunTask(void)
  71. {
  72.         if( Rec_Num >= 6 )                //是否接收到了6位以上的数据
  73.         {
  74.                 if(( Rec_Dat[Rec_Num-1] == 0x02 ) && ( Rec_Dat[Rec_Num-2] == 0x02 ) )        //末尾判断
  75.                 {
  76.                         if( ( Rec_Dat[Rec_Num-6] == 0x05 ) && ( Rec_Dat[Rec_Num-5] == 0x04 ) && ( Rec_Dat[Rec_Num-4] == 0x03 ) && ( Rec_Dat[Rec_Num-3] == 0x01 )  )
  77.                         {
  78.                                 P40 = 0;
  79.                                 P00 = 0;
  80.                                 Uart2_SendStr( "打开成功!\r\n" );
  81.                         }
  82.                         else if( ( Rec_Dat[Rec_Num-7] == 0x01) && ( Rec_Dat[Rec_Num-6] == 0x02 ) && ( Rec_Dat[Rec_Num-5] == 0x03 ) && ( Rec_Dat[Rec_Num-4] == 0x04 ) && ( Rec_Dat[Rec_Num-3] == 0x05 )  )
  83.                         {
  84.                                 P40 = 1;
  85.                                 P00 = 1;
  86.                                 Uart2_SendStr( "关闭成功!\r\n" );
  87.                         }
  88.                         Rec_Num = 0;
  89.                 }
  90.         }
  91. }
  92. //<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
  93. // 在此添加用户函数实现代码
  94. //<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
复制代码


回复

使用道具 举报 送花

3

主题

717

回帖

145

积分

等待验证会员

积分
145
发表于 2025-5-14 22:23:00 | 显示全部楼层
针对您提供的串口通信代码及使用问题,经分析存在以下技术问题需要修正:

一、基础语法错误修正
1. 头文件引用错误
原始代码:#include "configh"
修正建议:检查头文件命名规范,确认是否存在拼写错误
修正代码:#include "config.h" // 注意文件扩展名完整性

2. 变量声明不规范
原始代码:BTX2Busy=0;
修正建议:补充变量类型声明
修正代码:u8 BTX2Busy = 0; // 添加数据类型说明

3. 接收缓冲区管理
原始代码:
  1. c
  2. u8 RecDat[50];
  3. u8 RecNum = 0;
复制代码
修正建议:增加缓冲区溢出保护机制
修正代码:
  1. c
  2. define MAXRECLEN 50
  3. u8 RecDat[MAXRECLEN];
  4. u8 RecNum = 0;
复制代码

二、中断服务程序优化
1. 发送中断冗余处理
原始代码:
  1. c
  2. if (UART2CheckTxFlag()) {
  3.     UART2ClearTxFlag();
  4. }
复制代码
优化建议:若无发送中断需求应关闭相关中断
修改方案:移除发送中断处理代码

2. 接收数据处理优化
原始代码:
  1. c
  2. RecDat[RecNum++] = S2BUF;
复制代码
改进方案:增加缓冲区边界检查
修正代码:
  1. c
  2. if(RecNum < MAXRECLEN){
  3.     RecDat[RecNum++] = S2BUF;
  4. } else {
  5.     // 可添加缓冲区溢出标志
  6. }
复制代码

三、串口初始化配置建议
建议补充完整初始化函数:
  1. c
  2. void UART2Init(void)
  3. {
  4.     UART2Configure(UART2Mode1,
  5.                    UART2BRTUseBGR,
  6.                    UART2BRT115200,
  7.                    UART2RIEnable | UART2TIEnable);
  8.    
  9.     EA = 1;         // 开启总中断
  10.     ENABLEUART2;   // 使能串口2
  11. }
复制代码

四、关键配置检查清单
1. 时钟源配置
确认系统时钟与波特率计算匹配:
  1. c
  2. // 示例波特率计算公式:
  3. // Baud = SYSclk / (256  [BRTValue])
复制代码

2. 引脚复用配置
检查GPIO初始化代码:
  1. c
  2. // 确保已配置UART2对应引脚模式
  3. GPIOInit(UART2TXPIN, GPIOModeAFPP);
  4. GPIOInit(UART2RXPIN, GPIOModeIPU);
复制代码

3. 中断向量确认
核对芯片手册确认:
  1. c
  2. // 不同芯片中断向量可能有差异
  3. void UART2ISR(void) interrupt X // X需与实际中断号一致
复制代码

五、调试建议
1. 基础测试流程:
  1. c
  2. // 发送测试函数
  3. void UART2SendTest(void)
  4. {
  5.     UART2SendString("AT\r\n");
  6.     while(BTX2Busy); // 等待发送完成
  7. }
  8. // 接收状态查询
  9. void CheckRecData(void)
  10. {
  11.     if(RecNum > 0){
  12.         UART2SendData(RecDat, RecNum);
  13.         RecNum = 0;
  14.     }
  15. }
复制代码

2. 示波器检测要点:
测量TX引脚信号波形
验证波特率误差(应

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2025-06-16 08:41:37
已绑定手机

67

主题

1919

回帖

4309

积分

荣誉版主

无情的代码机器

积分
4309
发表于 2025-5-15 00:26:19 | 显示全部楼层
  1. //<<AICUBE_USER_HEADER_REMARK_BEGIN>>
  2. ////////////////////////////////////////
  3. // 在此添加用户文件头说明信息
  4. // 文件名称: uart.c
  5. // 文件描述:
  6. // 文件版本: V1.0
  7. // 修改记录:
  8. //   1. (2025-05-12) 创建文件
  9. ////////////////////////////////////////
  10. //<<AICUBE_USER_HEADER_REMARK_END>>
  11. #include "config.h"
  12. //<<AICUBE_USER_INCLUDE_BEGIN>>
  13. // 在此添加用户头文件包含
  14. //<<AICUBE_USER_INCLUDE_END>>
  15. //<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
  16. // 在此添加用户全局变量定义、用户宏定义以及函数声明
  17. u8 B_TX2_Busy = 0;
  18. u8 Rec_Dat[50];                //接收缓冲区
  19. u8 Rec_Num = 0;                //接收计数
  20. //<<AICUBE_USER_GLOBAL_DEFINE_END>>
  21. BOOL fPrintfBusy;
  22. ////////////////////////////////////////
  23. // 串口2中断服务程序
  24. // 入口参数: 无
  25. // 函数返回: 无
  26. ////////////////////////////////////////
  27. void UART2_ISR(void) interrupt UART2_VECTOR
  28. {
  29.     //<<AICUBE_USER_UART2_ISR_CODE1_BEGIN>>
  30.     // 在此添加中断函数用户代码
  31.     if (UART2_CheckTxFlag())            //判断串口发送中断
  32.     {
  33.         UART2_ClearTxFlag();            //清除串口发送中断标志
  34.         fPrintfBusy = 0;                //清除printf发送忙标志
  35.                         B_TX2_Busy = 0;
  36.     }
  37.     if (UART2_CheckRxFlag())            //判断串口接收中断
  38.     {
  39.         UART2_ClearRxFlag();            //清除串口接收中断标志
  40.                         Rec_Dat[Rec_Num++] = S2BUF;
  41.     }
  42.     //<<AICUBE_USER_UART2_ISR_CODE1_END>>
  43. }
  44. ////////////////////////////////////////
  45. // 串口2初始化函数
  46. // 入口参数: 无
  47. // 函数返回: 无
  48. ////////////////////////////////////////
  49. void UART2_Init(void)
  50. {
  51. #ifdef BAUDRATE
  52. #undef BAUDRATE
  53. #endif
  54. #define BAUDRATE        (9600)
  55. #define T2_RELOAD       (65536 - (SYSCLK / BAUDRATE + 2) / 4)
  56.     UART2_SwitchP4243();                //设置串口数据端口: RxD2 (P4.2), TxD2 (P4.3)
  57. //  UART2_Timer2BRT();                  //串口2固定选择定时器2作为波特率发生器
  58.     TIMER2_TimerMode();                 //设置定时器2为定时模式
  59.     TIMER2_1TMode();                    //设置定时器2为1T模式
  60.     TIMER2_SetPrescale(0);              //设置定时器2的8位预分频
  61.     TIMER2_SetReload16(T2_RELOAD);      //设置定时器2的16位重载值
  62.     TIMER2_Run();                       //定时器2开始运行
  63.     UART2_EnableRx();                   //使能串口2接收数据
  64.     UART2_Mode1();                      //设置串口2为模式1 (8位数据可变波特率)
  65.     UART2_SetIntPriority(0);            //设置中断为最低优先级
  66.     UART2_EnableInt();                  //使能串口2中断
  67.     fPrintfBusy = 0;                    //清除发送数据忙标志
  68.     //<<AICUBE_USER_UART2_INITIAL_BEGIN>>
  69.     // 在此添加用户初始化代码
  70.                     Rec_Num = 0;
  71.         B_TX2_Busy = 0;
  72.                                 P2 = 0x0F;
  73.     //<<AICUBE_USER_UART2_INITIAL_END>>
  74. }
  75. ////////////////////////////////////////
  76. // 重写printf字符发送重定向函数
  77. // 入口参数: dat (printf函数待打印的字符)
  78. // 函数返回: 需要返回入口参数的数据
  79. ////////////////////////////////////////
  80. char putchar (char dat)                 //将串口2和printf函数绑定
  81. {
  82.     while (fPrintfBusy);
  83.     UART2_SendData(dat);
  84.     fPrintfBusy = 1;
  85.     return dat;
  86. }
  87. //<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
  88. // 在此添加用户函数实现代码
  89. void Uart2_SendStr( u8 *puts )                //串口数据发送函数
  90. {
  91.     for (; *puts != 0;  puts++)     //遇到停止符0结束
  92.     {
  93.                                
  94.                                 while(B_TX2_Busy);
  95.                                 S2BUF = (*puts);
  96.                                 B_TX2_Busy = 1;  
  97.                        
  98.     }        
  99. }
  100. void Usart2_RunTask(void)
  101. {
  102.         if( Rec_Num >= 6 )                //是否接收到了6位以上的数据
  103.         {
  104.                 if(( Rec_Dat[Rec_Num-1] == 0x02 ) && ( Rec_Dat[Rec_Num-2] == 0x02 ) )        //末尾判断
  105.                 {
  106.                         if( ( Rec_Dat[Rec_Num-6] == 0x05 ) && ( Rec_Dat[Rec_Num-5] == 0x04 ) && ( Rec_Dat[Rec_Num-4] == 0x03 ) && ( Rec_Dat[Rec_Num-3] == 0x01 )  )
  107.                         {
  108.                                 P40 = 0;
  109.                                 P00 = 0;
  110.                                                                                                                                 P2 = ~P2;
  111.                                 Uart2_SendStr( "打开成功!\r\n" );
  112.                         }
  113.                         else if( ( Rec_Dat[Rec_Num-7] == 0x01) && ( Rec_Dat[Rec_Num-6] == 0x02 ) && ( Rec_Dat[Rec_Num-5] == 0x03 ) && ( Rec_Dat[Rec_Num-4] == 0x04 ) && ( Rec_Dat[Rec_Num-3] == 0x05 )  )
  114.                         {
  115.                                 P40 = 1;
  116.                                 P00 = 1;
  117.                                                                                                                                 P2 = ~P2;
  118.                                 Uart2_SendStr( "关闭成功!\r\n" );
  119.                         }
  120.                         Rec_Num = 0;
  121.                 }
  122.         }
  123. }
  124. //<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
复制代码


三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2025-06-16 08:41:37
已绑定手机

67

主题

1919

回帖

4309

积分

荣誉版主

无情的代码机器

积分
4309
发表于 2025-5-15 00:31:38 | 显示全部楼层
楼主这种写法,keil编译器居然会产生死循环代码阻塞,离谱啊~
奇怪知识点++



SJMP自己跳自己:
截图202505150028012895.jpg

SJMP自己跳自己:
截图202505150028527518.jpg

正确代码:
截图202505150029371455.jpg

三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:26
  • 最近打卡:2025-06-16 10:35:34
已绑定手机

12

主题

65

回帖

330

积分

中级会员

积分
330
发表于 2025-5-15 10:08:33 | 显示全部楼层
erci*** 发表于 2025-5-15 00:31
楼主这种写法,keil编译器居然会产生死循环代码阻塞,离谱啊~
奇怪知识点++

#include "usart.h"
#include "io.h"


u8 Rec_Dat[50];                //接收缓冲区
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[Rec_Num++] = 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[Rec_Num-1] == 0x02 ) && ( Rec_Dat[Rec_Num-2] == 0x02 ) )        //末尾判断
                {
                        if( ( Rec_Dat[Rec_Num-6] == 0x05 ) && ( Rec_Dat[Rec_Num-5] == 0x04 ) && ( Rec_Dat[Rec_Num-4] == 0x03 ) && ( Rec_Dat[Rec_Num-3] == 0x01 )  )
                        {
                                P40 = 0;
                                P00 = 0;
                                Uart2_SendStr( "打开成功!\r\n" );
                        }
                        else if( ( Rec_Dat[Rec_Num-7] == 0x01) && ( Rec_Dat[Rec_Num-6] == 0x02 ) && ( Rec_Dat[Rec_Num-5] == 0x03 ) && ( Rec_Dat[Rec_Num-4] == 0x04 ) && ( Rec_Dat[Rec_Num-3] == 0x05 )  )
                        {
                                P40 = 1;
                                P00 = 1;
                                Uart2_SendStr( "关闭成功!\r\n" );
                        }
                        Rec_Num = 0;
                }
        }
}[/code]  这个代码就可以

点评

是的,换了存储类型汇编代码就变了 [attachimg]98727[/attachimg]  详情 回复 发表于 2025-5-15 10:32
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2025-06-16 08:41:37
已绑定手机

67

主题

1919

回帖

4309

积分

荣誉版主

无情的代码机器

积分
4309
发表于 2025-5-15 10:32:37 | 显示全部楼层
小*** 发表于 2025-5-15 10:08
#include "usart.h"
#include "io.h"

是的,换了存储类型汇编代码就变了
截图202505151032252741.jpg
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2025-06-16 08:41:37
已绑定手机

67

主题

1919

回帖

4309

积分

荣誉版主

无情的代码机器

积分
4309
发表于 2025-5-15 10:46:03 | 显示全部楼层

测试代码优化级别6以上会引发此问题:
截图202505151045582973.jpg
问题复现工程:
ai8051u-32bit.zip (39.92 KB, 下载次数: 2)
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2025-06-16 08:41:37
已绑定手机

67

主题

1919

回帖

4309

积分

荣誉版主

无情的代码机器

积分
4309
发表于 2025-5-15 10:49:06 | 显示全部楼层
建议标题改为keil编译优化导致代码死循环问题。
这问题已经和AiCube、串口没关系了。
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:208
  • 最近打卡:2025-06-16 08:41:37
已绑定手机

67

主题

1919

回帖

4309

积分

荣誉版主

无情的代码机器

积分
4309
发表于 2025-5-15 10:58:13 | 显示全部楼层
使用volatile关键字修饰也可以规避此类问题
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看II
  • 打卡总天数:26
  • 最近打卡:2025-06-16 10:35:34
已绑定手机

12

主题

65

回帖

330

积分

中级会员

积分
330
发表于 2025-5-15 11:21:12 | 显示全部楼层
erci*** 发表于 2025-5-15 10:58
使用volatile关键字修饰也可以规避此类问题
  1. #include "config.h"
  2. u8 Rec_Dat[50];                //接收缓冲区
  3. u8 Rec_Num = 0;                //接收计数
  4. volatile  B_TX2_Busy = 0;
复制代码
好像还是不行

点评

不加类型声明,编译器默认是当16位数处理,不过也能执行下去 [attachimg]98735[/attachimg] [attachimg]98738[/attachimg]  详情 回复 发表于 2025-5-15 11:42
还有你这个B_TX2_Busy 连个类型都没声明噢,居然可以编译通过我也服了。。。。 加了类型声明和volatile关键字汇编里没死循环了 [attachimg]98733[/attachimg]  详情 回复 发表于 2025-5-15 11:29
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-16 18:22 , Processed in 0.226231 second(s), 98 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表