本帖最后由 我是红尘一抹阳光 于 2024-9-11 13:48 编辑

很庆幸能收到国民技术的开发板,感谢!!!
ea904030553ad31d1bc290b3640a8db.jpg

开发板图展示:
image.png

开发板原理图:
image.png
官方给的N32G401集成1个灵活的通用DMA控制器,支持8个DMA通道,可以管理存储器到存储器、外设到存储器和存储器到

外设的数据传输。

N32G401系列产品中,集成了最多4个串行收发接口,包括2个通用同步/异步收发器(USART1和USART2)和 2个通用异步收发器(UART3和UART4)。

官方给的串口USART1和USART2接口具有硬件的CTS和RTS信号管理、兼容ISO7816的智能卡模式和类SPI通信模式,所有接口都可以使用DMA操作。

所以,我想验证下通过DMA发送串口功能。
1、首先自定义一行打印数据
  1. USART_InitType USART_InitStructure;
  2. uint8_t TxBuffer1[20] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a};
通过串口实现打印效果。
2、配置DMA、GPIO、USART相关的时钟
  1. void RCC_Configuration(void)
  2. {
  3.     /* DMA clock enable */
  4.     RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_DMA);
  5.     /* Enable GPIO clock */
  6.     RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
  7.     RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
  8.     /* Enable USARTy and USARTz Clock */
  9.     USARTy_APBxClkCmd(RCC_APB2_PERIPH_USART1);
  10. }
通过开启这些外设的时钟,后续的外设功能才能正常使用。
3、配置 GPIO 引脚
  1. void GPIO_Configuration(void)
  2. {
  3.     GPIO_InitType GPIO_InitStructure;

  4.     /* Initialize GPIO_InitStructure */
  5.     GPIO_Structure_Initialize(&GPIO_InitStructure);
  6.      
  7.     /* Configure USARTy Tx as alternate function push-pull */
  8.     GPIO_InitStructure.Pin            = GPIO_PIN_9;     
  9.     GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;
  10.     GPIO_InitStructure.GPIO_Alternate = GPIO_AF5_USART1;
  11.     GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);


  12.     /* Configure USARTx Rx as alternate function push-pull */
  13.     GPIO_InitStructure.Pin            = GPIO_PIN_10;
  14.     GPIO_InitStructure.GPIO_Alternate = GPIO_AF5_USART1;
  15.     GPIO_Peripheral_Initialize(GPIOA);     
  16.   
  17. }
4、初始化DMA。只发送一次,当计数器为0时便不再搬运数据。
  1. void DMA_Configuration(void)
  2. {
  3.     DMA_InitType DMA_InitStructure;

  4.     /* DMA_CH1 (triggered by USARTy Tx event) Config */
  5.     DMA_Reset(DMA_CH1);
  6.     DMA_InitStructure.PeriphAddr     = (USART1_BASE + 0x04);
  7.     DMA_InitStructure.MemAddr        = (uint32_t)TxBuffer1;
  8.     DMA_InitStructure.Direction      = DMA_DIR_PERIPH_DST;
  9.     DMA_InitStructure.BufSize        = TxBufferSize1;
  10.     DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_MODE_DISABLE;
  11.     DMA_InitStructure.MemoryInc      = DMA_MEM_INC_MODE_ENABLE;
  12.     DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;
  13.     DMA_InitStructure.MemDataSize    = DMA_MEM_DATA_WIDTH_BYTE;
  14.     DMA_InitStructure.CircularMode   = DMA_CIRCULAR_MODE_DISABLE;
  15.     DMA_InitStructure.Priority       = DMA_CH_PRIORITY_HIGHEST;
  16.     DMA_InitStructure.Mem2Mem        = DMA_MEM2MEM_DISABLE;
  17.     DMA_Initializes(DMA_CH1);
  18.     DMA_Channel_Request_Remap(DMA_CH1,DMA_REMAP_USART1_TX);

  19. }
5、USART配置
  1. void usart_config(){

  2.    /* USART1 and USARTz configuration */
  3.     USART_InitStructure.BaudRate            = 115200;
  4.     USART_InitStructure.WordLength          = USART_WL_8B;
  5.     USART_InitStructure.StopBits            = USART_STPB_1;
  6.     USART_InitStructure.Parity              = USART_PE_NO;
  7.     USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
  8.     USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

  9.     /* Configure USART1 and USARTz */
  10.     USART_Initializes(USART1, &USART_InitStructure);

  11.     /* Enable USART1 DMA Rx and TX request */
  12.     USART_DMA_Transfer_Enable(USART1, USART_DMAREQ_RX | USART_DMAREQ_TX);



  13.     /* Enable USART1 TX DMA Channel */
  14.     DMA_Channel_Enable(DMA_CH1);

  15.     /* Enable the USART1 and USARTz */
  16.     USART_Enable(USART1);

  17. }
波特率、数据位长度、停止位、校验位、硬件流控制和工作模式配置,启用 DMA_CH1 通道,该通道用于 USART1 的数据传输。DMA 可以自动搬运数据,不需要 CPU 来处理数据传输,适用于大量数据或高频率的传输。
6、测试
  1. int main(void)
  2. {
  3.     /* System Clocks Configuration */
  4.     RCC_Configuration();

  5.     /* NVIC configuration */
  6.     NVIC_Configuration();

  7.     /* Configure the GPIO ports */
  8.     GPIO_Configuration();

  9.     /* Configure the DMA */
  10.     DMA_Configuration();

  11.     usart_config();
  12.         
  13.         
  14.         
  15.           while(1){
  16.                
  17.                 DMA_Channel_Disable(DMA_CH1);
  18.                
  19.                 DMA_Current_Data_Transfer_Number_Set(DMA_CH1, 20);
  20.                 DMA_Channel_Enable(DMA_CH1);
  21.                
  22.                 while (USART_Flag_Status_Get(USART1, USART_FLAG_RXDNE) == RESET)
  23.        {
  24.         
  25.                 }
  26.                         
  27.                 __NOP();
  28.                 __NOP();
  29.                 __NOP();

  30.         }
  31.                
  32.                
  33.                
  34. }
现实效果如下:

image.png
说明:
使用DMA来处理USART数据传输主要是为了提高传输效率、减轻CPU的负担、避免频繁的中断处理,并且在需要进行大数据量、实时性要求高的场景中表现尤为优越。

所以经常会DMA与USART配合使用,这样能让系统在保持高性能的同时,减少延迟和数据丢失的风险。