[AT32F437] ADC 普通组单次模式 + DMA 单次模式 4 路NTC 测温调试笔记

[复制链接]
1408|1
zsf90 发表于 2025-9-9 23:13 | 显示全部楼层 |阅读模式
, , ,
本帖最后由 zsf90 于 2025-9-10 00:34 编辑

首先配置 ADC :

1372868c042a1c62f4.png

1451068c042fb6a984.png

6805468c0433ee56f2.png
开启 DMA 中断
2534968c0435e4986b.png

代码部分:
  1. /* add user code begin Header */
  2. /**
  3. **************************************************************************
  4. * @file     main.c
  5. * @brief    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 "at32f435_437_wk_config.h"
  28. #include "wk_adc.h"
  29. #include "wk_dma.h"
  30. #include "wk_gpio.h"
  31. #include "wk_system.h"
  32. #include "wk_usart.h"

  33. /* private includes ----------------------------------------------------------*/
  34. /* add user code begin private includes */

  35. /* add user code end private includes */

  36. /* private typedef -----------------------------------------------------------*/
  37. /* add user code begin private typedef */

  38. /* add user code end private typedef */

  39. /* private define ------------------------------------------------------------*/
  40. /* add user code begin private define */

  41. /* add user code end private define */

  42. /* private macro -------------------------------------------------------------*/
  43. /* add user code begin private macro */

  44. /* add user code end private macro */

  45. /* private variables ---------------------------------------------------------*/
  46. /* add user code begin private variables */

  47. uint8_t adc_dma_done = 0;
  48. uint16_t adc_buffer[4];

  49. /* add user code end private variables */

  50. /* private function prototypes --------------------------------------------*/
  51. /* add user code begin function prototypes */

  52. /* add user code end function prototypes */

  53. /* private user code ---------------------------------------------------------*/
  54. /* add user code begin 0 */
  55. // 新增:强制重置ADC和DMA状态的函数
  56. void adc_dma_reset(void)
  57. {
  58.     // 1. 关闭ADC和DMA,确保硬件处于初始状态
  59.     adc_ordinary_software_trigger_enable(ADC3, FALSE);
  60.     dma_channel_enable(DMA1_CHANNEL1, FALSE);
  61.     // 重新配置DMA传输
  62.     dma_data_number_set(DMA1_CHANNEL1, 4);  // 设置传输长度
  63.     dma_channel_enable(DMA1_CHANNEL1, TRUE);
  64.         adc_dma_mode_enable(ADC3, TRUE); /* 使能 ADC 的DMA模式,需要在 DMA 搬运完成中关闭 */

  65.     // 2. 清除所有相关标志(包括全局标志)
  66.     /* 清除 ADC 所有标志(经测试不用清除程序一样正常) */
  67.     //adc_flag_clear(ADC3, ADC_OCCE_FLAG | ADC_OCCO_FLAG);
  68.     //dma_flag_clear(DMA1_GL1_FLAG);  // 清除DMA全局标志(关键)
  69.     //dma_flag_clear(DMA1_FDT1_FLAG | DMA1_HDT1_FLAG | DMA1_DTERR1_FLAG);
  70.     adc_ordinary_software_trigger_enable(ADC3, TRUE); /* 软件触发普通组转换 */
  71. }
  72. /* add user code end 0 */

  73. /**
  74. * @brief main function.
  75. * @param  none
  76. * @retval none
  77. */
  78. int main(void)
  79. {
  80.     /* add user code begin 1 */

  81.     /* add user code end 1 */

  82.     /* system clock config. */
  83.     wk_system_clock_config();

  84.     /* config periph clock. */
  85.     wk_periph_clock_config();

  86.     /* nvic config. */
  87.     wk_nvic_config();

  88.     /* timebase config. */
  89.     wk_timebase_init();

  90.     /* init gpio function. */
  91.     wk_gpio_config();

  92.     /* init adc-common function. */
  93.     wk_adc_common_init();

  94.     /* init adc3 function. */
  95.     wk_adc3_init();

  96.     /* init dma1 channel1 */
  97.     wk_dma1_channel1_init();
  98.     /* config dma channel transfer parameter */
  99.     /* user need to modify define values DMAx_CHANNELy_XXX_BASE_ADDR and DMAx_CHANNELy_BUFFER_SIZE in
  100.      * at32xxx_wk_config.h */

  101.     /* init usart1 function. */
  102.     wk_usart1_init();

  103.     /* add user code begin 2 */

  104.     dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); /* 使能 DMA 搬运完成中断 */

  105.         /* 配置 DMA通道参数 */
  106.     wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&ADC3->odt, (uint32_t)adc_buffer, 4);
  107.     /* add user code end 2 */

  108.     while (1)
  109.     {
  110.         /* add user code begin 3 */
  111.         adc_dma_reset();

  112.         /* 等待 DMA 搬运完成 */
  113.         while (!adc_dma_done)
  114.             ;
  115.         adc_dma_done = 0;

  116.         /* 打印采样结果 */
  117.         printf("CH0=%d, CH1=%d, CH2=%d, CH3=%d\r\n", adc_buffer[0], adc_buffer[1], adc_buffer[2], adc_buffer[3]);
  118.                
  119.                 wk_delay_ms(1000);
  120.         /* add user code end 3 */
  121.     }
  122. }

  123. /* add user code begin 4 */
  124. void led_run(void)
  125. {
  126.     static uint16_t count = 0;
  127.         static uint8_t flag = 0;
  128.     count++;
  129.     if (count >= 100)
  130.     {
  131.         count = 0;
  132.         gpio_bits_write(LED1_GPIO_PORT, LED1_PIN, flag = !flag);
  133.     }
  134. }
  135. /* add user code end 4 */
