[其他ST产品] 串口UART模式中断收发数据——华大HC32F460

[复制链接]
 楼主| xdvca 发表于 2023-10-27 12:21 | 显示全部楼层 |阅读模式
基础知识
USART1基地址为:0x4001_D000

USART2基地址为:0x4001_D400

USART3基地址为:0x4002_1000

USART4基地址为:0x4002_1400

引脚映射:华大HC32F460与STM32F10x的区别在于:HC32F460有64个引脚支持Fun32~63功能选择,即我们说的重映射,Fun32~63主要为串行通信功能(包含USART,SPI, I2C, I2S, CAN);分为了Fun_Grp1、Fun_Grp2。具体可看<数据手册-引脚功能表>。而STM32F10x的GPIO引脚重映射是有规定的,所以华大的用起来比较灵活。

接收超时定时器通道选择
TIMEOUT 计数器采用Timer0 模块的计数器,具体对应关系如下:
USART1:Timer0 Unit1 A 通道
USART2:Timer0 Unit1 B 通道
USART3:Timer0 Unit2 A 通道
USART4:Timer0 Unit2 B 通道

USART串口通信的基本参数配置为一致,也是最常用的模式

UsartIntClkCkOutput:时钟为内部时钟输出

UsartClkDiv_16:16分频

UsartDataBits8:8位数据位

UsartDataLsbFirst:低位在前

UsartOneStopBit:1位停止位

UsartParityNone:无奇偶校验

UsartSamleBit8:8位采样

UsartStartBitFallEdge:起始位检测下降沿

UsartRtsEnable:RTS允许

 楼主| xdvca 发表于 2023-10-27 12:22 | 显示全部楼层
代码实现
本样例主要展示USART外设配置为USART外设配置为UART模式时通过中断方式收发数据。

串口助手软件配置端口参数:

波特率:115200

数据位:8

校验位:None

停止位:1

宏定义
  1. /* USART channel definition */
  2. #define USART_CH                         (M4_USART4)
  3. /* USART baudrate definition */
  4. #define USART_BAUDRATE                  (115200ul)
  5. /* USART Interrupt Number */
  6. #define USART_RX_IRQn                   (Int000_IRQn)
  7. #define USART_ERR_IRQn                  (Int001_IRQn)
  8. #define USART_RTO_IRQn                  (Int002_IRQn)
  9. #define USART_TX_IRQn                   (Int003_IRQn)
  10. #define USART_CMP_IRQn                  (Int004_IRQn)
  11. /* USART RX Port/Pin definition */
  12. #define USART_RX_PORT                   (PortE)
  13. #define USART_RX_PIN                    (Pin14)
  14. #define USART_RX_FUNC                   (Func_Usart4_Rx)

  15. #define USART_TX_PORT                   (PortE)
  16. #define USART_TX_PIN                    (Pin15)
  17. #define USART_TX_FUNC                   (Func_Usart4_Tx)

  18. /* USART interrupt number  */
  19. #define USART_RI_NUM                    (INT_USART4_RI)
  20. #define USART_EI_NUM                    (INT_USART4_EI)
  21. #define USART_RTO_NUM                   (INT_USART4_RTO)
  22. #define USART_TI_NUM                    (INT_USART4_TI)
  23. #define USART_TCI_NUM                   (INT_USART4_TCI)


  24. #define set                              Ok
  25. #define reset                            Error

  26. #define ENCODER_LEN      6

  27. static uint16_t u16RxData;
 楼主| xdvca 发表于 2023-10-27 12:23 | 显示全部楼层
