- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
【原创】如何实现KinetisADC自校准
2014-12-2118:42发表 系统分类:嵌入式系统 自定义分类:Kinetis
标签:KinetisADC自校准
Kinetis内部自带的16位ADC一直是其非常大的优势和特色,毕竟目前市场上ARMMCU端的江山把16位ADC集成到片内去也只有Freescale这样做了,当然这里的16位是指其最高分辨率,其ENOB最好可以做到13.5位,但是这也让其他家MCU的12位ADC拍马也赶不上了
(12位ADC,其ENOB能达到10位就已经算是很好了),在一些医疗电力等应用还是有其独特的优势的。当然,不能一概而论的想当然为其他家也肯定不能把16位ADC做到片内,我觉着各家有各家的权衡,面向的应用对象不同,精度和速度这两个永远是一个矛盾(ADI家那种高大上的高速高精度ADC除外,谁让人家舍得本钱呢,贵有贵的理由),其他家比如ST和Atmel等内部的12位ADC的采样率还是比较快的(12位模式,上1M还是松松的,Freescale的16位ADC配置成12位模式下最高为800多ksps)。
既然Kinetis主打的是高精度,那我们当然要让这个优势发挥到淋漓尽致了,为保证片内ADC的精度和线性度,Freescale在ADC内部集成了自校准功能,这部分最近有人也问过我,我觉着还是写出来分享给大家好了。如下图为校准前(黄色线)与理论值(蓝色线)的比较,当然这个图只是个简单的示意图了,这个时候肯定会有人问到,他之前代码中没有校准也可以正常转换且转换出来的值与实际值也差不多,这个是为什么呢。这个不用担心,实际上可以理解为芯片出厂已经在相关寄存器被写入了一个校准值了,所以一般情况下下图中不校准和校准后的这个offset和gain差是很小的,但是如果我们不是一般情况下呢,呵呵,比如外界环境比较恶劣等条件下还是强烈建议在使用ADC模块前将ADC校准一下为好。说到这,还会有较真的人问到具体的校准原理是什么,我也只能把头摇成个拨浪鼓,俺也不知道,我只能说在校准时VREFL和VREFH这两个脚的电压肯定是需要采样做两点校准的,至于还有哪些点要采样或者中间还有哪些操作,我也懒得再往深了找了,想想头大,呵呵。
说到这里,我需要再提一句,我这里提到的ADC自校准功能并不是想当然的写一个寄存器位触发一次校准然后等着校准完成就OK了。实际上这个过程如果更准确的说应该叫做半自动校准,前半段过程是自动的即写一个寄存器位触发校准然后等待完成,但是后半段则需要手动去做(前半段校准后的值被写到相关寄存器里了,后半段还需要手动对这些寄存器里面的值做一定运算处理后再赋给最终的寄存器)。这部分说起来比较麻烦,我还是直接列出这部分代码,然后大家对照着手册中ADC章节描述校准的部分慢慢消化慢慢理解:
(1)在ADC校准前,我们还是得先让ADC工作起来(因为ADC校准也是通过ADC内部正常工作正常转换的),校准前对ADC模块的配置,手册里也给出了明确的建议如下图,即打开32次硬件平均,ADC的输入时钟小于4MHz,外部VREFH与VDDA电压一致,然后建议校准是在常温下进行,具体实现代码可以参考我贴上来的:
+查看代码
+查看代码
(2)ADC的基本初始化已经完成,下面就马上开始校准了,校准的流程手册里也给出了明确的建议如下图,具体实现代码我也贴上来了:
1 unsignedshortcal_var;2
ADC0_SC2= ~ADC_SC2_ADTRG_MASK;//EnableSoftwareConversionTriggerforCalibrationPro
ADC0_SC3=(~ADC_SC3_ADCO_MASK~ADC_SC3_AVGS_MASK);//setsingleconversion,clearavgs
ADC0_SC30|=(ADC_SC3_AVGE_MASK|ADC_SC3_AVGS(AVGS_32));//TurnaveragingONandsetat6
ADC0_SC3|=ADC_SC3_CAL_MASK; //StartCAL
while((ADC0_SC1ADC_SC1_COCO_MASK)==0);//Waitcalibrationend9
10 if((ADC0_SC3ADC_SC3_CALF_MASK)==ADC_SC3_CALF_MASK)11 {
12 return(1); //CheckforCalibrationfailerrorandreturn13 }
文档评论(0)