当前位置:   article > 正文

【AT-START-F423测评】+ UART + DMA + IDLE 接收不定长数据_uart dma接收不定长

uart dma接收不定长

DMA 传输必须设置传输的数据量,对应的中断也只有传输完成,半传输完成和传输错误中断,对于不定长数据的传输基本没有办法识别是否传输完成。
UART 有个 IDLE 标志,在 UART 总线上没有数据传输时,UART TX 和 RX 都会保持高电平,在识别到 RX 上连续的 10 bit (包含起始位,数据位,结束位)高电平时,会设置 IDLE 标志,当打开 IDLE 中断时即会触发 IDLE 中断。
所以,基于以上两点,可以配合 UART 的 IDLE 中断和 DMA 一起使用。
步骤:
1、AT32_Work_Bench 配置过程
 

 

 

 

 



2、代码编写main.c

复制
  1. /* add user code begin Header */
  2. /**
  3.   **************************************************************************
  4.   * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  5.   * [url=home.php?mod=space&uid=247401]@brief[/url]    main program
  6.   **************************************************************************
  7.   *                       Copyright notice & Disclaimer
  8.   *
  9.   * The software Board Support Package (BSP) that is made available to
  10.   * download from Artery official website is the copyrighted work of Artery.
  11.   * Artery authorizes customers to use, copy, and distribute the BSP
  12.   * software and its related documentation for the purpose of design and
  13.   * development in conjunction with Artery microcontrollers. Use of the
  14.   * software is governed by this copyright notice and the following disclaimer.
  15.   *
  16.   * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  17.   * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  18.   * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  19.   * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  20.   * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  21.   * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  22.   *
  23.   **************************************************************************
  24.   */
  25. /* add user code end Header */
  26. /* Includes ------------------------------------------------------------------*/
  27. #include "at32f423_wk_config.h"
  28. /* private includes ----------------------------------------------------------*/
  29. /* add user code begin private includes */
  30. #include <string.h>
  31. /* add user code end private includes */
  32. /* private typedef -----------------------------------------------------------*/
  33. /* add user code begin private typedef */
  34. /* add user code end private typedef */
  35. /* private define ------------------------------------------------------------*/
  36. /* add user code begin private define */
  37. /* add user code end private define */
  38. /* private macro -------------------------------------------------------------*/
  39. /* add user code begin private macro */
  40. #define MS_TICK         (system_core_clock / 8 / 1000U)
  41. #define TX_BUF_SIZE     100
  42. #define RX_BUF_SIZE     100
  43. /* add user code end private macro */
  44. /* private variables ---------------------------------------------------------*/
  45. /* add user code begin private variables */
  46. static volatile uint32_t sys_tick;
  47. uint8_t tx_buf[TX_BUF_SIZE];    /* uart 发送缓冲区 */
  48. volatile uint16_t tx_len;                /* uart 实际发送数据长度 */
  49. volatile uint8_t tx_flag;                /* uart 发送繁忙标志 */
  50. uint8_t rx_buf[RX_BUF_SIZE];    /* uart 接收缓冲区 */
  51. volatile uint16_t rx_len;                /* uart 实际接收数据长度 */
  52. volatile uint8_t rx_flag;                /* uart 接收完成标志 */
  53. static const char *start_msg = "The demo is started!\n";
  54. /* add user code end private variables */
  55. /* private function prototypes --------------------------------------------*/
  56. /* add user code begin function prototypes */
  57. /* add user code end function prototypes */
  58. /* private user code ---------------------------------------------------------*/
  59. /* add user code begin 0 */
  60. static void systick_init(void)
  61. {
  62.     SysTick_Config(MS_TICK);
  63.     systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_DIV8);
  64. }
  65. static void sys_tick_increament(void)
  66. {
  67.     sys_tick++;
  68. }
  69. uint32_t sys_tick_get(void)
  70. {
  71.     return sys_tick;
  72. }
  73. void SysTick_Handler(void)
  74. {
  75.   sys_tick_increament();
  76. }
  77. /* add user code end 0 */
  78. /**
  79.   * @brief  take some delay for waiting power stable, delay is about 60ms with frequency 8MHz.
  80.   * @param  none
  81.   * @retval none
  82.   */
  83. static void wk_wait_for_power_stable(void)
  84. {
  85.   volatile uint32_t delay = 0;
  86.   for(delay = 0; delay < 50000; delay++);
  87. }
  88. /**
  89.   * @brief main function.
  90.   * @param  none
  91.   * @retval none
  92.   */
  93. int main(void)
  94. {
  95.   /* add user code begin 1 */
  96.     uint32_t start_tick;
  97.   /* add user code end 1 */
  98.   /* add a necessary delay to ensure that Vdd is higher than the operating
  99.      voltage of battery powered domain (2.57V) when the battery powered
  100.      domain is powered on for the first time and being operated. */
  101.   wk_wait_for_power_stable();
  102.   
  103.   /* system clock config. */
  104.   wk_system_clock_config();
  105.   /* config periph clock. */
  106.   wk_periph_clock_config();
  107.   /* nvic config. */
  108.   wk_nvic_config();
  109.   /* init dma1 channel1 */
  110.   wk_dma1_channel1_init();
  111.   /* config dma channel transfer parameter */
  112.   /* user need to modify parameters memory_base_addr and buffer_size */
  113.   wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&USART1->dt, (uint32_t)rx_buf, RX_BUF_SIZE);
  114.   dma_channel_enable(DMA1_CHANNEL1, TRUE);
  115.   /* init dma1 channel2 */
  116.   wk_dma1_channel2_init();
  117.   /* config dma channel transfer parameter */
  118.   /* user need to modify parameters memory_base_addr and buffer_size */
  119.   wk_dma_channel_config(DMA1_CHANNEL2, (uint32_t)&USART1->dt, (uint32_t)start_msg, strlen(start_msg));
  120.   dma_channel_enable(DMA1_CHANNEL2, TRUE);
  121.   /* init usart1 function. */
  122.   wk_usart1_init();
  123.   /* init gpio function. */
  124.   wk_gpio_config();
  125.   /* add user code begin 2 */
  126.     systick_init();
  127.    
  128.     dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE); /* 打开 dma 发送完成中断 */
  129.     rx_len = RX_BUF_SIZE;                                   /* 设置接收的最大长度 */
  130.     dma_flag_clear(DMA1_FDT1_FLAG);                         /* 清除 uart dma 传输完成标志 */
  131.     usart_flag_clear(USART1, USART_IDLEF_FLAG);             /* 清除空闲中断标志 */
  132.     dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); /* 打开 uart dma 接收完成中断 */
  133.     usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE);   /* 打开 uart 空闲中断 */
  134.    
  135.     start_tick = sys_tick_get();
  136.   /* add user code end 2 */
  137.   while(1)
  138.   {
  139.     /* add user code begin 3 */
  140.     if (rx_flag) {
  141.         rx_flag = 0;
  142.         
  143.         while (tx_flag == 0);                           /* 等待发送就绪 */
  144.         
  145.         if (rx_len) {
  146.             memcpy(tx_buf, rx_buf, rx_len);             /* 拷贝接收数据 */
  147.             /* 配置 DMA 发送*/
  148.             wk_dma_channel_config(DMA1_CHANNEL2, (uint32_t)&USART1->dt, (uint32_t)tx_buf, rx_len);
  149.             dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE); /* 打开 dma 发送完成中断 */
  150.             dma_channel_enable(DMA1_CHANNEL2, TRUE);                /* 启动 dma 通道传输 */
  151.             tx_flag = 0;                                /* 设置发送繁忙标志 */
  152.         }
  153. //        else {
  154. //            while (1);
  155. //        }
  156.         /* 重新启动 uart dma 接收 */
  157.         dma_flag_clear(DMA1_FDT1_FLAG);                         /* 清除 uart dma 传输完成标志 */
  158.         usart_flag_clear(USART1, USART_IDLEF_FLAG);             /* 清除空闲中断标志 */
  159.         dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); /* 打开 uart dma 接收完成中断 */
  160.         usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE);   /* 打开 uart 空闲中断 */
  161.         rx_len = RX_BUF_SIZE;                                   /* 设置接收的最大长度 */
  162.         /* 重新配置 dma 接收参数 */
  163.         wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&USART1->dt, (uint32_t)rx_buf, RX_BUF_SIZE);
  164.         dma_channel_enable(DMA1_CHANNEL1, TRUE);                /* 打开 dma 通道传输 */
  165.     }
  166.    
  167.     if (sys_tick_get() - start_tick >= 500) {                   /* 每隔 500 ms 翻转一次 LED */
  168.         start_tick = sys_tick_get();
  169.         gpio_bits_toggle(LED2_GPIO_PORT, LED2_PIN);
  170.         gpio_bits_toggle(LED3_GPIO_PORT, LED3_PIN);
  171.         gpio_bits_toggle(LED4_GPIO_PORT, LED4_PIN);
  172.     }
  173.     /* add user code end 3 */
  174.   }
  175. }


