[方案相关] 小华HC32F448串口使用

[复制链接]
2546|18
 楼主| t61000 发表于 2023-12-20 14:37 | 显示全部楼层 |阅读模式
1. 串口GPIO配置
端口号和Pin脚号跟STM32没什么区别。

串口复用功能跟STM32大不一样。

如下图,选自HC32F448 表 2-1 引脚功能表。

1)每个管脚都有对应的管脚名称、中断号,以及功能号

2)调试口默认为TRACE/JTAG功能号,若要使能普通GPIO功能则要关闭调试功能

3)非调试口默认功能号为Func0,即普通GPIO功能。Func2到Func11为定时器或时钟功能,Func12为EXMC/TIMA功能

4)Func32~63为通用复用功能-分为两组,对于同一组的IO,可以配置为UART/I2C/SPI/CAN 4组功能,且Rx/Tx可以互换。而不是像STM32那样,每个IO的复用功能是固定的,对应通讯线必须一一选对。

1984165828ba215374.png

8002765828bac7df13.png

 楼主| t61000 发表于 2023-12-20 14:38 | 显示全部楼层
如下,硬件选择了PB0和PA7作为串口通讯脚,可以在FG1任意选择一个可用串口使用。
  1. #define USART_RX_PORT                   (GPIO_PORT_B)   /* PB0: USART2_RX */
  2. #define USART_RX_PIN                    (GPIO_PIN_00)
  3. #define USART_RX_GPIO_FUNC              (GPIO_FUNC_37)
  4. #define USART_TX_PORT                   (GPIO_PORT_A)   /* PA7: USART2_TX */
  5. #define USART_TX_PIN                    (GPIO_PIN_07)
  6. #define USART_TX_GPIO_FUNC              (GPIO_FUNC_36)

  7. static void UartGpioConfig(void)
  8. {
  9.         GPIO_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_GPIO_FUNC);
  10.     GPIO_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_GPIO_FUNC);
  11. }
 楼主| t61000 发表于 2023-12-20 14:42 | 显示全部楼层
2. 串口波特率配置
  1. static void UartBaudConfig(void)
  2. {
  3.         USART_FCG_ENABLE();
  4.         stc_usart_uart_init_t stcUartInit;
  5.         (void)USART_UART_StructInit(&stcUartInit);
  6.     stcUartInit.u32ClockDiv = USART_CLK_DIV64;
  7.     stcUartInit.u32CKOutput = USART_CK_OUTPUT_ENABLE;
  8.     stcUartInit.u32Baudrate = USART_BAUDRATE;
  9.     stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT;
  10.     USART_UART_Init(USART_UNIT, &stcUartInit, NULL);
  11. }
 楼主| t61000 发表于 2023-12-20 14:43 | 显示全部楼层
3. 串口接收超时配置
小华HC32F4串口支持的中断与STM32大有不同:

1)HC32 接收数据寄存器满中断,在收到1个字节时就会触发。等同于STM32的RXNE。名字不同

2)HC32 TIMEOUT中断,等同于STM32的空闲中断 IDLE 。HC32通过关联定时器直接配置超时时间,比STM32更加简便。
 楼主| t61000 发表于 2023-12-20 14:43 | 显示全部楼层
 楼主| t61000 发表于 2023-12-20 14:44 | 显示全部楼层
定时器Timer0被专门用来做串口的计时器,板子用的串口2,所以定时器要配置Timer0_1 B 。

9122465828d35afa0c.png
 楼主| t61000 发表于 2023-12-20 14:44 | 显示全部楼层
//串口接收超时设置·关联定时器
#define USART_TIMEOUT_BITS              (5000U)
#define TMR0_UNIT                       (CM_TMR0_1)
#define TMR0_CH                         (TMR0_CH_B)
#define TMR0_FCG_ENABLE()               (FCG_Fcg2PeriphClockCmd(FCG2_PERIPH_TMR0_1, ENABLE))

