搜索
bottom↓
回复: 6

【跟我学OSKinetis】第5课-精度时间我做主!ADC!《转》

[复制链接]

出0入0汤圆

发表于 2014-5-15 13:07:27 | 显示全部楼层 |阅读模式
本节课我们来学习一下ADC模块在OSKinetis固件库中的使用方法。在例程包中已经有了关于ADC的单端和差分采集例程,相信大家已经运行过了。在使用过程中,只要进行简单的配置,就可以随意控制转换时间以及转换精度。虽然配置容易,但是具体到每次采集需要消耗多少时间在固件库中并不能表示出来,如果你的应用“没有时间概念”,那么大可不必关心本节课,如果你的应用比较在意模数转换的时间,那么请仔细看看本节课的内容。
与前几课不同,这次我们首先讲解例程,然后说说例程中的采集时间是具体怎么计算的,还有一些ADC模块中比较难懂的概念,我们也会给大家讲讲,比如:AD采样频率和AD时钟、硬件触发、AB组寄存器的区分、PGA可编程增益等等。如果你已经通过自学,可以熟练的使用ADC库函数了,那么可以直接看例程讲解后面的章节。

ADC例程讲解
本节课我们先讲解两个简单的ADC例程,也就是软件触发模式下的单端和差分采集。在后续的课程中我们会详细讲解硬件触发、DMA传输等高级例程。

单端采集-LPLD_AnalogSampleSE
如果你使用RUSH Kinetis开发板,那么可以直接将本例程下载到芯片中,通过旋转母板上的可变电阻器观察结果输出。无论你怎么旋转旋钮,输出结果总是0~4095之间。这说明单端输入的电压量总是、也只能是正电压,旋钮的位置以及相应的原理图如下图所示:

可以从原理图得知,K60的ADC输入引脚ADC0_DP1永远是R7分压得到的,电压值在0~3.3V之间变化。
接下来看代码,找到应用中的ADC初始化函数adc_init(),代码如下:

  adc_init_struct.ADC_Adcx = ADC0;
  adc_init_struct.ADC_DiffMode = ADC_SE;        //单端采集
  adc_init_struct.ADC_BitMode = SE_12BIT;       //单端12位精度
  adc_init_struct.ADC_SampleTimeCfg = SAMTIME_SHORT;    //短采样时间
  adc_init_struct.ADC_HwAvgSel = HW_4AVG;       //4次硬件平均
  adc_init_struct.ADC_CalEnable = TRUE; //使能初始化校验
  LPLD_ADC_Init(adc_init_struct);
  LPLD_ADC_Chn_Enable(ADC0, DAD1);

Line 1:ADC_Adcx成员变量用于配置ADCx的模块号,MK60D系列单片机有ADC0和ADC1两个模块。哦对了,adc_init_struct是在之前定义的ADC初始化结构体变量。
Line 2:ADC_DiffMode用于配置采集模式,分为单端采集和差分采集,这里配置为单端采集。
Line 3:ADC_BitMode用于配置当前ADCx模块的采集精度,这里配置为单端12位精度。需要注意的是,每个ADCx模块只能配置为一种采集精度,也就是说如果ADC0配置为12位精度,那么它包含的所有输入通道均为12位精度。
Line 4:ADC_SampleTimeCfg用于选择长、短采样时间模式,这里配置为段采样时间模式。如果配置为长采样时间模式,还要配置额外需要的时间,这个成员变量是ADC_LongSampleTimeSel。
Line 5:配置ADC_HwAvgSel成员变量来使能硬件平均,同时指定为4次平均。ADC可以配置4、8、16、32次平均,如果不配置此参数,就不使能硬件平均功能。
Line 6:ADC_CalEnable用于使能校验功能,使能校验只会增加初始化的时间,建议使能。
Line 7:调用初始化函数,初始化ADC0模块。
Line 8:调用通道使能函数,使能单端通道DAD1的AD采集复用功能。该函数不是必须调用的,如果该通道对应的引脚没有被配置为其他功能,则不必调用该函数。这里的DAD1通道对应就是上面原理图中的ADC0_DP1引脚。
关于初始化结构体ADC_InitTypeDef成员变量的取值定义,请大家参考在线手册定义(ADC_InitTypeDef)。
初始化完毕后,就可以直接使用AD采集函数获取转换结果了,代码如下:

result = LPLD_ADC_Get(ADC0, DAD1);

Line 1:使用LPLD_ADC_Get()函数可以通过软件触发的模式获取相应ADCx模块不同通道的采集结果。该函数内部首先选择相应输入通道,然后通过判断标志位等待转换结束,也就是说如果转换为结束,该函数不会返回值。如果你采用硬件触发方式或中断方式获取采集数据,那么可以通过LPLD_ADC_GetResult()函数直接读取寄存器的转换结果,使用方法我们后续课程会提及。

