• 小华HC32F448串口使用


    目录

    1. 串口GPIO配置

    2. 串口波特率配置

    3. 串口接收超时配置

    4. 串口中断注册

    5. 串口初始化

    6. 串口数据接收处理

    7. DMA接收配置和处理


    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的复用功能是固定的,对应通讯线必须一一选对。

    如下,硬件选择了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. }

    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. }

    3. 串口接收超时配置

    小华HC32F4串口支持的中断与STM32大有不同:

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

    2)HC32 TIMEOUT中断,等同于STM32的空闲中断 IDLE 。HC32通过关联定时器直接配置超时时间,比STM32更加简便。

    定时器Timer0被专门用来做串口的计时器,板子用的串口2,所以定时器要配置Timer0_1 B 。

    1. //串口接收超时设置·关联定时器
    2. #define USART_TIMEOUT_BITS (5000U)
    3. #define TMR0_UNIT (CM_TMR0_1)
    4. #define TMR0_CH (TMR0_CH_B)
    5. #define TMR0_FCG_ENABLE() (FCG_Fcg2PeriphClockCmd(FCG2_PERIPH_TMR0_1, ENABLE))
    6. /*
    7. * TMR0_Config()
    8. * 配置串口接收超时
    9. */
    10. static void TMR0_Config(void)
    11. {
    12. uint16_t u16Div;
    13. uint16_t u16Delay;
    14. uint16_t u16CompareValue;
    15. stc_tmr0_init_t stcTmr0Init;
    16. TMR0_FCG_ENABLE();
    17. /* Initialize TMR0 base function. */
    18. stcTmr0Init.u32ClockSrc = TMR0_CLK_SRC_XTAL32;
    19. stcTmr0Init.u32ClockDiv = TMR0_CLK_DIV8;
    20. stcTmr0Init.u32Func = TMR0_FUNC_CMP;
    21. if (TMR0_CLK_DIV1 == stcTmr0Init.u32ClockDiv) {
    22. u16Delay = 7U;
    23. } else if (TMR0_CLK_DIV2 == stcTmr0Init.u32ClockDiv) {
    24. u16Delay = 5U;
    25. } else if ((TMR0_CLK_DIV4 == stcTmr0Init.u32ClockDiv) || \
    26. (TMR0_CLK_DIV8 == stcTmr0Init.u32ClockDiv) || \
    27. (TMR0_CLK_DIV16 == stcTmr0Init.u32ClockDiv)) {
    28. u16Delay = 3U;
    29. } else {
    30. u16Delay = 2U;
    31. }
    32. u16Div = (uint16_t)1U << (stcTmr0Init.u32ClockDiv >> TMR0_BCONR_CKDIVA_POS);
    33. u16CompareValue = ((USART_TIMEOUT_BITS + u16Div - 1U) / u16Div) - u16Delay;
    34. stcTmr0Init.u16CompareValue = u16CompareValue;
    35. (void)TMR0_Init(TMR0_UNIT, TMR0_CH, &stcTmr0Init);
    36. TMR0_HWStartCondCmd(TMR0_UNIT, TMR0_CH, ENABLE);
    37. TMR0_HWClearCondCmd(TMR0_UNIT, TMR0_CH, ENABLE);
    38. }

    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. /* Register RX full IRQ handler. */
    14. stcIrqSigninConfig.enIRQn = USART_RX_FULL_IRQn;
    15. stcIrqSigninConfig.enIntSrc = USART_RX_FULL_INT_SRC;
    16. stcIrqSigninConfig.pfnCallback = &USART_RxFull_IrqCallback;
    17. (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    18. NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    19. NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    20. NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
    21. /* Register RX error IRQ handler. */
    22. stcIrqSigninConfig.enIRQn = USART_RX_ERR_IRQn;
    23. stcIrqSigninConfig.enIntSrc = USART_RX_ERR_INT_SRC;
    24. stcIrqSigninConfig.pfnCallback = &USART_RxError_IrqCallback;
    25. (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    26. NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    27. NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    28. NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
    29. /* Register RX timeout IRQ handler. */
    30. stcIrqSigninConfig.enIRQn = USART1_RX_TIMEOUT_IRQn;
    31. stcIrqSigninConfig.enIntSrc = USART1_RX_TIMEOUT_INT_SRC;
    32. stcIrqSigninConfig.pfnCallback = &USART_RxTimeout_IrqCallback;
    33. (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    34. NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    35. NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    36. NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
    37. }

    5. 串口初始化

    LL_PERIPH_WE() 为打开相应寄存器的写使能

    LL_PERIPH_WP() 为关闭相应寄存器的写使能

    1. void UART_Init(void)
    2. {
    3. LL_PERIPH_WE(LL_PERIPH_ALL);
    4. UartGpioConfig();
    5. UartBaudConfig();
    6. TMR0_Config();
    7. RegisterIrq();
    8. LL_PERIPH_WP(LL_PERIPH_ALL);
    9. USART_FuncCmd(USART_UNIT, ( USART_TX | USART_RX | USART_INT_RX | USART_RX_TIMEOUT | USART_INT_RX_TIMEOUT), ENABLE);
    10. }

    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. GpsRxCallBack(gps_buf, gps_len);
    17. gps_len = 0;
    18. }

    对于GPS、Wifi这类不频繁的数据交互,用到超时中断和接收寄存器满就可以处理数据了。

    对于4G/蓝牙等有持续大量数据交互的模块,就需要用到DMA了。

    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. /* Wait TX data register empty */
    8. while ((u32TmpCount <= u32Timeout) && (0UL == u32TxEmpty)) {
    9. u32TxEmpty = READ_REG32_BIT(UART->SR, USART_SR_TXE);
    10. u32TmpCount++;
    11. }
    12. if (0UL != u32TxEmpty) {
    13. WRITE_REG16(UART->TDR, ch);
    14. i32Ret = LL_OK;
    15. } else {
    16. i32Ret = LL_ERR_TIMEOUT;
    17. }
    18. return i32Ret;
    19. }

    8. DMA接收配置和处理

    DMA配置方式与STM32基本相同:

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

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

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

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


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

    可以配置AOS源和AOS目标.

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

    AOS目标可以是DMA传输、定时器计数、ADC模数转换、event事件等等

    如下是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. (void)DMA_StructInit(&stcDmaInit);
    99. stcDmaInit.u32IntEn = DMA_INT_ENABLE;
    100. stcDmaInit.u32BlockSize = 1UL;
    101. stcDmaInit.u32TransCount = ARRAY_SZ(m_4gRxBuf);
    102. stcDmaInit.u32DataWidth = DMA_DATAWIDTH_8BIT;
    103. stcDmaInit.u32DestAddr = (uint32_t)(&USART_UNIT->TDR);
    104. stcDmaInit.u32SrcAddr = (uint32_t)m_4gRxBuf;
    105. stcDmaInit.u32SrcAddrInc = DMA_SRC_ADDR_INC;
    106. stcDmaInit.u32DestAddrInc = DMA_DEST_ADDR_FIX;
    107. i32Ret = DMA_Init(TX_DMA_UNIT, TX_DMA_CH, &stcDmaInit);
    108. if (LL_OK == i32Ret)
    109. {
    110. stcIrqSignConfig.enIntSrc = TX_DMA_TC_INT_SRC;
    111. stcIrqSignConfig.enIRQn = TX_DMA_TC_IRQn;
    112. stcIrqSignConfig.pfnCallback = &TX_DMA_TC_IrqCallback;
    113. (void)INTC_IrqSignIn(&stcIrqSignConfig);
    114. NVIC_ClearPendingIRQ(stcIrqSignConfig.enIRQn);
    115. NVIC_SetPriority(stcIrqSignConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    116. NVIC_EnableIRQ(stcIrqSignConfig.enIRQn);
    117. AOS_SetTriggerEventSrc(TX_DMA_TRIG_SEL, TX_DMA_TRIG_EVT_SRC);
    118. DMA_Cmd(TX_DMA_UNIT, ENABLE);
    119. DMA_TransCompleteIntCmd(TX_DMA_UNIT, TX_DMA_TC_INT, ENABLE);
    120. }
    121. return i32Ret;
    122. }

    如下是DMA接收处理代码:

    1)USART_RxTimeout_IrqCallback

    重启AOS系统

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

    处理DMA接收数据。

    2)RX_DMA_TC_IrqCallback

    即接收完成中断

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

    3)USART_TxComplete_IrqCallback

    即串口发送完成中断

    硬件上需要清除标志位,一般要失能发送中断

    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. AOS_SW_Trigger();
    6. TMR0_Stop(TMR0_UNIT, TMR0_CH);
    7. USART_ClearStatus(USART_UNIT, USART_FLAG_RX_TIMEOUT);
    8. if(unLen != 0 && unLen != RX_FRAME_LEN_MAX)
    9. DtuRxCallBack(m_4gRxBuf, unLen);
    10. }
    11. //串口DMA接收·传输完成中断
    12. static void RX_DMA_TC_IrqCallback(void)
    13. {
    14. DtuRxCallBack(m_4gRxBuf, RX_FRAME_LEN_MAX);
    15. DMA_ClearTransCompleteStatus(RX_DMA_UNIT, RX_DMA_TC_FLAG);
    16. }
    17. //串口发送完成中断
    18. static void USART_TxComplete_IrqCallback(void)
    19. {
    20. m_enTxEnd = SET;
    21. DtuTxCallBack(m_auTxBuf);
    22. USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_CPLT), DISABLE);
    23. USART_ClearStatus(USART_UNIT, USART_FLAG_TX_CPLT);
    24. }
    25. //串口接收错误中断
    26. static void USART_RxError_IrqCallback(void)
    27. {
    28. (void)USART_ReadData(USART_UNIT);
    29. USART_ClearStatus(USART_UNIT, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN));
    30. }
    31. //串口DMA发送·传输完成中断
    32. static void TX_DMA_TC_IrqCallback(void)
    33. {
    34. USART_FuncCmd(USART_UNIT, USART_INT_TX_CPLT, ENABLE);
    35. DMA_ClearTransCompleteStatus(TX_DMA_UNIT, TX_DMA_TC_FLAG);
    36. }

    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. while(m_enTxEnd == RESET);
    14. m_enTxEnd = RESET;
    15. m_auTxBuf = pBuf;
    16. //启动DMA传输
    17. DMA_SetSrcAddr(TX_DMA_UNIT, TX_DMA_CH, (uint32_t)pBuf);
    18. DMA_SetTransCount(TX_DMA_UNIT, TX_DMA_CH, u16TxLen);
    19. (void)DMA_ChCmd(TX_DMA_UNIT, TX_DMA_CH, ENABLE);
    20. USART_FuncCmd(USART_UNIT, USART_TX, ENABLE);
    21. }
  • 相关阅读:
    Tensorflow 01(介绍)
    计算机毕业设计ssm“逢遇”个人博客平台qaoxv系统+程序+源码+lw+远程部署
    Spring IOC
    社招两年半10个公司28轮面试面经(含字节、拼多多、美团、滴滴......)
    做题(2)
    将主机1中的数据存到主机2的MySQL数据库中
    Vue2 基础语法
    pytorch中tensor转成图片保存
    flutter Podfile.lock与pubspec.yaml版本不同问题
    Autovue集成全过程
  • 原文地址:https://blog.csdn.net/weixin_38743772/article/details/133804695