/*
* TMR0_Config()
* 配置串口接收超时
*/
static void TMR0_Config(void)
{
    uint16_t u16Div;
    uint16_t u16Delay;
    uint16_t u16CompareValue;
    stc_tmr0_init_t stcTmr0Init;

    TMR0_FCG_ENABLE();

    /* Initialize TMR0 base function. */
    stcTmr0Init.u32ClockSrc = TMR0_CLK_SRC_XTAL32;
    stcTmr0Init.u32ClockDiv = TMR0_CLK_DIV8;
    stcTmr0Init.u32Func     = TMR0_FUNC_CMP;
    if (TMR0_CLK_DIV1 == stcTmr0Init.u32ClockDiv) {
        u16Delay = 7U;
    } else if (TMR0_CLK_DIV2 == stcTmr0Init.u32ClockDiv) {
        u16Delay = 5U;
    } else if ((TMR0_CLK_DIV4 == stcTmr0Init.u32ClockDiv) || \
               (TMR0_CLK_DIV8 == stcTmr0Init.u32ClockDiv) || \
               (TMR0_CLK_DIV16 == stcTmr0Init.u32ClockDiv)) {
        u16Delay = 3U;
    } else {
        u16Delay = 2U;
    }

    u16Div = (uint16_t)1U << (stcTmr0Init.u32ClockDiv >> TMR0_BCONR_CKDIVA_POS);
    u16CompareValue = ((USART_TIMEOUT_BITS + u16Div - 1U) / u16Div) - u16Delay;
    stcTmr0Init.u16CompareValue = u16CompareValue;
    (void)TMR0_Init(TMR0_UNIT, TMR0_CH, &stcTmr0Init);

    TMR0_HWStartCondCmd(TMR0_UNIT, TMR0_CH, ENABLE);
    TMR0_HWClearCondCmd(TMR0_UNIT, TMR0_CH, ENABLE);
}
 楼主| t61000 发表于 2023-12-20 14:44 | 显示全部楼层
4. 串口中断注册

  1. #define USART_RX_ERR_IRQn               (INT005_IRQn)
  2. #define USART_RX_ERR_INT_SRC            (INT_SRC_USART2_EI)
  3. #define USART_RX_FULL_IRQn              (INT006_IRQn)
  4. #define USART_RX_FULL_INT_SRC           (INT_SRC_USART2_RI)
  5. #define USART1_RX_TIMEOUT_IRQn          (INT007_IRQn)
  6. #define USART1_RX_TIMEOUT_INT_SRC       (INT_SRC_USART2_RTO)

  7. static void USART_RxFull_IrqCallback(void);
  8. static void USART_RxError_IrqCallback(void);
  9. static void USART_RxTimeout_IrqCallback(void);

  10. static void RegisterIrq(void)
  11. {
  12.         stc_irq_signin_config_t stcIrqSigninConfig;
  13.        
  14.         /* Register RX full IRQ handler. */
  15.     stcIrqSigninConfig.enIRQn = USART_RX_FULL_IRQn;
  16.     stcIrqSigninConfig.enIntSrc = USART_RX_FULL_INT_SRC;
  17.     stcIrqSigninConfig.pfnCallback = &USART_RxFull_IrqCallback;
  18.     (void)INTC_IrqSignIn(&stcIrqSigninConfig);
  19.     NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
  20.     NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
  21.     NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);

  22.     /* Register RX error IRQ handler. */
  23.     stcIrqSigninConfig.enIRQn = USART_RX_ERR_IRQn;
  24.     stcIrqSigninConfig.enIntSrc = USART_RX_ERR_INT_SRC;
  25.     stcIrqSigninConfig.pfnCallback = &USART_RxError_IrqCallback;
  26.     (void)INTC_IrqSignIn(&stcIrqSigninConfig);
  27.     NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
  28.     NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
  29.     NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
  30.        
  31.         /* Register RX timeout IRQ handler. */
  32.     stcIrqSigninConfig.enIRQn = USART1_RX_TIMEOUT_IRQn;
  33.     stcIrqSigninConfig.enIntSrc = USART1_RX_TIMEOUT_INT_SRC;
  34.     stcIrqSigninConfig.pfnCallback = &USART_RxTimeout_IrqCallback;
  35.     (void)INTC_IrqSignIn(&stcIrqSigninConfig);
  36.     NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
  37.     NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
  38.     NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
  39. }
 楼主| t61000 发表于 2023-12-20 14:45 | 显示全部楼层
5. 串口初始化
LL_PERIPH_WE() 为打开相应寄存器的写使能