差分采集-LPLD_AnalogSampleDIFF
该例程同样用RUSH Kinetis开发板上的旋钮进行试验,不同的是,该例程的运行结果会随着旋钮的转动,输出-2047~2048之间的数。因为在电路中,通过R8和R9的分压,将1.15V的电压输入到了ADC0_DM1引脚,该引脚是DAD1差分通道的负输入端。而正输入端是又R7滑动变阻器进行分压的,因此DAD1差分通道的电压输入是在-1.15~1.15V之间变化的。
接下来看初始化函数代码:

  adc_init_struct.ADC_Adcx = ADC0;
  adc_init_struct.ADC_DiffMode = ADC_DIFF;      //差分采集
  adc_init_struct.ADC_BitMode = DIFF_13BIT;     //差分13位精度
  adc_init_struct.ADC_SampleTimeCfg = SAMTIME_SHORT;    //短采样时间
  adc_init_struct.ADC_HwAvgSel = HW_4AVG;       //4次硬件平均
  adc_init_struct.ADC_CalEnable = TRUE; //使能初始化校验
  LPLD_ADC_Init(adc_init_struct);
  LPLD_ADC_Chn_Enable(ADC0, DAD1);

从代码中只能看到两处与上一个例程不同,分别是Line 2和Line 3,我们只要把采集模式改为差分(ADC_DIFF)、精度模式改为差分13位精度(DIFF_13BIT)即可。
初始化完毕后,同样适用LPLD_ADC_Get()函数采集通道ADC转换数据,不同的是我们需要把转换结果强制转换为有符号类型数字,因为这里的转换结果是差分数据,正负端输入的值可能是个负值,如下所示:

result = (int16)LPLD_ADC_Get(ADC0, DAD1);

当然,变量result也必须是有符号整形才可以。

ADC转换时间
所谓转换时间,就是从使能AD转换通道开始到转换完成标志置位的这段时间,其中使能AD转换通道的动作可以是软件触发也可以是硬件触发。曾经有人说库函数的AD转换函数太慢,有几ms之久,其实那是旧版本库出于稳定考虑采用了最长的转换时间。最新的OSKinetis V3固件库则可以通过配置ADC_SampleTimeCfg(长短采样)、ADC_LongSampleTimeSel(长采样时间选择)、ADC_HwAvgSel(硬件平均)等参数来使用不同的转换时间方案。你只要使用我们编写的ADC转换时间计算工具,就可以轻松得到不同配置模式下的AD转换时间!

转换时间公式解析
首先我们看看K60技术文档中K60P144M100SF2RM.pdf关于ADC转换时间是怎样定义的(如果你不想了解,也不影响固件库的使用),请看该技术文档的Page.838,图表34-95,该公式就是K60的ADC转换时间计算公式:
转换时间 = SFCAdder + 平均次数 * (BCT + LSTAdder + HSCAdder)
SFCAdder-代表单次或首次连续转换时间的累加值,该值由这样几个寄存器位决定:ADLSMP(采样时间配置)、ADACKEN(AD异步时钟输出使能)、ADICLK(输入时钟选择)。具体对应值见技术文档的表34-107。例如:采样时间配置为长时间采样(ADLSMP=1)、使能异步时钟输出(ADACKEN=1)、选择异步时钟(ADICLK=11),那么SFCAdder的值就是5个ADCK周期+5个总线周期。
ADCK-代表AD时钟,他由ADICLK决定,可以是总线时钟、总线时钟/2、备用时钟(ALTCLK)、异步时钟ADACK。
平均次数-代表硬件平均次数,如果仅用硬件平均就是1。
BCT-代表基础转换时间,它由你设定的转换精度决定,具体见技术文档的表34-109。例如选择单端8位精度,那么时间就是17个ADCK周期。
LSTAdder-代表长采样时间模式的时间累加值,如果选择为短采样模式则为0,如果选择为长采样时间模式,则根据ADLSTS(长采样时间选择)寄存器位的值决定,具体见技术文档的表34-110。
HSCAdder-高速转换时间累加值。当ADHSC=0,不采用高速转换时间时该值为0,如果为1,值为2个ADCK周期。

计算固件库中配置的AD转换时间
不知道大家有没有被上面的公式弄糊涂,如果没明白也没关系,因为下面有更方便的方法来知道AD转换时间到底是多少。不过首先你要下载一个“OSKinetis小工具”,打开后选择“ADC Time”选项,根据例程LPLD_AnalogSampleSE中的ADC初始化配置设置相关选项,点击“Calculate”后便会在界面中显示出当前ADC模块的转换时间以及频率,如下图所示:


这个软件中的所有选项名称都是ADC初始化结构体中的成员变量,所有选项都是成员变量的取值,因此你也可以先用此工具配置好各个参数,计算出合适的时间后再去修改代码。该软件计算出来的时间是理论上ADC的转换时间,当然在使用固件库的过程中,会有部分时间损耗在函数的其他代码运行上,转换时间要多出几个us。如果你配置的转换时间越长,计算出来的时间和实际测试时间约近似!
如果你想测试下ADC的转换时间实际是多少,可以用IO口的高低电平变化来测试,例如在调用LPLD_ADC_Get()函数前置某个IO口为1,在调用之后再置IO口0,用示波器观察高电平的时序时间就是ADC的转换时间,当然会比理论计算长一点。

