历史上的今天
今天是:2025年02月18日(星期二)
2020年02月18日 | stm32 TIM2定时器触发ADC、DMA采样
2020-02-18 来源:eefocus
使用ADC的定时器触发ADC转换的功能,然后使用DMA进行数据的搬运!采用TIM2定时器的触发间隔,实现ADC定时采样转换的功能,然后可以在程序的死循环中一直检测DMA转换完成标志,然后进行数据的读取,或者使能DMA转换完成中断,这样每次转换完成就会产生中断。
做示波器时,由于要做调整横坐标显示倍数增大和缩小,故需要改变采样频率,也就是改变TIM2 的定时器时间间隔,在TIM2初始化函数定义时,添加u16 Value参数,第一次调试时,设置如下:
定时器2初始化函数void TIM2_Configuration(u16 Value),配置TIM_Period = Value - 1;
TIM_TimeBaseStructure.TIM_Period = Value - 1;//设置2ms一次TIM2比较的周期(注意此处!!!)
TIM_TimeBaseStructure.TIM_Prescaler = 1;//系统主频56M,这里2分频 (注意此处!!!)
DMA配置:
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;//内存存储基地址
DMA_InitStructure.DMA_BufferSize = 2000;//DMA缓存大小,2000个
ADC配置:
ADC_InitStructure.ADC_ScanConvMode =DISABLE;//关闭扫描模式 因为只有一个通道
ADC_InitStructure.ADC_ContinuousConvMode =DISABLE;//关闭连续转换模式 否则只要触发一次,后续的转换就会永不停歇(除非CONT清0),这样第一次以后的ADC,就不是由TIM2_CC2来触发了
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2;//软件转换模式
示波器中为防止波形频闪,需要用到触发电平。想让触发点定在屏幕中间,在第一次上电触发脉冲到来时,需要DMA中有至少半屏的数据,若半屏为240个点,则另外需要一个定时器来控制这个时间,采用TIM4,设置如下:
TIM_TimeBaseStructure.TIM_Period = 240*Value -1; //240个点的定时时间 (注意此处!!!)
TIM_TimeBaseStructure.TIM_Prescaler = 1; //系统主频56M,这里2分频 (注意此处!!!)
当TIM2定时时间到,使能触发中断。当触发脉冲到来时,记下当前位置,即为触发位置。禁能触发中断并再次启动定时器,采集另外240个点。从上述位置左右各取240个点,显示在屏幕上即可;
遇到的问题:
1、在调整Value值来改变TIM2的时间间隔,240个点的定时时间出错,理论上在进入TIM4的中断时,应采样240多个点(比如为140时,采样242个点),但是Value为280时,才7个点。
分析:
通过查看TIM_Period的数据类型发现,其为u16,即unsigned short,范围为0-65536,当Value为280时,TIM4的TIM_Period为67200,超过了u16的范围,实际设置的TIM_Period值为1664-1。
TIM4的时间间隔:
((1+TIM_Prescaler )/56M)*(1+TIM_Period )=((1+1)/56M)*(1+1664-1)=59.4us
采样周期:
((1+TIM_Prescaler )/56M)*(1+TIM_Period )=((1+1)/56M)*(1+280-1)=10us
通过以上计算,发现Value为280时,为6采样周期,与7个点的时间相差无几,终于找出问题所在;
解决:
由于定时器的分频TIM_Prescaler 设置的比较小,TIM4的TIM_Period 又做了240的乘数,想要增大定时器时间间隔,使得Value很容易超范围,可将TIM_Prescaler设置为19,采样周期为10us(即定时器TIM2时间间隔),Value只需设置为28即可。
2、以上是Value过大时出现的问题,但当Value比较小时,还是在原来的TIM设置条件下,TIM_Prescaler = 1,当Value小于28时,当TIM4定时时间到时,只采集了100多个点。
分析:
ADC转换就是输入模拟的信号量,单片机转换成数字量。读取数字量必须等转换完成后,完成一个通道的读取叫做采样周期。采样周期一般来说=转换时间+读取时间。而转换时间=采样时间+12.5个时钟周期。
CPU的频率为56MHz ,ADC取4分频,即为14MHz,则ADC总转换时间为:TCONV = 1.5 + 12.5 = 14周期= 14/14M = 1μs
故采一个点的时间理论上略大于1us,而在Value设置为28时,TIM2的时间间隔正好为1us,导致240us实际采集的点数比较少,通过多次试验,修改Value的值,发现当取值为32是正好采样正确,为31时则不行,通过计算为1.1us,故需要设置TIM2的采样间隔大于此数值即可。
史海拾趣
|
目录 第一章 概述 第二章 微机及其外设电源电路 第三章 电源维修方面 第四章 不间断电源 第五章 微机直流稳压电源 第六章 显示器电源 第七章 打印机电源 [ 本帖最后由 wzt 于 2010-3-10 18:10 编辑 ]… 查看全部问答> |
|
1 概述 当前,USB外设的开发是一个热点。由于USB总线具有传输速度快、占用资源少及真正的即插即用等优点,越来越受到业界的青睐。可是,USB的开发要求设计人员对USB的标准、Firmware(固件)编程及驱动程序的编写等有较深入的理解,因 ...… 查看全部问答> |
|
现在我用TIM4产生PWM,然后TIM2定时中断往TIM4扔音频数据,现在播放正常,但是发现在配置打开TIM4,TIM2后,USART1好像就失效了,就是串口1不能首发数据了,请问是TIM4,TIM2和串口一有冲突么?… 查看全部问答> |
|
功能强大的串口工具:GhostyComm 4.0(万能通讯精灵) 功能强大的串口工具:GhostyComm 4.0(万能通讯精灵) 本软件是本人在2002初从事单片机开发工作时为了方便调试而编写的,当时是win 98版本。2003年才开发win xp版本。直 ...… 查看全部问答> |
|
关于CEDDK的READ_PORT_UCHAR(<端口号地址>),其中的端口号地址是在哪里定义的呢? 小弟最近在写一个GPIO驱动,在GPI_Read()流接口函数中想用READ_PORT_UCHAR()从指定的GPIO的端口接受数据。我用的是PXA270,其中的GPIO的端口号地址是在哪里定义的呢?我看了PXA270的datasheet好像没有发现。… 查看全部问答> |
|
昨天弄来一个标准5.0的BSP,发现和4.2差别太大了,于是看了一整天OAL的流程以及SD相关的东西, 现在有一些疑惑请大家帮个忙解答一下。 在启动的时候OEMInit函数会调用如下中断初始化函数 //---这个函数并没有初始化EINT16为双边触发啊?怎么回事 ...… 查看全部问答> |




