2025年at24c02擦写次数(ntag215擦写)

at24c02擦写次数(ntag215擦写)本文的主要目的是通过学习官方文档 掌握使用 STM32CubeMx 实现 STM32F446ZET 芯片的多重 ADC 采样与 DMA 存储的功能 STM32F4 系列在使用 Cube 时均可以参考本文章 STM32F446 系列有 3 个 ADC 即 ADC1 ADC2 和 ADC3 其中 ADC1 有 19 个通道 ADC2 和 ADC3 有 16 个通道

大家好,我是讯享网,很高兴认识大家。




本文的主要目的是通过学习官方文档,掌握使用STM32CubeMx实现STM32F446ZET6芯片的多重ADC采样与DMA存储的功能,STM32F4系列在使用Cube时均可以参考本文章


    STM32F446系列有3个ADC,即ADC1,ADC2和ADC3,其中ADC1有19个通道,ADC2和ADC3有16个通道。需要注意的ADC的主要参数如下所示:

  • 12-bit,10-bit,8-bit或者6-bit采样
  • 拥有扫描模式,连续模式
  • 有单重模式,双重模式和三重模式
  • 在双重/三重模式中也可开启DMA数据存储
  • 可以使用VREF+提供外置的精确参考电压供ADC采样
  • 在转换结束或者采样值超出设定阈值时产生中断
  • VREF-必须接到VSSA

    下图是关于ADC所使用到的各引脚的电平要求,在设计电路时应注意要对模拟电源电压和数字电源电压进行隔离,对模拟地和数字地进行隔离。一般推荐使用外部芯片产生的高精度参考电压作为VREF+确保ADC采样精度。

 
    
讯享网

    接着是在DMA中断中修改代码令BUFF切换:

讯享网

    只要添加以上两部分代码就可以实现双缓存功能。

    在一些简单的功能实现中,并不需要使用连续模式,而是使用定时器以特定的频率进行扫描采样。这时候需要对ADC的触发源进行配置,来确定在什么情况下触发一次ADC采样。此时可以利用ADC采样完毕后的中断进行数据的处理,该方式适用于定时器触发的频率较低时的采样,可以适应绝大部分情况下的采样需求。

    多重ADC的使用有多种模式,这里只介绍一种模式,三重规则同步模式(triple injected simultaneous mode),即由ADC1控制ADC2和ADC3,三个ADC同时触发一次转换。
    在三重ADC模式下,DMA有3种模式来传输数据,这里只介绍最常用的模式,注意该模式在双重ADC模式下不可使用:
    先传输ADC1的一个半字(half-word),再传输ADC2的一个半字,接着传输ADC3的一个半字,接着传输ADC1的一个半字,如此循环往复。
    再三重规则同步模式下,需要注意三个ADC的采样通道序列的长度应是相等的,可以按照下图中的序列进行采样。再每个Conversion后,都会产生三个DMA传输请求,依次传输ADC1,ADC2,ADC3的数据。请注意,这和双重模式下的DMA是不同的,具体请参考手册。


首先实现一个简单的但能满足大多数情况的模式,即由定时器触发ADC进行一定频率的采样,在DMA的目标缓冲区填满后,触发中断进行数据的处理。需要注意的是,如果打开DMA Continuous Requesets,新采样的数据会覆盖原来的缓冲区,因此要及时对数据进行处理,注意时序问题。

    首先要关注系统时钟,也就是SYSCLK。这里为了保证时钟的精确性,我使用了25MHz的外接晶振HSE作为时钟源,经过简单的数学计算配置SYSCLK为120MHz,配置PCLK2为60MHz,这意味着ADCCLK的最高频率为30MHz。具体时钟树配置如下所示:
在这里插入图片描述