ADC模块解惑
AD采样频率和ADC模块时钟
虽然在使用固件库的时候,不会涉及到AD采样频率和ADC模块时钟这两个概念,但是为了更深入的学习Kinetis,知道总比不知道好。AD采样频率就是AD采样时间的倒数,这个时间的计算方法我们在上面一节已经说了,从公式以及公式各项中我们可以看到ADCK这个名词。ADCK就是ADC模块的时钟,而这个时钟是可以选择的且可以分频的,可以是模块内部生成的异步时钟,也可以是总线时钟、总线时钟/2、或者备用时钟。如下图所示,该图是ADC模块内部框图的一部分,全图可见技术文档的Page.805。


图中红框表示可选的时钟源,绿框表示通过ADICLK这个寄存器位来选择时钟源,蓝框表示经过ADIV分频后输出ADCK时钟。采样频率域ADC时钟最直接的关系,可以理解为一个AD采样时间内,包含n个ADCK,ADCK的频率越快,AD的采样频率也就越快!
ADC的硬件触发
ADC最重要的功能就是硬件触发,通过使用硬件触发模式,可以指定特定事件来触发ADC进行采集作业,而不需要人工用软件去控制ADC何时进行采集,配合DMA的使用,完全可以做到CPU无干预进行AD采集。在Kinetis中,能够触发ADC进行采集的方法除了软件触发之外就仅有PDB模块可以触发AD采集。那么又由什么来触发PDB工作呢,原来PDB还可以再由其他模块进行触发,例如PIT、FTM、软件触发等等。因此倒推回来,ADC就可以间接由PIT、FTM等内部模块进行触发了,例如可以设定PIT模块定时产生请求,触发ADC进行采集。那么你可能又要问了,既然可以用PIT间接触发ADC,那为什么不直接触发还要进过PDB呢,其实PDB并不是一个桥梁那么简单,他可以在接收到内部触发后,延时一段时间再触发AD采集,也可以触发一连串AD采集,具体的我们就不说了,讲到PDB的时候自然会提及。
A、B组寄存器区别
ADC模块的AB组寄存器概念仅涉及它的状态控制寄存器SC1,SC1A可以配置ADC为软件或硬件触发,SC1B只能配置ADC为硬件触发。很多学习ADC寄存器编写的同学对于这两组寄存器到底怎么用存在很大的疑惑,总是和ADC的通道概念相混淆。但是真相只有一个,就是SC1A和SC1B只有一个能暂时去控制ADC进行采集。很多人会问了,那我要俩SC干嘛,只有一个干活。但是你没发现,一个SC干活的话他只能去控制一个通道,如果2个SC轮流干活的话他们就可以同时采集2个通道的数据了!这个就是技术文档中写的,很多人不明白的“ping-pong”控制模式。而且这种高级的控制模式光用ADC一个模块实现不了,还必须配合PDB去控制。
当然具体到固件库的使用,我们已经大大的简化了编写步骤,本节只是给大家一个感性认识。
PGA可编程增益运放
ADC模块有个别通道不仅可以做普通的AD输入使用,还可以把输入的信号做内部放大。然后这个放大不是只是简单的把采集数据进行乘法运算,而是从硬件上进行信号增益。这就为那些成本敏感和空间有限的设计带来了便利!在固件库的使用过程中,可以直接在初始化时配置增益倍数,用ADC_PgaGain这个成员变量,在获取采集结果的时候,要使用正确的具有PGA功能的通道才能获取增益后的数据。对于MK60D单片机来说他只有DAD2通道可以进行可编程增益AD采集。

附上一课链接:
【跟我学OSKinetis】第4课-从启动代码开始看!UART!《转》
http://www.amobbs.com/thread-5580643-1-1.html
(出处: amoBBS 阿莫电子论坛)

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2014-5-16 09:27:40 | 显示全部楼层
感谢楼主的资料分享。

出0入0汤圆

 楼主| 发表于 2014-5-16 12:28:59 | 显示全部楼层
FSL_TICS_ZJJ 发表于 2014-5-16 09:27
感谢楼主的资料分享。

感谢斑竹顶帖子,都没人顶...

出0入0汤圆

发表于 2014-9-5 15:01:28 | 显示全部楼层
mark学习了,最近对飞思卡尔的热情又上升了一步。

出0入13汤圆

发表于 2014-9-7 17:36:50 来自手机 | 显示全部楼层
内容全看完了,讲解得很不错

出0入0汤圆

发表于 2014-9-8 12:26:08 | 显示全部楼层
细看了一遍,楼主写的不错,资料顺便收藏了!

出0入0汤圆

 楼主| 发表于 2014-9-11 08:56:47 | 显示全部楼层
希望对大家有帮助!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-10 08:30

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表