LL_PERIPH_WP() 为关闭相应寄存器的写使能
  1. void UART_Init(void)
  2. {
  3.     LL_PERIPH_WE(LL_PERIPH_ALL);
  4.        
  5.         UartGpioConfig();
  6.        
  7.         UartBaudConfig();
  8.        
  9.         TMR0_Config();
  10.        
  11.         RegisterIrq();
  12.        
  13.     LL_PERIPH_WP(LL_PERIPH_ALL);
  14.        
  15.         USART_FuncCmd(USART_UNIT, ( USART_TX | USART_RX | USART_INT_RX | USART_RX_TIMEOUT | USART_INT_RX_TIMEOUT), ENABLE);
  16. }
 楼主| t61000 发表于 2023-12-20 14:45 | 显示全部楼层
6. 串口数据接收处理
USART_RxFull_IrqCallback 中断 只负责接收和缓存单字节数据,以及递增数据长度 (通过读数据清除标志位)

USART_RxTimeout_IrqCallback 中断 处理超时中断(超时中断触发后必须要关闭定时器,和清除标志位)

USART_RxError_IrqCallback 中断 处理异常错误

  1. static void USART_RxFull_IrqCallback(void)
  2. {
  3.         uint8_t u8Data = (uint8_t)USART_ReadData(USART_UNIT);
  4.         if(gps_len < RX_FRAME_LEN_MAX)
  5.                 gps_buf[gps_len++] = u8Data;
  6. }

  7. static void USART_RxError_IrqCallback(void)
  8. {
  9.         (void)USART_ReadData(USART_UNIT);

  10.     USART_ClearStatus(USART_UNIT, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN));
  11. }

  12. static void USART_RxTimeout_IrqCallback(void)
  13. {
  14.         TMR0_Stop(TMR0_UNIT, TMR0_CH);

  15.     USART_ClearStatus(USART_UNIT, USART_FLAG_RX_TIMEOUT);
  16.        
  17.         GpsRxCallBack(gps_buf, gps_len);
  18.         gps_len = 0;
  19. }
 楼主| t61000 发表于 2023-12-20 14:45 | 显示全部楼层
对于GPS、Wifi这类不频繁的数据交互,用到超时中断和接收寄存器满就可以处理数据了。

对于4G/蓝牙等有持续大量数据交互的模块,就需要用到DMA了。
 楼主| t61000 发表于 2023-12-20 14:45 | 显示全部楼层
7. 串口数据发送
  1. static int32_t UartSendByte(CM_USART_TypeDef *UART, uint8_t ch)
  2. {
  3.         uint32_t u32TxEmpty = 0UL;
  4.     __IO uint32_t u32TmpCount = 0UL;
  5.         uint32_t u32Timeout = HCLK_VALUE/USART_BAUDRATE;
  6.         int32_t i32Ret = LL_ERR_INVD_PARAM;
  7.        
  8.         /* Wait TX data register empty */
  9.         while ((u32TmpCount <= u32Timeout) && (0UL == u32TxEmpty)) {
  10.                 u32TxEmpty = READ_REG32_BIT(UART->SR, USART_SR_TXE);
  11.                 u32TmpCount++;
  12.         }

  13.         if (0UL != u32TxEmpty) {
  14.                 WRITE_REG16(UART->TDR, ch);
  15.                 i32Ret = LL_OK;
  16.         } else {
  17.                 i32Ret = LL_ERR_TIMEOUT;
  18.         }
  19.                
  20.         return i32Ret;
  21. }
 楼主| t61000 发表于 2023-12-20 14:45 | 显示全部楼层
8. DMA接收配置和处理
DMA配置方式与STM32基本相同:

1)设置DMA源地址和源地址增长类型,设置目的地址和目的地址增长类型

DMA接收属于串口数据寄存器到内存,即源地址固定,目的地址递增

DMA发送属于内存到串口数据寄存器,即源地址递增,目的地址固定

2)设置位宽、传输大小、传输块数

所不同的是,HC32有一个可配置的自动运行系统AOS。

可以配置AOS源和AOS目标.

AOS源可以是DMA传输完成、UART接收数据、定时器上溢和下溢、event电平变化等等。

AOS目标可以是DMA传输、定时器计数、ADC模数转换、event事件等等
 楼主| t61000 发表于 2023-12-20 14:46 | 显示全部楼层