通过阅读手册可以知道,三重ADC同步采样模式下,由ADC1进行整体的管理与触发。因此,关于多重ADC模式的设置位于ADC1的配置界面中。分别使能ADC1,ADC2,ADC3,根据我自己的需求,每个ADC的规则序列有4个通道,ADC1的设置界面如下所示:
在这里插入图片描述
需要注意的是,当不使能DMA Continuous Requests时,DMA在填满缓冲区一次后不会再进行数据的传输,因此一般情况下都应该打开该选项。在ADC1的DMA界面添加DMA,如下图所示,模式设置为Circular:
在这里插入图片描述
对于ADC2和ADC3的设置则较为简单:
在这里插入图片描述
同样要注意打开DMA Continuous Requests,并分别在ADC2与ADC3的DMA界面添加相应的DMA,并将模式设置为Circular。





从ADC1的配置中可以发现,ADC使用了TIM2的Trigger Out event进行触发,因此要对TIM2进行相应的配置。在STM32F4系列中,TIM2的时钟源为PCLK1。由时钟树可知,其时钟频率为60MHz,对于定时器的触发时间,有如下公式:
发生中断时间=(Prescaler+1)* (Period+1)/PCLK1
若设置ADC的采样频率为10KHz ,则有Prescaler=59,Period=99,具体配置如下:
在这里插入图片描述


ADC1,ADC2,ADC3的DMA中断都是默认开启的,不需要修改。定时器中断与其他外设的中断可以根据自己的需求进行开启,需要注意的是,如果使用了SDIO,则在SD卡读写时应当关闭所有中断。

在初始化函数后,添加如下代码即可启动ADC与定时器,需要注意定时器应在ADC启动后再启动,如果想要触发定时器中断,则应使用函数HAL_TIM_Base_Start_IT(&htim2),具体代码如下:

 
讯享网

上述两个函数分别时DMA缓冲区全满与缓冲区半满的回调函数,打开位于stm32f4xx_hal_dma.c的HAL_DMA_RegisterCallback(DMA_HandleTypeDef hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void ( pCallback)(DMA_HandleTypeDef *_hdma))可以知道,每个DMA通道都有很多个回调函数,分别在缓冲区全满,缓冲区半满,双缓存情况下的缓冲区1(另一个是缓冲区0)全满,双缓存情况下的缓冲区1半满等中断下触发相应回调。在本例中,Cube为ADC注册了DMA缓冲区全满,半满以及错误的回调函数,只需要在main.c中对相关回调进行重写即可在触发相应中断时执行自己想要进行的操作。
实际上,有了半满中断后,双缓存的意义便不太大了。在一些特殊情况下,比如需要在采样过程中修改缓冲区的地址,则需要利用DMA的双缓存机制的相关函数,因此下一节对双缓存机制进行探究。

只需要在ADC1,ADC2与ADC3的设置中关闭定时器触发的设置并打开连续模式即可,如下所示:
在这里插入图片描述
此时定时器TIM2可以选择关闭。

需要注意的是,STM32的双缓存机制的设置函数理论上为HAL_DMAEx_MultiBufferStart_IT(),但是使用该函数无法进行缓冲区的切换,可能是官方文档存在一定BUG。为此,我摸索出可以实现相关机制的配置代码如下:

 

在上述代码中,首先利用RegisterCallback函数注册dma的缓冲区2全满回调函数,这样在缓存2填满后会触发回调函数进入用户定义的HAL_ADC_MutiM1ConvCpltCallback()中。同时使用非中断模式启动DMA的双缓存存储,在ADC启动后打开缓冲区全满中断,即DMA_IT_TC标志,可以根据需要选择是否打开缓冲区半满中断,即DMA_IT_HT标志。要注意的是,如果要打开缓冲区半满中断,应当给缓冲区2添加一个缓冲区半满回调函数,只需要再注册函数的调用中将ID从HAL_DMA_XFER_M1CPLT_CB_ID改为HAL_DMA_XFER_M1HALFCPLT_CB_ID,同时再自行定义一个回调函数即可。
双缓存机制的意义在于可以改变缓冲区的目标地址,需要使用
HAL_DMAEx_ChangeMemory()函数,打开stm32f4xx_hal_dma_ex.c文件即可查看该函数的定义和调用方法。


小讯
上一篇 2025-04-14 15:23
下一篇 2025-04-23 21:59

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/205402.html