STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下;

一、ADC+DMA采样时进入死循环;

解决方法:ADC-dma死循环问题_stm32 adc dma死机-优快云博客

将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Buffer_Size,原本ADC_Buffer_Size是1,改为5之后就不会进入hard_fault死循环了;

二、ADC+DMA连续转换导致写FLASH失败

网上有人说写FLASH之前需要__disable_irq()禁用中断,写FLASH结束再恢复中断,我这么做了但是还是无法写成功(不开启ADC+DMA连续转换前是可以写FLASH的),于是就把连续转换改成了手动软件触发,每次需要ADC数据的时候就软件触发一次,这样才可以正常写入FLASH,也不知道为什么;

还有一个问题需要注意,就是有时候你发现开启了ADC+DMA连续转换,但是ADC只转换一次就不工作了,看看你的DMA配置是不是Circular模式,不是的话需要改成Circular模式才能实现DMA数据的连续接收;

### STM32 HAL库 ADC Timer DMA FFT 示例代码 为了实现ADC与定器、DMA以及FFT的协同工作,在STM32上可以采用如下方法: #### 初始化配置 初始化过程中,需确保ADC模块能够按照指定的间间隔启动转换操作,并通过DMA自动传输数据到存储区。同,还需准备用于FFT处理的数据缓冲区。 ```c // 定义全局变量保存采样点数和FFT长度 #define SAMPLE_POINTS 1024 float32_t adcBuffer[SAMPLE_POINTS]; // 存储原始ADC样本值 float32_t fftInput[SAMPLE_POINTS*2]; // FFT输入数组, 实部+虚部 uint8_t isConversionComplete = 0; // 转换完成标志位 void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_ADC1_Init(void); static void MX_TIM6_Init(void); int main(void){ /* Reset of all peripherals, Initializes the Flash interface and Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); // 初始化DMA控制器 MX_ADC1_Init(); // 初始化ADC外设 MX_TIM6_Init(); // 设置定器作为触发源 // 启动ADC连续模式下的DMA请求 if (HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcBuffer, SAMPLE_POINTS) != HAL_OK){ Error_Handler(__FILE__, __LINE__); } while(1){ if(isConversionComplete){ // 当一次完整的序列采集完毕 memcpy((char *)fftInput, (const char *)adcBuffer, sizeof(float32_t)*SAMPLE_POINTS); arm_cfft_radix4_f32(&fftInstance, fftInput); // 执行快速傅里叶变换 // 对于后续的结果解析... isConversionComplete = 0; } // 其他任务... } } ``` 上述代码片段展示了如何基于HAL库构建基本框架[^1]。这里定义了一个`adcBuffer[]`用来接收来自ADC的实际读数值;而另一个更大的数组`fftInput[]`则专门服务于FFT算法所需的复数表示法——其中前半部分存放实部(即实际测量所得电压),后半部分预留给零填充构成对应的虚部。 当所有的采样都完成后,会触发中断服务例程ISR更新状态标记`isConversionComplete=1`,从而允许主线程继续执行下一步骤的操作,比如调用ARM CMSIS DSP Library中的`arm_cfft_radix4_f32()`来进行频域分析[^2]。 #### 中断回调函数 每当一组新的ADC样品准备好之后就会触发这个回调事件处理器,它负责通知应用程序层已经完成了必要的准备工作以便进一步处理这些新获得的信息。 ```c /* ADC conversion complete callback in non blocking mode */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){ if(hadc->Instance==ADC1){ isConversionComplete = 1; } } ``` 这段简单的逻辑确保了只有当全部预期数量的模拟量都被成功数字化并转移到目标位置以后才会激活相应的指示符,进而促使主循环内的条件分支得以满足去发起下一轮更深层次的数据挖掘活动。 #### 关键注意事项 - **序同步**:考虑到实性和精度的要求,建议仔细调整各个组件之间的工作节奏,特别是要保证ADC采样的速率既不会过低影响最终效果也不会过高超出硬件承受范围。 - **资源分配**:合理规划RAM空间对于嵌入式开发至关重要,尤其是在涉及到大量浮点运算的情况下更是如此。应尽可能优化内存布局减少不必要的浪费。 - **错误检测机制**:尽管示例中省略了一些异常情况的捕捉流程,但在真实项目里务必要加入完善的保护措施防止意外状况的发生造成不可预见的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值