如下是DMA初始化配置的参考代码,配置了串口DMA接收和串口DMA发送:
  1. //DMA单元
  2. #define RX_DMA_UNIT                     (CM_DMA1)
  3. //DMA通道号·通道号越小优先级越高
  4. #define RX_DMA_CH                       (DMA_CH0)
  5. //DMA单元时钟
  6. #define RX_DMA_FCG_ENABLE()             (FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_DMA1, ENABLE))
  7. //AOS系统的目标·触发DMA1通道0传输
  8. #define RX_DMA_TRIG_SEL                 (AOS_DMA1_0)
  9. //AOS系统的触发源·接收数据寄存器满中断
  10. #define RX_DMA_TRIG_EVT_SRC             (EVT_SRC_USART1_RI)
  11. //AOS系统的目标·DMA完成中断
  12. #define RX_DMA_RECONF_TRIG_SEL          (AOS_DMA_RC)
  13. //AOS系统的触发源·AOS_STRG中断源
  14. #define RX_DMA_RECONF_TRIG_EVT_SRC      (EVT_SRC_AOS_STRG)
  15. //DMA传输完成中断·通道号1
  16. #define RX_DMA_TC_INT                   (DMA_INT_TC_CH0)
  17. //DMA传输完成标志·通道号2
  18. #define RX_DMA_TC_FLAG                  (DMA_FLAG_TC_CH0)
  19. //DMA传输完成中断号
  20. #define RX_DMA_TC_IRQn                  (INT000_IRQn)
  21. //DMA传输完成中断源
  22. #define RX_DMA_TC_INT_SRC               (INT_SRC_DMA1_TC0)

  23. //串口DMA发送配置
  24. #define TX_DMA_UNIT                     (CM_DMA2)
  25. #define TX_DMA_CH                       (DMA_CH0)
  26. #define TX_DMA_FCG_ENABLE()             (FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_DMA2, ENABLE))
  27. #define TX_DMA_TRIG_SEL                 (AOS_DMA2_0)
  28. #define TX_DMA_TRIG_EVT_SRC             (EVT_SRC_USART1_TI)
  29. #define TX_DMA_TC_INT                   (DMA_INT_TC_CH0)
  30. #define TX_DMA_TC_FLAG                  (DMA_FLAG_TC_CH0)
  31. #define TX_DMA_TC_IRQn                  (INT001_IRQn)
  32. #define TX_DMA_TC_INT_SRC               (INT_SRC_DMA2_TC0)

  33. /*******************************************************************************
  34. * Local variable definitions ('static')
  35. ******************************************************************************/
  36. static __IO en_flag_status_t m_enTxEnd = SET;
  37. static uint8_t m_4gRxBuf[RX_FRAME_LEN_MAX];
  38. static uint8_t *m_auTxBuf = NULL;

  39. /*******************************************************************************
  40. * Local function definitions ('static')
  41. ******************************************************************************/
  42. static void RX_DMA_TC_IrqCallback(void);
  43. static void TX_DMA_TC_IrqCallback(void);

  44. /*
  45. * DMA_Config()
  46. * 配置串口DMA接收和DMA发送
  47. */
  48. static int32_t DMA_Config(void)
  49. {
  50.     int32_t i32Ret;
  51.     stc_dma_init_t stcDmaInit;
  52.     stc_dma_llp_init_t stcDmaLlpInit;
  53.     stc_irq_signin_config_t stcIrqSignConfig;
  54.     static stc_dma_llp_descriptor_t stcLlpDesc;

  55.     //使能DMA和FCG时钟
  56.     RX_DMA_FCG_ENABLE();
  57.     TX_DMA_FCG_ENABLE();
  58.     FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_AOS, ENABLE);

  59.     /* USART_RX_DMA */
  60.     (void)DMA_StructInit(&stcDmaInit);
  61.     stcDmaInit.u32IntEn = DMA_INT_ENABLE;//DMA interrupt enable
  62.     stcDmaInit.u32BlockSize = 1UL;//DMA block size
  63.     stcDmaInit.u32TransCount = ARRAY_SZ(m_4gRxBuf);//DMAbuf大小
  64.     stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;//DMAbuf位宽
  65.     stcDmaInit.u32DestAddr = (uint32_t)m_4gRxBuf;//DMAbuf地址
  66.     stcDmaInit.u32SrcAddr = (uint32_t)(&USART_UNIT->RDR);//由外设到内存的 外设地址 -> 串口数据寄存器
  67.     stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_FIX;//由外设到内存的 源地址模式 固定
  68.     stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_INC;//由外设到内存的 目标地址模式 自动递增
  69.     i32Ret = DMA_Init(RX_DMA_UNIT, RX_DMA_CH, &stcDmaInit);
  70.     if (LL_OK == i32Ret)
  71.         {
  72.         (void)DMA_LlpStructInit(&stcDmaLlpInit);
  73.         stcDmaLlpInit.u32State = DMA_LLP_ENABLE;
  74.         stcDmaLlpInit.u32Mode  = DMA_LLP_WAIT;
  75.         stcDmaLlpInit.u32Addr  = (uint32_t)&stcLlpDesc;
  76.         (void)DMA_LlpInit(RX_DMA_UNIT, RX_DMA_CH, &stcDmaLlpInit);//初始化DMA链表指针

  77.         stcLlpDesc.SARx   = stcDmaInit.u32SrcAddr;
  78.         stcLlpDesc.DARx   = stcDmaInit.u32DestAddr;
  79.         stcLlpDesc.DTCTLx = (stcDmaInit.u32TransCount << DMA_DTCTL_CNT_POS) | (stcDmaInit.u32BlockSize << DMA_DTCTL_BLKSIZE_POS);;
  80.         stcLlpDesc.LLPx   = (uint32_t)&stcLlpDesc;
  81.         stcLlpDesc.CHCTLx = stcDmaInit.u32SrcAddrInc | stcDmaInit.u32DestAddrInc | stcDmaInit.u32DataWidth |  \
  82.                             stcDmaInit.u32IntEn      | stcDmaLlpInit.u32State    | stcDmaLlpInit.u32Mode;

  83.         DMA_ReconfigLlpCmd(RX_DMA_UNIT, RX_DMA_CH, ENABLE);
  84.         DMA_ReconfigCmd(RX_DMA_UNIT, ENABLE);
  85.         AOS_SetTriggerEventSrc(RX_DMA_RECONF_TRIG_SEL, RX_DMA_RECONF_TRIG_EVT_SRC);

  86.         stcIrqSignConfig.enIntSrc = RX_DMA_TC_INT_SRC;
  87.         stcIrqSignConfig.enIRQn  = RX_DMA_TC_IRQn;
  88.         stcIrqSignConfig.pfnCallback = &RX_DMA_TC_IrqCallback;
  89.         (void)INTC_IrqSignIn(&stcIrqSignConfig);
  90.         NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
  91.         NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
  92.         NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);

  93.         AOS_SetTriggerEventSrc(RX_DMA_TRIG_SEL, RX_DMA_TRIG_EVT_SRC);

  94.         DMA_Cmd(RX_DMA_UNIT, ENABLE);
  95.         DMA_TransCompleteIntCmd(RX_DMA_UNIT, RX_DMA_TC_INT, ENABLE);
  96.         (void)DMA_ChCmd(RX_DMA_UNIT, RX_DMA_CH, ENABLE);
  97.     }
  98.        
  99.     (void)DMA_StructInit(&stcDmaInit);
  100.     stcDmaInit.u32IntEn = DMA_INT_ENABLE;
  101.     stcDmaInit.u32BlockSize = 1UL;
  102.     stcDmaInit.u32TransCount = ARRAY_SZ(m_4gRxBuf);
  103.     stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
  104.     stcDmaInit.u32DestAddr = (uint32_t)(&USART_UNIT->TDR);
  105.     stcDmaInit.u32SrcAddr = (uint32_t)m_4gRxBuf;
  106.     stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_INC;
  107.     stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_FIX;
  108.     i32Ret = DMA_Init(TX_DMA_UNIT, TX_DMA_CH, &stcDmaInit);
  109.     if (LL_OK == i32Ret)
  110.         {
  111.         stcIrqSignConfig.enIntSrc = TX_DMA_TC_INT_SRC;
  112.         stcIrqSignConfig.enIRQn  = TX_DMA_TC_IRQn;
  113.         stcIrqSignConfig.pfnCallback = &TX_DMA_TC_IrqCallback;
  114.         (void)INTC_IrqSignIn(&stcIrqSignConfig);
  115.         NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
  116.         NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
  117.         NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);

  118.         AOS_SetTriggerEventSrc(TX_DMA_TRIG_SEL, TX_DMA_TRIG_EVT_SRC);

  119.         DMA_Cmd(TX_DMA_UNIT, ENABLE);
  120.         DMA_TransCompleteIntCmd(TX_DMA_UNIT, TX_DMA_TC_INT, ENABLE);
  121.     }
  122.        
  123.     return i32Ret;
  124. }
 楼主| t61000 发表于 2023-12-20 14:46 | 显示全部楼层