中断文件:
  1. /* add user code begin Header */
  2. /**
  3. **************************************************************************
  4. * @file     at32f435_437_int.c
  5. * @brief    main interrupt service routines.
  6. **************************************************************************
  7. */

  8. /* includes ------------------------------------------------------------------*/
  9. #include "at32f435_437_int.h"

  10. #include "wk_system.h"

  11. extern uint8_t adc_dma_done;
  12. void led_run(void);

  13. /**
  14. * @brief  this function handles systick handler.
  15. * @param  none
  16. * @retval none
  17. */
  18. void SysTick_Handler(void)
  19. {
  20.     wk_timebase_handler();
  21.     led_run();
  22. }

  23. /**
  24. * @brief  this function handles DMA1 Channel 1 handler.
  25. * @param  none
  26. * @retval none
  27. */
  28. void DMA1_Channel1_IRQHandler(void)
  29. {
  30.     if (dma_interrupt_flag_get(DMA1_FDT1_FLAG) != RESET)
  31.     {
  32.         dma_flag_clear(DMA1_FDT1_FLAG);

  33.         adc_dma_mode_enable(ADC3, FALSE); /* 关闭 ADC 的DMA模式(必须,缺少的话会导致只能进入一次该中断) */

  34.         adc_dma_done = 1;
  35.     }

  36. }



我的需求是4路ADC数据采集,在循环中执行软件触发,然后让DMA搬运数据到 adc_buffer 数组中。

遇到的问题是在循环中执行软件触发后只能进入一次DMA中断,结果就是只能打印一次下面的打印语句:
  1. /* 打印采样结果 */
  2. printf("CH0=%d, CH1=%d, CH2=%d, CH3=%d\r\n", adc_buffer[0], adc_buffer[1], adc_buffer[2], adc_buffer[3]);


经过不断的尝试后发现,需要在DMA搬运完成中断中关闭 ADC 的 DMA使能,用下面函数:
  1. adc_dma_mode_enable(ADC3, FALSE); /* 关闭 ADC 的DMA模式(必须,缺少的话会导致只能进入一次该中断) */
AT32_ADC_DMA.gif
微信图片_20250910002557_5_23.jpg
遗忘领域 发表于 2025-9-10 11:38 | 显示全部楼层
这个教程可以说是手把手了,很不错很详细!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

11

帖子

0

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