串口初始化
  1. /*串口初始化*/
  2. void UART_Init(void)
  3. {
  4.     en_result_t enRet = Ok;
  5.     stc_irq_regi_conf_t stcIrqRegiCfg;
  6.    
  7.     /*配置串口使用的时钟和基本通信配置*/
  8.     const stc_usart_uart_init_t stcInitCfg = {
  9.         UsartIntClkCkOutput,
  10.         UsartClkDiv_16,//时钟分频
  11.         UsartDataBits8,
  12.         UsartDataLsbFirst,
  13.         UsartOneStopBit,
  14.         UsartParityNone,
  15.         UsartSamleBit8,
  16.         UsartStartBitFallEdge,
  17.         UsartRtsEnable,
  18.     };
  19.    
  20.     /*打开时钟*/
  21.     PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_USART4, Enable);
  22.    
  23.     /*配置相应的IO作为串口的RX引脚*/
  24.     PORT_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_FUNC, Disable);
  25.     PORT_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_FUNC, Disable);

  26.     /*初始化串口配置*/
  27.     enRet = USART_UART_Init(USART_CH, &stcInitCfg);
  28.     while (enRet != Ok);
  29.     /*串口波特率设置*/
  30.     enRet = USART_SetBaudrate(USART_CH, USART_BAUDRATE);
  31.     while (enRet != Ok);
  32.    
  33.     /*设置串口接收中断*/
  34.     stcIrqRegiCfg.enIRQn = USART_RX_IRQn;
  35.     stcIrqRegiCfg.pfnCallback = &Usart4RxIrqCallback;
  36.     stcIrqRegiCfg.enIntSrc = USART_RI_NUM;
  37.     enIrqRegistration(&stcIrqRegiCfg);
  38.     NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
  39.     NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
  40.     NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
  41.    
  42.     /*设置串口接收错误中断*/
  43.     stcIrqRegiCfg.enIRQn = USART_ERR_IRQn;             /* 中断号,可通过参考手册查阅对应的中断号 */
  44.     stcIrqRegiCfg.pfnCallback = &Usart4ErrIrqCallback;  /* 中断回调函数 */
  45.     stcIrqRegiCfg.enIntSrc = USART_EI_NUM;             /* 错误中断向量号,可通过参考手册查阅对应的中断号*/
  46.     enIrqRegistration(&stcIrqRegiCfg);
  47.     NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);/* 配置中断优先级 */
  48.     NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);         /*先清一下这个中断的标志位(置零)*/
  49.     NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);               /*在使能这个中断*/
  50.    
  51.     /*设置接收超时中断*/
  52.     stcIrqRegiCfg.enIRQn = USART_RTO_IRQn;                     /* 中断号,可通过参考手册查阅对应的中断号 */
  53.     stcIrqRegiCfg.pfnCallback = &Usart4TimeoutIrqCallback;      /* 中断回调函数 */
  54.     stcIrqRegiCfg.enIntSrc = INT_USART4_RTO;                    /* 错误中断向量号,可通过参考手册查阅对应的中断号*/
  55.     enIrqRegistration(&stcIrqRegiCfg);
  56.     NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);   /* 配置中断优先级 */
  57.     NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);                         /*先清一下这个中断的标志位(置零)*/
  58.     NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);                               /*在使能这个中断*/
  59.    
  60.     /*设置串口发送中断*/
  61.     stcIrqRegiCfg.enIRQn = USART_TX_IRQn;               /* 中断号,可通过参考手册查阅对应的中断号 */
  62.     stcIrqRegiCfg.pfnCallback = &UsartTxIrqCallback;     /* 中断回调函数 */
  63.     stcIrqRegiCfg.enIntSrc = USART_TI_NUM;              /* 错误中断向量号,可通过参考手册查阅对应的中断号*/
  64.     enIrqRegistration(&stcIrqRegiCfg);
  65.     NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);   /* 配置中断优先级 */
  66.     NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);                          /*先清一下这个中断的标志位(置零)*/
  67.     NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);                                /*在使能这个中断*/
  68.    
  69.     /*设置串口发送完成中断*/
  70.     stcIrqRegiCfg.enIRQn = USART_CMP_IRQn;                             /* 中断号,可通过参考手册查阅对应的中断号 */
  71.     stcIrqRegiCfg.pfnCallback = &UsartTxCmpltIrqCallback;               /* 中断回调函数 */
  72.     stcIrqRegiCfg.enIntSrc = USART_TCI_NUM;                            /* 错误中断向量号,可通过参考手册查阅对应的中断号*/
  73.     enIrqRegistration(&stcIrqRegiCfg);
  74.     NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);   /* 配置中断优先级 */
  75.     NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);                         /*先清一下这个中断的标志位(置零)*/
  76.     NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);                               /*在使能这个中断*/
  77.    
  78.    
  79.     USART_FuncCmd(USART_CH, UsartTx, Enable);//使能发送
  80.     USART_FuncCmd(USART_CH, UsartRx, Enable);//使能接收
  81.     USART_FuncCmd(USART_CH, UsartRxInt, Enable);//使能接收中断
  82.     USART_FuncCmd(USART_CH, UsartTimeOut, Enable);//使能超时
  83.     USART_FuncCmd(USART_CH, UsartTimeOutInt, Enable);//使能超时中断
  84. }
 楼主| xdvca 发表于 2023-10-27 12:24 | 显示全部楼层