如下是DMA接收处理代码:

1)USART_RxTimeout_IrqCallback

重启AOS系统

关闭串口超时定时器,清除串口超时标志位。

处理DMA接收数据。

2)RX_DMA_TC_IrqCallback

即接收完成中断

硬件上需要清除中断标志位

3)USART_TxComplete_IrqCallback

即串口发送完成中断

硬件上需要清除标志位,一般要失能发送中断
 楼主| t61000 发表于 2023-12-20 14:46 | 显示全部楼层
  1. //串口接收超时中断
  2. static void USART_RxTimeout_IrqCallback(void)
  3. {
  4.     uint16_t unLen = RX_FRAME_LEN_MAX - (uint16_t)DMA_GetTransCount(RX_DMA_UNIT, RX_DMA_CH);
  5.        
  6.     AOS_SW_Trigger();

  7.     TMR0_Stop(TMR0_UNIT, TMR0_CH);

  8.     USART_ClearStatus(USART_UNIT, USART_FLAG_RX_TIMEOUT);
  9.        
  10.         if(unLen != 0 && unLen != RX_FRAME_LEN_MAX)
  11.                 DtuRxCallBack(m_4gRxBuf, unLen);
  12. }

  13. //串口DMA接收·传输完成中断
  14. static void RX_DMA_TC_IrqCallback(void)
  15. {
  16.         DtuRxCallBack(m_4gRxBuf, RX_FRAME_LEN_MAX);
  17.        
  18.     DMA_ClearTransCompleteStatus(RX_DMA_UNIT, RX_DMA_TC_FLAG);
  19. }

  20. //串口发送完成中断
  21. static void USART_TxComplete_IrqCallback(void)
  22. {
  23.         m_enTxEnd = SET;
  24.         DtuTxCallBack(m_auTxBuf);
  25.        
  26.         USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_CPLT), DISABLE);
  27.        
  28.     USART_ClearStatus(USART_UNIT, USART_FLAG_TX_CPLT);
  29. }

  30. //串口接收错误中断
  31. static void USART_RxError_IrqCallback(void)
  32. {
  33.     (void)USART_ReadData(USART_UNIT);

  34.     USART_ClearStatus(USART_UNIT, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN));
  35. }

  36. //串口DMA发送·传输完成中断
  37. static void TX_DMA_TC_IrqCallback(void)
  38. {
  39.     USART_FuncCmd(USART_UNIT, USART_INT_TX_CPLT, ENABLE);

  40.     DMA_ClearTransCompleteStatus(TX_DMA_UNIT, TX_DMA_TC_FLAG);
  41. }
 楼主| t61000 发表于 2023-12-20 14:46 | 显示全部楼层
