本帖最后由 zsf90 于 2025-9-10 00:34 编辑
首先配置 ADC :
开启 DMA 中断
代码部分:
- /* add user code begin Header */
- /**
- **************************************************************************
- * @file main.c
- * @brief main program
- **************************************************************************
- * Copyright notice & Disclaimer
- *
- * The software Board Support Package (BSP) that is made available to
- * download from Artery official website is the copyrighted work of Artery.
- * Artery authorizes customers to use, copy, and distribute the BSP
- * software and its related documentation for the purpose of design and
- * development in conjunction with Artery microcontrollers. Use of the
- * software is governed by this copyright notice and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
- * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
- * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
- * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
- * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
- *
- **************************************************************************
- */
- /* add user code end Header */
- /* Includes ------------------------------------------------------------------*/
- #include "at32f435_437_wk_config.h"
- #include "wk_adc.h"
- #include "wk_dma.h"
- #include "wk_gpio.h"
- #include "wk_system.h"
- #include "wk_usart.h"
- /* private includes ----------------------------------------------------------*/
- /* add user code begin private includes */
- /* add user code end private includes */
- /* private typedef -----------------------------------------------------------*/
- /* add user code begin private typedef */
- /* add user code end private typedef */
- /* private define ------------------------------------------------------------*/
- /* add user code begin private define */
- /* add user code end private define */
- /* private macro -------------------------------------------------------------*/
- /* add user code begin private macro */
- /* add user code end private macro */
- /* private variables ---------------------------------------------------------*/
- /* add user code begin private variables */
- uint8_t adc_dma_done = 0;
- uint16_t adc_buffer[4];
- /* add user code end private variables */
- /* private function prototypes --------------------------------------------*/
- /* add user code begin function prototypes */
- /* add user code end function prototypes */
- /* private user code ---------------------------------------------------------*/
- /* add user code begin 0 */
- // 新增:强制重置ADC和DMA状态的函数
- void adc_dma_reset(void)
- {
- // 1. 关闭ADC和DMA,确保硬件处于初始状态
- adc_ordinary_software_trigger_enable(ADC3, FALSE);
- dma_channel_enable(DMA1_CHANNEL1, FALSE);
- // 重新配置DMA传输
- dma_data_number_set(DMA1_CHANNEL1, 4); // 设置传输长度
- dma_channel_enable(DMA1_CHANNEL1, TRUE);
- adc_dma_mode_enable(ADC3, TRUE); /* 使能 ADC 的DMA模式,需要在 DMA 搬运完成中关闭 */
- // 2. 清除所有相关标志(包括全局标志)
- /* 清除 ADC 所有标志(经测试不用清除程序一样正常) */
- //adc_flag_clear(ADC3, ADC_OCCE_FLAG | ADC_OCCO_FLAG);
- //dma_flag_clear(DMA1_GL1_FLAG); // 清除DMA全局标志(关键)
- //dma_flag_clear(DMA1_FDT1_FLAG | DMA1_HDT1_FLAG | DMA1_DTERR1_FLAG);
- adc_ordinary_software_trigger_enable(ADC3, TRUE); /* 软件触发普通组转换 */
- }
- /* add user code end 0 */
- /**
- * @brief main function.
- * @param none
- * @retval none
- */
- int main(void)
- {
- /* add user code begin 1 */
- /* add user code end 1 */
- /* system clock config. */
- wk_system_clock_config();
- /* config periph clock. */
- wk_periph_clock_config();
- /* nvic config. */
- wk_nvic_config();
- /* timebase config. */
- wk_timebase_init();
- /* init gpio function. */
- wk_gpio_config();
- /* init adc-common function. */
- wk_adc_common_init();
- /* init adc3 function. */
- wk_adc3_init();
- /* init dma1 channel1 */
- wk_dma1_channel1_init();
- /* config dma channel transfer parameter */
- /* user need to modify define values DMAx_CHANNELy_XXX_BASE_ADDR and DMAx_CHANNELy_BUFFER_SIZE in
- * at32xxx_wk_config.h */
- /* init usart1 function. */
- wk_usart1_init();
- /* add user code begin 2 */
- dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); /* 使能 DMA 搬运完成中断 */
- /* 配置 DMA通道参数 */
- wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&ADC3->odt, (uint32_t)adc_buffer, 4);
- /* add user code end 2 */
- while (1)
- {
- /* add user code begin 3 */
- adc_dma_reset();
- /* 等待 DMA 搬运完成 */
- while (!adc_dma_done)
- ;
- adc_dma_done = 0;
- /* 打印采样结果 */
- printf("CH0=%d, CH1=%d, CH2=%d, CH3=%d\r\n", adc_buffer[0], adc_buffer[1], adc_buffer[2], adc_buffer[3]);
-
- wk_delay_ms(1000);
- /* add user code end 3 */
- }
- }
- /* add user code begin 4 */
- void led_run(void)
- {
- static uint16_t count = 0;
- static uint8_t flag = 0;
- count++;
- if (count >= 100)
- {
- count = 0;
- gpio_bits_write(LED1_GPIO_PORT, LED1_PIN, flag = !flag);
- }
- }
- /* add user code end 4 */
中断文件:
- /* add user code begin Header */
- /**
- **************************************************************************
- * @file at32f435_437_int.c
- * @brief main interrupt service routines.
- **************************************************************************
- */
- /* includes ------------------------------------------------------------------*/
- #include "at32f435_437_int.h"
- #include "wk_system.h"
- extern uint8_t adc_dma_done;
- void led_run(void);
- /**
- * @brief this function handles systick handler.
- * @param none
- * @retval none
- */
- void SysTick_Handler(void)
- {
- wk_timebase_handler();
- led_run();
- }
- /**
- * @brief this function handles DMA1 Channel 1 handler.
- * @param none
- * @retval none
- */
- void DMA1_Channel1_IRQHandler(void)
- {
- if (dma_interrupt_flag_get(DMA1_FDT1_FLAG) != RESET)
- {
- dma_flag_clear(DMA1_FDT1_FLAG);
- adc_dma_mode_enable(ADC3, FALSE); /* 关闭 ADC 的DMA模式(必须,缺少的话会导致只能进入一次该中断) */
- adc_dma_done = 1;
- }
- }
我的需求是4路ADC数据采集,在循环中执行软件触发,然后让DMA搬运数据到 adc_buffer 数组中。
遇到的问题是在循环中执行软件触发后只能进入一次DMA中断,结果就是只能打印一次下面的打印语句:
- /* 打印采样结果 */
- 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使能,用下面函数:
- adc_dma_mode_enable(ADC3, FALSE); /* 关闭 ADC 的DMA模式(必须,缺少的话会导致只能进入一次该中断) */
|