对STM32内部FLASH编程时遇到的ADC异常问题

发布者:科技先锋最新更新时间:2024-04-19 关键字:STM32 手机看文章 扫描二维码
随时随地手机看文章

某STM32用户使用STM32F407芯片开发产品。用到内部3个ADC,其中ADC1与ADC2工作在ADC双模式,ADC3独立工作。运行代码时给FLASH开锁编程后,发现ADC3不工作了(其DR数据寄存器似乎不更新了,倒是用来触发ADC的定时器TIM2依然正常),Flash编程前后ADC3配置寄存器CR1、CR2没有发生改变。如果重新配置ADC3后就能正常工作。

从问题现象来看,初步感觉跟flash编程有些关系。


经了解,客户的确做了flash编程,有一部分参数需要存放在FLASH内。他的ADC3是由TIM2触发的,ADC3的转换结果是通过DMA搬运。

鉴于此,我这边便提醒他,如果不是基于双BANK条件,在flash编程时CPU是堵塞的,此时若发生中断不会得到响应,让他注意这点及因此可能导致的问题。

客户进一步反馈确认:

1:通ADC结果过DMA读取,并非中断方式获取;

2:FLASH编程过程中禁止了所有中断;

3:奇怪的是ADC3改为由软件触发则没有异常现象。用来触发ADC的定时器一直计数正常,并且只要重新配置ADC3(无须对触发定时器重新配置)也能恢复它的正常工作。

先说下客户提到的在flash编程时将总中断关闭动作。其实,从效果来讲,这个关中断没啥用,反正在Flash编程过程中即使有中断发生CPU也不会给予响应。

结合其反馈,软件触发和定时器触发ADC有个明显差别,就在于定时器的触发对于我们用户来讲往往存在些未知性或不确定性,即不知它具体的触发时间点。客户一直强调TIM工作保持正常,对ADC不能被触发感到奇怪。

整体上,通过问题症状结合经验初步判断是ADC3发生溢出事件了,建议客户做进一步检查确认。

后来,他反馈的确是发生了ADC溢出事件。在FLASH编程前暂停TIM2触发就可以避免溢出发生,不再发生ADC功能异常。

按理说他现在ADC结果是DMA传输,TIM触发DMA时应该可以及时读取数据的,怎么还发生了溢出呢?那就有种可能,在某个时刻,当ADC被TIM触发完成转换后,这时的DMA还没有准备好,导致ADC的结果没有被及时取走。

那什么原因会导致ADC结果不能被及时取走呢?若DMA配置在非循环模式,当DMA传输完成一轮数据后,DMA将不再继续实施数据传输,这时CPU往往还会进入DMA中断服务程序做些必要处理或者为下轮传输做准备。若这个DMA传输完成中断发生在FLASH编程期间,这就可能导致问题。由于该期间它本身不能得到响应,下一轮的DMA传输就没法被开启。但此时的TIM还是依然如故地触发ADC,其结果若不能被及时取走,导致溢出就再自然不过了。

当ADC发生溢出后,如果没有对溢出位做清零,后续的ADC转换动作是不会触发DMA的。具体到本案例,严格地讲,后来客户觉得读不到ADC的更新数据,不是因为ADC不工作,其实它一直被定时器触发转换,只是因为发生了溢出,没法正常触发DMA传输,进而无法实现ADC结果的搬运。

所以,在上述应用情况下,在做flash编程前可以先行关闭定时器,之后再打开。或者在DMA传输完成的中断服务程序里,在重新开启DMA之前,先暂时关闭定时器,对并ADC的溢出及出错做检测处理,之后再开启定时器和DMA传输。


关键字:STM32 引用地址:对STM32内部FLASH编程时遇到的ADC异常问题

上一篇:STM32F4的时钟系统的实现方法
下一篇:一个基于STM32芯片设计的智能循迹往返小车

推荐阅读最新更新时间:2026-03-19 23:13

