stm32duino / Arduino_Core_STM32

STM32 core support for Arduino
https://github.com/stm32duino/Arduino_Core_STM32/wiki
Other
2.79k stars 967 forks source link

About the application of DMA&ADC joint function of STM32 developed by CubeIDE on ArduinoIDE #2343

Closed CJT1111 closed 5 months ago

CJT1111 commented 5 months ago

First I read an article @fpistm gave me: https://www.stm32duino.com/viewtopic.php?t=110 Then I wrote the following code according to the article:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Arduino库调用

include

//HAL库调用 extern "C" {

include "stm32f1xx_hal_dma.h"

include "stm32f1xx_hal_adc.h"

include "stm32f1xx_hal.h"

include "stm32f1xx_hal_adc_ex.h"

}

// 串口调用 HardwareSerial Serial1(PA10, PA9); // RX,TX/硬件串口调用(void setup()前)

//HAL模块声明 ADC_HandleTypeDef hadc1; DMA_HandleTypeDef hdma_adc1;

//ADC转换完成标志 volatile bool adc_conversion_complete = false;

// 定义ADC通道和DMA缓冲区 const uint32_t ADC_BUFFER_LENGTH = 2048; //ADC的BUFFER长度 uint16_t adc_buffer[ADC_BUFFER_LENGTH]; //ADC数组

void setup() { // 初始化串口 Serial1.begin(9600); Serial1.println("ADC&DMA测试"); delay(1000);

// 初始化HAL库 HAL_Init();

// 启动ADC和DMA的时钟使能 HAL_RCC_ADC1_CLK_ENABLE(); HAL_RCC_DMA1_CLK_ENABLE();

// 配置ADC hadc1.Instance = ADC1; // 使用ADC1 hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; // 多通道扫描模式 hadc1.Init.ContinuousConvMode = ENABLE; // 连续转换模式 hadc1.Init.DiscontinuousConvMode = DISABLE; // 禁用非连续转换模式 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; //软件触发ADC开始 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // ADC数据右对齐 hadc1.Init.NbrOfConversion = 1; // 转换序列中的转换数(单通道) HAL_ADC_Init(&hadc1); // 配置ADC通道 ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Channel = ADC_CHANNEL_1; //通道设置 sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5; HAL_ADC_ConfigChannel(&hadc1, &sConfig);

// 配置DMA hdma_adc1.Instance = DMA1_Channel1; //通道配置(DMA1_Channel1) hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; //方向配置(从外设到内存) hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; //禁用外设地址增量 hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; //启用内存地址增量 hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //设置外设数据对齐为半字对齐(16位ADC) hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //设置内存数据对齐为半字对齐 hdma_adc1.Init.Mode = DMA_CIRCULAR; //设置DMA工作在循环模式 hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH; //设置DMA通道的优先级为高 HAL_DMA_Init(&hdma_adc1); //DMA配置

//ADC和DMA链接 __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1); //ADC和DMA链接

// 检查DMA中断 HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0); //配置DMA中断优先级 HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); //使能DMA1通道1的中断,允许其响应

// 开始DMA传输 HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_BUFFER_LENGTH); //开始使用DMA进行ADC数据的传输,数据会被传输到adc_buffer数组,长度为ADC_BUFFER_LENGTH }

//分布调数助手 // Serial1.println("ADC&DMA测试分布调试断点[0]"); // delay(1000);

void loop() { // 检查是否完成了一次ADC转换 if (adc_conversion_complete) { adc_conversion_complete = false;

// 选择性地打印部分数据以避免过慢的串口通信
for (int i = 0; i < ADC_BUFFER_LENGTH; i += ADC_BUFFER_LENGTH / 10) {  // 举例:仅打印部分数据点
  Serial1.print("ADC Data [");
  Serial1.print(i);
  Serial1.print("]: ");
  Serial1.println(adc_buffer[i]);
}

} else { Serial1.println("E"); } }

// DMA中断服务程序 void DMA1_Channel1_IRQHandler() { HAL_DMA_IRQHandler(&hdma_adc1); }

// DMA传输完成回调函数 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { adc_conversion_complete = true; }` ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Then this program can be compiled, but I passed the breakpoint test, found that he will be stuck in “*HAL_ADC_Start_DMA(&hadc1, (uint32_t)adc_buffer, ADC_BUFFER_LENGTH);**” here, please see what the problem, thank you.