9. DMA发送
  1. //串口DMA发送
  2. void DtuDMASend(uint8_t *pBuf, uint16_t u16TxLen)
  3. {
  4. #if 0 //串口发送数据打印
  5.         printf("Tx: ");
  6.         for(uint16_t i = 0; i < u16TxLen; i++)
  7.         {
  8.                 printf("%02X",pBuf[i]);
  9.         }
  10.         printf("\r\n");
  11. #endif
  12.        
  13.         //等待上一包发完
  14.         while(m_enTxEnd == RESET);
  15.         m_enTxEnd = RESET;
  16.         m_auTxBuf = pBuf;
  17.        
  18.         //启动DMA传输
  19.         DMA_SetSrcAddr(TX_DMA_UNIT, TX_DMA_CH, (uint32_t)pBuf);
  20.         DMA_SetTransCount(TX_DMA_UNIT, TX_DMA_CH, u16TxLen);
  21.         (void)DMA_ChCmd(TX_DMA_UNIT, TX_DMA_CH, ENABLE);
  22.         USART_FuncCmd(USART_UNIT, USART_TX, ENABLE);
  23. }
xdvca 发表于 2024-7-31 22:47 | 显示全部楼层
某些引脚用于调试功能 TRACE/JTAG。如果要这些引脚用于普通 GPIO 功能,必须关闭调试功能。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

124

帖子

0

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