定时器初始化
  1. /*usart timer0初始化*/
  2. static void Usart_Timer0_Init(void)
  3. {
  4.         stc_clk_freq_t stcClkTmp;
  5.         stc_tim0_base_init_t stcTimerCfg;
  6.         stc_tim0_trigger_init_t StcTimer0TrigInit;

  7.         MEM_ZERO_STRUCT(stcClkTmp);
  8.         MEM_ZERO_STRUCT(stcTimerCfg);
  9.         MEM_ZERO_STRUCT(StcTimer0TrigInit);

  10.         /* Timer0 peripheral enable */
  11.         PWC_Fcg2PeriphClockCmd(PWC_FCG2_PERIPH_TIM02, Enable);

  12.         /* Clear CNTAR register for channel A */
  13. //        TIMER0_WriteCntReg(LCD_TMR_UNIT, Tim0_ChannelA, 0u);
  14.         TIMER0_WriteCntReg(M4_TMR02, Tim0_ChannelB, 0u);

  15.         /* Config register for channel A */
  16.         stcTimerCfg.Tim0_CounterMode = Tim0_Async;
  17.         stcTimerCfg.Tim0_AsyncClockSource = Tim0_XTAL32;
  18.         stcTimerCfg.Tim0_ClockDivision = Tim0_ClkDiv8;
  19.         stcTimerCfg.Tim0_CmpValue = 32000u;
  20.         TIMER0_BaseInit(M4_TMR02, Tim0_ChannelB, &stcTimerCfg);

  21.         /* Clear compare flag */
  22.         TIMER0_ClearFlag(M4_TMR02, Tim0_ChannelB);

  23.         /* Config timer0 hardware trigger */
  24.         StcTimer0TrigInit.Tim0_InTrigEnable = false;
  25.         StcTimer0TrigInit.Tim0_InTrigClear = true;
  26.         StcTimer0TrigInit.Tim0_InTrigStart = true;
  27.         StcTimer0TrigInit.Tim0_InTrigStop = false;
  28.         TIMER0_HardTriggerInit(M4_TMR02, Tim0_ChannelB, &StcTimer0TrigInit);
  29. }
 楼主| xdvca 发表于 2023-10-27 12:24 | 显示全部楼层
时钟初始化
  1. /*时钟初始化*/
  2. static void ClkInit(void)
  3. {
  4.     stc_clk_xtal_cfg_t   stcXtalCfg;
  5.     stc_clk_mpll_cfg_t   stcMpllCfg;
  6.     en_clk_sys_source_t  enSysClkSrc;
  7.     stc_clk_sysclk_cfg_t stcSysClkCfg;

  8.     MEM_ZERO_STRUCT(enSysClkSrc);
  9.     MEM_ZERO_STRUCT(stcSysClkCfg);
  10.     MEM_ZERO_STRUCT(stcXtalCfg);
  11.     MEM_ZERO_STRUCT(stcMpllCfg);

  12.     /* Set bus clk div. */
  13.     stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;  /* Max 168MHz */
  14.     stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  /* Max 84MHz */
  15.     stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  /* Max 168MHz */
  16.     stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  /* Max 84MHz */
  17.     stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  /* Max 60MHz */
  18.     stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  /* Max 42MHz */
  19.     stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  /* Max 84MHz */
  20.     CLK_SysClkConfig(&stcSysClkCfg);

  21.     /* Switch system clock source to MPLL. */
  22.     /* Use Xtal as MPLL source. */
  23.     stcXtalCfg.enMode = ClkXtalModeOsc;
  24.     stcXtalCfg.enDrv = ClkXtalLowDrv;
  25.     stcXtalCfg.enFastStartup = Enable;
  26.     CLK_XtalConfig(&stcXtalCfg);
  27.     CLK_XtalCmd(Enable);

  28.     /* MPLL config. */
  29.     stcMpllCfg.pllmDiv = 1ul;
  30.     stcMpllCfg.plln = 50ul;
  31.     stcMpllCfg.PllpDiv = 4ul;
  32.     stcMpllCfg.PllqDiv = 4ul;
  33.     stcMpllCfg.PllrDiv = 4ul;
  34.     CLK_SetPllSource(ClkPllSrcXTAL);
  35.     CLK_MpllConfig(&stcMpllCfg);

  36.     /* flash read wait cycle setting */
  37.     EFM_Unlock();
  38.     EFM_SetLatency(EFM_LATENCY_5);
  39.     EFM_Lock();

  40.     /* Enable MPLL. */
  41.     CLK_MpllCmd(Enable);

  42.     /* Wait MPLL ready. */
  43.     while (Set != CLK_GetFlagStatus(ClkFlagMPLLRdy))
  44.     {
  45.     }

  46.     /* Switch system clock source to MPLL. */
  47.     CLK_SetSysClkSource(CLKSysSrcMPLL);
  48. }
 楼主| xdvca 发表于 2023-10-27 12:25 | 显示全部楼层
