当前位置:首页 > 单片机 > 单片机
[导读] 因为公司的产品上需要使用AD来检测电池电压,要求不是很高,突然想用下DMA+ADC+TIM,以前以为很简单,实际使用中让我觉得很惭愧,遇到的问题让我一下子蒙了,不停的查资料,不停的测试,终于一个一个的问题都解决了

 因为公司的产品上需要使用AD来检测电池电压,要求不是很高,突然想用下DMA+ADC+TIM,以前以为很简单,实际使用中让我觉得很惭愧,遇到的问题让我一下子蒙了,不停的查资料,不停的测试,终于一个一个的问题都解决了,同时对stm32的ADC有了新的认识,并且打算再闲暇时间内将stm32的资源尽量的实践下。

我用的是STM32F4 来调试ADC3+DMA+TIM1(单通道),首先我先查看了下DMA的资料,之后参考官方提供的ADC3+DMA很快可以正常读取数据,之后我直接添加定时器触发AD转换,结果失败,我开始查资料看手册,逐渐对这三者之间的关系有了一个认识

首先定时器产生触发信号,AD检测到转换信号后开始转换,每转换一次就通过DMA将数据放到指定的内存地址中,直到达到DMA设定的DMA_BufferSize设定值后DMA置位相应的标志位,从而完成一次DMA传输。

由上面的关系的可以得知ADC转换是一次一次即单次非扫描模式(我测试的是AD单通道),因为连续模式一旦触发就会不停的转换,这样的话定时器触发转换就失去了意义,之后DMA设置成普通模式,即完成一次DMA传输后,停止传输,之后的DMA请求不被响应,因为DMA传输完成后以为着可以进行数据处理了,这个时候为了防止数据被覆盖(网上还有其他方法防止数据被覆盖)。

1>关于定时器的PWM输出

一开始我用定时器1的CH1来作为AD的触发信号对应的管脚是PA8,管脚配置的时候配置成复用模式没有调用 GPIO_PinAFConfig,将PA8复用成TIM1的输出脚,关于定时器的时钟我忽略了一个重要的因素,所以设置的频率一直不对

查看stmf4的参考手册 如果APBx_PRESC为1则定时器的时钟为PCLKx的时钟 否则为2倍的PCLKx

-如果是定时器1和定时器8 需要调用TIM_CtrlPWMOutputs来开启pwm输出之后通过示波器可以正确查看PA8的的波形输出。

2>AD转换

-ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

我对这句一点都不懂,通过查资料发现stm32F4的ADC的DMA有4种模式,主要是为了通过联合使用ADC模块提升采样速度,其中默认模式和模式1差不多,

DMA mode 1 enabled (2 / 3 half-words one by one - 1 then 2 then 3)

//从依次取ADC的值,分辨率为12位,

DMA mode 2 enabled (2 / 3 half-words by pairs - 2&1 then 1&3 then 3&2)

//可以联合使用这三个ADC模块进行采样,采样速度也是单独的三倍(2.4*3Msps),分辨率是12位,完成两次转换后,将值取走应该是

//ADC2+ADC1 ,ADC1+ADC3 ,ADC3+ADC2

DMA mode 3 enabled (2 / 3 bytes by pairs - 2&1 then 1&3 then 3&2)

//模式3和模式2差不多 但是分辨率要求是8位或6位,虽然分辨率降低了但是转换时间相对12位的要短。

-ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

//连续模式必须被禁止,不然定时器触发就失去了意义

ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;

//查看寄存器,发现需要使能外部触发,上面就是开启并制定触发信号的极性

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;

//选择触发时间

-一旦使用外部触发,那么 软件触发就不需要再调用。

3> DMA的传输

-ADC每转换一次,DMA搬运一次,达到指定的次数后,完成一次传输。

-DMA重启,看了网上很多人说DMA关闭后再开启后无法实现DMA传输,在stm32研讨会的演讲稿上有关于DMA重启的解决办法,

我按照第二种方法测试,发现如果处理数据时间长就会有问题,之后我吧定时器和ADC一起关闭之后处理数据,再配置DMA,在开启AD和定时器,就正常了。不太清楚哪里的问题。

-stm32f4的DMA分为数据流和通道,其中通道与stm32f1的触发源类似,F4的数据流与F1的通道类似21ic基础知识

这样ADC+DMA+TIM就正常工作了。

我想用内部ADC把采集的波形通过ucgui显示出来,从而加强对AD的运用与认识,我用stm32采集信号发生器的法波信号进行采集,一次采集300个点,之后通过ucgui将其显示在TFT屏上,为了让波形好看一些,我查了下网上的一些例程和示波器的资料,里面讲到可以通过数字内插的方法将波形重现和回放,数字内插的方法常用的有两种,一种是线性内插一种是sinx/x内插,线性内插比较好了解,关于sinx/x内插就复杂的多,仅仅是理解就很麻烦,数学功底严重不足的悲剧,原理都不懂想用c语言描述就别想了,所以只能用线性内插了,不过网上有关于sinx/x内插的c语言实例,使用线性内插后,波形比之前好看多了,通过调整TIM1的触发信号的频率达到了t/div 的作用如何算频率,一开始我打算把AD采集的结果的最大值和最小值的下标做个差,之后绝对值再乘tim1的周期 后来果断放弃,原因很明显。后来我查询最大值和最小值 之后求平均值,然后一次查询(前一个AD值比均值小且其后一个值比均值大)记录下标,之后查询前一个AD值比均值大且其后一个值比均值小 记录下标,将两次下标做差求绝对值之后与触发信号的频率运算可以求出采集的波形的频率。目前我仅仅测试了占空比为50%的方波信号,效果还好,不过还要完善,比如占空比不为50%的情况。

折腾了几个晚上,我发现stm32的资源很丰富,而我只掌握了很少很少的一部分基础的东西。以后要不断的完善和实践。将折腾的过程中遇到的问题和理解写出来与大家分享,其中有误的地方希望大家提出来交流。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