at32f423_int.c

复制
  1. /* add user code begin Header */
  2. /**
  3.   **************************************************************************
  4.   * [url=home.php?mod=space&uid=288409]@file[/url]     at32f423_int.c
  5.   * [url=home.php?mod=space&uid=247401]@brief[/url]    main interrupt service routines.
  6.   **************************************************************************
  7.   *                       Copyright notice & Disclaimer
  8.   *
  9.   * The software Board Support Package (BSP) that is made available to
  10.   * download from Artery official website is the copyrighted work of Artery.
  11.   * Artery authorizes customers to use, copy, and distribute the BSP
  12.   * software and its related documentation for the purpose of design and
  13.   * development in conjunction with Artery microcontrollers. Use of the
  14.   * software is governed by this copyright notice and the following disclaimer.
  15.   *
  16.   * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  17.   * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  18.   * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  19.   * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  20.   * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  21.   * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  22.   *
  23.   **************************************************************************
  24.   */
  25. /* add user code end Header */
  26. /* includes ------------------------------------------------------------------*/
  27. #include "at32f423_int.h"
  28. /* private includes ----------------------------------------------------------*/
  29. /* add user code begin private includes */
  30. /* add user code end private includes */
  31. /* private typedef -----------------------------------------------------------*/
  32. /* add user code begin private typedef */
  33. /* add user code end private typedef */
  34. /* private define ------------------------------------------------------------*/
  35. /* add user code begin private define */
  36. /* add user code end private define */
  37. /* private macro -------------------------------------------------------------*/
  38. /* add user code begin private macro */
  39. /* add user code end private macro */
  40. /* private variables ---------------------------------------------------------*/
  41. /* add user code begin private variables */
  42. /* add user code end private variables */
  43. /* private function prototypes --------------------------------------------*/
  44. /* add user code begin function prototypes */
  45. /* add user code end function prototypes */
  46. /* private user code ---------------------------------------------------------*/
  47. /* add user code begin 0 */
  48. /* add user code end 0 */
  49. /* external variables ---------------------------------------------------------*/
  50. /* add user code begin external variables */
  51. extern volatile uint8_t tx_flag;
  52. extern volatile uint16_t rx_len;
  53. extern volatile uint8_t rx_flag;
  54. /* add user code end external variables */
  55. /**
  56.   * @brief  this function handles nmi exception.
  57.   * @param  none
  58.   * @retval none
  59.   */
  60. void NMI_Handler(void)
  61. {
  62.   /* add user code begin NonMaskableInt_IRQ 0 */
  63.   /* add user code end NonMaskableInt_IRQ 0 */
  64.   /* add user code begin NonMaskableInt_IRQ 1 */
  65.   /* add user code end NonMaskableInt_IRQ 1 */
  66. }
  67. /**
  68.   * @brief  this function handles hard fault exception.
  69.   * @param  none
  70.   * @retval none
  71.   */
  72. void HardFault_Handler(void)
  73. {
  74.   /* add user code begin HardFault_IRQ 0 */
  75.   /* add user code end HardFault_IRQ 0 */
  76.   /* go to infinite loop when hard fault exception occurs */
  77.   while (1)
  78.   {
  79.     /* add user code begin W1_HardFault_IRQ 0 */
  80.     /* add user code end W1_HardFault_IRQ 0 */
  81.   }
  82. }
  83. /**
  84.   * @brief  this function handles memory manage exception.
  85.   * @param  none
  86.   * @retval none
  87.   */
  88. void MemManage_Handler(void)
  89. {
  90.   /* add user code begin MemoryManagement_IRQ 0 */
  91.   /* add user code end MemoryManagement_IRQ 0 */
  92.   /* go to infinite loop when memory manage exception occurs */
  93.   while (1)
  94.   {
  95.     /* add user code begin W1_MemoryManagement_IRQ 0 */
  96.     /* add user code end W1_MemoryManagement_IRQ 0 */
  97.   }
  98. }
  99. /**
  100.   * @brief  this function handles bus fault exception.
  101.   * @param  none
  102.   * @retval none
  103.   */
  104. void BusFault_Handler(void)
  105. {
  106.   /* add user code begin BusFault_IRQ 0 */
  107.   /* add user code end BusFault_IRQ 0 */
  108.   /* go to infinite loop when bus fault exception occurs */
  109.   while (1)
  110.   {
  111.     /* add user code begin W1_BusFault_IRQ 0 */
  112.     /* add user code end W1_BusFault_IRQ 0 */
  113.   }
  114. }
  115. /**
  116.   * @brief  this function handles usage fault exception.
  117.   * @param  none
  118.   * @retval none
  119.   */
  120. void UsageFault_Handler(void)
  121. {
  122.   /* add user code begin UsageFault_IRQ 0 */
  123.   /* add user code end UsageFault_IRQ 0 */
  124.   /* go to infinite loop when usage fault exception occurs */
  125.   while (1)
  126.   {
  127.     /* add user code begin W1_UsageFault_IRQ 0 */
  128.     /* add user code end W1_UsageFault_IRQ 0 */
  129.   }
  130. }
  131. /**
  132.   * @brief  this function handles svcall exception.
  133.   * @param  none
  134.   * @retval none
  135.   */
  136. void SVC_Handler(void)
  137. {
  138.   /* add user code begin SVCall_IRQ 0 */
  139.   /* add user code end SVCall_IRQ 0 */
  140.   /* add user code begin SVCall_IRQ 1 */
  141.   /* add user code end SVCall_IRQ 1 */
  142. }
  143. /**
  144.   * @brief  this function handles debug monitor exception.
  145.   * @param  none
  146.   * @retval none
  147.   */
  148. void DebugMon_Handler(void)
  149. {
  150.   /* add user code begin DebugMonitor_IRQ 0 */
  151.   /* add user code end DebugMonitor_IRQ 0 */
  152.   /* add user code begin DebugMonitor_IRQ 1 */
  153.   /* add user code end DebugMonitor_IRQ 1 */
  154. }
  155. /**
  156.   * @brief  this function handles pendsv_handler exception.
  157.   * @param  none
  158.   * @retval none
  159.   */
  160. void PendSV_Handler(void)
  161. {
  162.   /* add user code begin PendSV_IRQ 0 */
  163.   /* add user code end PendSV_IRQ 0 */
  164.   /* add user code begin PendSV_IRQ 1 */
  165.   /* add user code end PendSV_IRQ 1 */
  166. }
  167. /**
  168.   * @brief  this function handles DMA1 Channel 1 handler.
  169.   * @param  none
  170.   * @retval none
  171.   */
  172. void DMA1_Channel1_IRQHandler(void)
  173. {
  174.   /* add user code begin DMA1_Channel1_IRQ 0 */
  175.     if(dma_flag_get(DMA1_FDT1_FLAG)) {
  176.         rx_flag = 1; /* 标记接收到数据 */
  177.         /* 关闭 dma 通道,关闭中断 */
  178.         dma_channel_enable(DMA1_CHANNEL1, FALSE);
  179.         dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, FALSE);
  180.         usart_interrupt_enable(USART1, USART_IDLE_INT, FALSE);
  181.     }
  182.   /* add user code end DMA1_Channel1_IRQ 0 */
  183.   /* add user code begin DMA1_Channel1_IRQ 1 */
  184.   /* add user code end DMA1_Channel1_IRQ 1 */
  185. }
  186. /**
  187.   * @brief  this function handles DMA1 Channel 2 handler.
  188.   * @param  none
  189.   * @retval none
  190.   */
  191. void DMA1_Channel2_IRQHandler(void)
  192. {
  193.   /* add user code begin DMA1_Channel2_IRQ 0 */
  194.     if(dma_flag_get(DMA1_FDT2_FLAG)) {
  195.         tx_flag = 1;                                                /* 设置发送就绪 */
  196.         dma_channel_enable(DMA1_CHANNEL2, FALSE);                   /* 关闭 dma 通道传输 */
  197.         dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, FALSE);    /* 关闭 dma 传输完成中断 */
  198.         dma_flag_clear(DMA1_FDT2_FLAG);                             /* 清除传输完成标志 */
  199.     }
  200.   /* add user code end DMA1_Channel2_IRQ 0 */
  201.   /* add user code begin DMA1_Channel2_IRQ 1 */
  202.   /* add user code end DMA1_Channel2_IRQ 1 */
  203. }
  204. /**
  205.   * @brief  this function handles USART1 handler.
  206.   * @param  none
  207.   * @retval none
  208.   */
  209. void USART1_IRQHandler(void)
  210. {
  211.   /* add user code begin USART1_IRQ 0 */
  212.     if(usart_flag_get(USART1, USART_IDLEF_FLAG) != RESET)
  213.     {
  214.         rx_flag = 1; /* 标记接收到数据 */
  215.         rx_len -= dma_data_number_get(DMA1_CHANNEL1); /* 计算实际接收到的数据长度 */
  216.         /* 关闭 dma 通道,关闭中断 */
  217.         dma_channel_enable(DMA1_CHANNEL1, FALSE);
  218.         dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, FALSE);
  219.         usart_interrupt_enable(USART1, USART_IDLE_INT, FALSE);
  220.     }
  221.   /* add user code end USART1_IRQ 0 */
  222.   /* add user code begin USART1_IRQ 1 */
  223.   /* add user code end USART1_IRQ 1 */
  224. }
  225. /* add user code begin 1 */
  226. /* add user code end 1 */



3、测试
可以看到,接收字节数 == 发送字节数
 





 

uart_idle.rar

5.97 MB。
---------------------
作者:cuyebiren
链接:https://bbs.21ic.com/icview-3336688-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/755621
推荐阅读
相关标签
  

闽ICP备14008679号