相关中断回调函数
串口发送空中断,串口发送完成中断
串口接收中断,串口接收错误中断,串口接收超时中断
  1. /*串口接收中断回调函数RX*/
  2. static void Usart4RxIrqCallback(void)
  3. {
  4.     if (Set == USART_GetStatus(USART_CH, UsartRxNoEmpty)){
  5.         u16RxData = USART_RecData(USART_CH);//取出数据
  6.         buffer = u16RxData;
  7.         USART_FuncCmd(USART_CH, UsartTx, Enable);
  8.         USART_SendData(USART_CH, buffer);
  9.   }
  10. }

  11. /*串口接收错误中断回调函数RX ERR*/
  12. static void Usart4ErrIrqCallback(void)
  13. {
  14.     if (Set == USART_GetStatus(USART_CH, UsartFrameErr))
  15.       USART_ClearStatus(USART_CH, UsartFrameErr);
  16.    
  17.     if (Set == USART_GetStatus(USART_CH, UsartParityErr))
  18.       USART_ClearStatus(USART_CH, UsartParityErr);
  19.    
  20.     if (Set == USART_GetStatus(USART_CH, UsartOverrunErr))
  21.       USART_ClearStatus(USART_CH, UsartOverrunErr);
  22.    
  23.     if (Set == USART_GetStatus(USART_CH, UsartRxNoEmpty))
  24.       USART_ClearStatus(USART_CH, UsartRxNoEmpty);
  25.    
  26.     if (Set == USART_GetStatus(USART_CH, UsartTxComplete))
  27.       USART_ClearStatus(USART_CH, UsartTxComplete);
  28.    
  29.     if (Set == USART_GetStatus(USART_CH, UsartTxEmpty))
  30.       USART_ClearStatus(USART_CH, UsartTxEmpty);
  31.    
  32.     if (Set == USART_GetStatus(USART_CH, UsartRxTimeOut))
  33.       USART_ClearStatus(USART_CH, UsartRxTimeOut);
  34.    
  35.     if (Set == USART_GetStatus(USART_CH, UsartRxMpb))
  36.       USART_ClearStatus(USART_CH, UsartRxMpb);
  37. }

  38. /*串口接收超时中断回调RX TIMEOUT*/
  39. static void Usart4TimeoutIrqCallback(void)
  40. {
  41.     TIMER0_Cmd(M4_TMR02, Tim0_ChannelB,Disable);
  42.     USART_ClearStatus(USART_CH, UsartRxTimeOut);
  43. }

  44. /*串口发送中断回调函数TX*/
  45. static void UsartTxIrqCallback(void)
  46. {
  47.     USART_SendData(USART_CH, u16RxData);
  48.     USART_FuncCmd(USART_CH, UsartTxEmptyInt, Disable);       
  49.     USART_FuncCmd(USART_CH, UsartTxCmpltInt, Enable);
  50. }

  51. /*串口发送完成中断回调函数TX CAM*/
  52. static void UsartTxCmpltIrqCallback(void)
  53. {
  54.     USART_FuncCmd(USART_CH,UsartTx,Disable);
  55.     USART_FuncCmd(USART_CH,UsartTxCmpltInt,Disable);
  56. }
 楼主| xdvca 发表于 2023-10-27 12:25 | 显示全部楼层
mian函数
  1. static uint8_t u8RxData;

  2. int32_t main(void)
  3. {
  4.     //时钟初始化
  5.     ClkInit();
  6.     //串口初始化
  7.     UART_Init();
  8.     //定时器0初始化
  9.     Usart_Timer0_Init();
  10.         
  11.     while(1){
  12.       ;
  13.     }
  14.         
  15. }
 楼主| xdvca 发表于 2023-10-27 12:26 | 显示全部楼层
问题
1.有个坑
USART的波特率需将串口时钟频率降低。
62036653b3bda8b7d5.png
 楼主| xdvca 发表于 2023-10-27 12:27 | 显示全部楼层
49826653b3bf5dd17e.png

在我的代码里,波特率设置的USART_SetBaudrate的SetUartBaudrate里

25427653b3c0b0cd47.png
如果只有一个B = u32Baudrate;就会跳过???????

所以我多写了一个B = u32Baudrate;

防止代码在此发生错误
 楼主| xdvca 发表于 2023-10-27 12:27 | 显示全部楼层
结果
96047653b3c2d587ea.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

452

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部