STM8 ADC读取数据异常问题的解决
做了一个stm8的一个测量电压电流的项目,发现adc通道通过一个10k电阻连接VCC,的时候ADC数据出来都是只有200多,按理说,10位adc应该出来1000多才对,由于adc出来的数据是十六位的,怀疑是串口发送数据的时候数据位数不对。于是改为 uint16_t dat_tmp = 0; // ADC_conf(4); // dat_tmp = ADC_GetConversionValue(); // printf( rnddddddddddrn ); // delay(0xffff); TIM1_SR1 &= ~(1 0); //清除中断标志 ms_count++; if(ms_count 1000) //1ms*
[单片机]
STM8 <font color='red'>ADC</font>读取数据<font color='red'>异常</font>问题的解决
如何用 STM32 FLASH 实现等效 100 万次擦写的 EEPROM 功能?
在单片机开发中, 数据存储 是一个绕不开的话题。EEPROM因其非易失性存储特性,常用于保存配置参数等数据。 然而,EEPROM的擦写次数通常有限,以STM32为例,STM32L0、STM32L4自带的EEPROM一般 10万次 左右,而很多单片机并不内置EEPROM,这时候,利用单片机的FLASH存储器来模拟EEPROM就成为了一个高性价比的解决方案,但,FLASH的擦写次数一般在 1万次 左右,这个我们可以通过ST的官方数据手册看到: 1万次,在很多场景下并不够。 今天,老宇哥跟大家一起探讨,如何用单片机FLA
[嵌入式]
如何用 <font color='red'>STM32</font> <font color='red'>FLASH</font> 实现等效 100 万次擦写的 EEPROM 功能?
STM32外设使用中的五个易错技巧与避坑指南
STM32作为嵌入式开发领域的热门微控制器,功能极为丰富,几乎能够完成所有常见控制任务,如GPIO等外设应有尽有。然而,正因为其功能强大,开发过程中也更容易遇到各种陷阱。许多初学者甚至经验丰富的开发者,常在外设配置上浪费大量时间,调试许久仍难以定位问题。本文总结了5个STM32外设使用中最易出错的技巧,旨在帮助你少走弯路、提高开发效率。 1. GPIO 配置别忘了上拉/下拉 很多初学者在读取按键、外部或中断输入时,会发现输入状态总是不稳定,甚至出现抖动或误触发。这通常是因为 GPIO 输入口浮空造成的。 常见坑: 输入引脚未配置上拉/下拉,导致状态随机波动。 上拉/下拉和外部电路冲突,影响可靠性。 输入误
[嵌入式]
STM32输入捕获
输入捕获是处理器捕获外部输入信号的功能,基于定时器抓取输入信号指定触发方式之间的长度。具体有下面三种触发情况: 1、 上升沿触发 2、 下降沿触发 3、 上下都触发 当触发条件发生后,捕获比较寄存器锁定当前的计数值,如果开启了中断或者DMA,就可以通过中断或DMA及时获得数据进行处理。有时可能遇到上一次触发的标志还没清除,下次触发就发生了,此时会将over-capture标志置位,对于可能出现over-capture的情况,建议先读取数据再清除标志,避免在读取标志后及读取数据前这段时间错过over-capture。 配置输入捕获的步骤: 1. 打开定时器和对应输入引脚的时钟 2. 配置引脚为对应的复用功能 3.
[单片机]
STM32 USART学习
USART(同步异步串口通信) 在STM32的参考手册中,串口被描述成通用同步异步收发器(USART),它提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间进行全双工数据交换。USART利用分数波特率发生器提供宽范围的波特率选择。它支持同步单向通信和半双工单线通信,也支持LIN(局部互联网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。它还允许多处理器通信。还可以使用DMA方式,实现高速数据通信 STM32 中的USART框图 框图 1、引脚编号 TX:发送数据输出 RX:接收数据串行输入 SCLK(位于最右边):发送器时钟输出,仅同步通信时使
[单片机]
vofa+ : 优雅のSTM32串口调试
0、前言 最近工作和电机的学习都要频繁打印数据来调试,但用过keil自带的那debug的都懂啊,用来看看寄存器和打断点就还行,数据监看就完全是顶级折磨,将近半秒钟才刷新一次,纯纯看个乐了。单纯监看数据的话,用串口无疑是更好的选择,比如xcom和sscom,常用的115200波特率就足以把数据闪电般打印出来。 虽然速度的问题解决了,但是看到这无穷无尽的数据长龙宛如看到了我的人生走马灯.....想要在其中找到某几个出问题的数据更无疑是大海捞针。但今天,一切都好起来了,因为一个维新派串口工具改变了一切。 1、工具介绍 本次的主角:vofa+,非常简单的一个串口工具,常见的串口功能都有,但既然它出现在了文章里就证明它没那么简单,是的,
[单片机]
使用Rust开发STM32嵌入式程序入门教程
Why? Rust作为一门新兴语言,其安全、可靠、运行效率高等特点让它成为一门非常适合嵌入式开发的语言。本文主要介绍如何搭建Rust嵌入式开发环境,然后使用stm32h7开发板点个灯。 在嵌入式开发领域,C语言的地位是无法被撼动的(至少在2023年是这样)。用Rust开发嵌入式目前就两个目的: 玩 战未来 :) 适用对象 如果你没有接触过嵌入式编程,或者完全不懂gcc系列的开源工具链,或者完全没有接触过Rust,那么建议先了解一下相关的背景知识。 OK,Let's GO! 搭建Rust开发环境 安装Rust 首先第一步是安装Rust的开发环境。Rust开发环境的安装非常简单,参考https://ru
[单片机]
STM32实现软件复位
实现代码(调用该函数即可): //重新启动 void restartSystem(){ __set_FAULTMASK(1); HAL_NVIC_SystemReset(); } cut-off 相关知识: STM32关全局中断: 第一种方法,:操作PRIMASK寄存器 __set_PRIMASK(0) /* 使能全局中断 */ __set_PRIMASK(1) /* 禁止全局中断*/ 或者 __enable_irq(); /* 使能全局中断 */ __disable_irq(); /* 禁止全局中断*/ PRIMASK 用于除能在 NMI 和硬 fault 之
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved