搜索
bottom↓
回复: 15

[分享]如何实现Kinetis ADC自校准[转]

[复制链接]

出0入0汤圆

发表于 2014-12-24 08:20:52 | 显示全部楼层 |阅读模式
原帖   地址 http://blog.chinaaet.com/detail/38979
  Kinetis内部自带的16位ADC一直是其非常大的优势和特色,毕竟目前市场上ARM MCU端的江山把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电压一致,然后建议校准是在常温下进行,具体实现代码可以参考我贴上来的:



  1. unsigned short cal_var;
  2.    
  3.   ADC0_SC2 &=  ~ADC_SC2_ADTRG_MASK ; // Enable Software Conversion Trigger for Calibration Process    - ADC0_SC2 = ADC0_SC2 | ADC_SC2_ADTRGW(0);   
  4.   ADC0_SC3 &= ( ~ADC_SC3_ADCO_MASK & ~ADC_SC3_AVGS_MASK ); // set single conversion, clear avgs bitfield for next writing
  5.   ADC0_SC30 |= ( ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(AVGS_32) );  // Turn averaging ON and set at max value ( 32 )
  6.    
  7.   ADC0_SC3 |= ADC_SC3_CAL_MASK ;      // Start CAL
  8.   while ( (ADC0_SC1 & ADC_SC1_COCO_MASK ) == 0); // Wait calibration end
  9.       
  10.   if ((ADC0_SC3 & ADC_SC3_CALF_MASK) == ADC_SC3_CALF_MASK )
  11.   {  
  12.    return(1);    // Check for Calibration fail error and return
  13.   }
  14.   // Calculate plus-side calibration
  15.   cal_var = 0x00;
  16.    
  17.   cal_var =  ADC0_CLP0;
  18.   cal_var += ADC0_CLP1;
  19.   cal_var += ADC0_CLP2;
  20.   cal_var += ADC0_CLP3;
  21.   cal_var += ADC0_CLP4;
  22.   cal_var += ADC0_CLPS;
  23.   cal_var = cal_var/2;
  24.   cal_var |= 0x8000; // Set MSB
  25.   ADC0_PG0 = ADC_PG_PG(cal_var);
  26.   
  27.   // Calculate minus-side calibration
  28.   cal_var = 0x00;
  29.    cal_var =  ADC0_CLM0;
  30.   cal_var += ADC0_CLM1;
  31.   cal_var += ADC0_CLM2;
  32.   cal_var += ADC0_CLM3;
  33.   cal_var += ADC0_CLM4;
  34.   cal_var += ADC0_CLMS;
  35.   cal_var = cal_var/2;
  36.   cal_var |= 0x8000; // Set MSB
  37.   ADC0_MG = ADC_MG_MG(cal_var);
  38.    
  39.   ADC0_SC3 &= ~ADC_SC3_CAL_MASK ; /* Clear CAL bit */
复制代码


  按照如上两个步骤即可完成ADC校准,之后再正常写ADC的初始化函数即可,不过需要重点注意一下,在写ADC初始化的时候首先校准寄存器就不要再重复操作了,还有配置寄存器这部分需要特别注意,因为前面两步已经对个别配置寄存器操作了,所以用户在自己写ADC初始化操作的时候要先把要操作的寄存器清0然后再赋值,相信这样做的目的大家都懂的,否则可不一定会想你想的那样正常工作的(举个最简单的例子,因为前面我们对ADC0SC3配置了32均分功能,相应的位为全1,如果下面我们自己写初始化函数的时候想要配置成8均分时就不能或操作了,得先清0再或才是对的,不知道我解释的清楚不,呵呵)。

    好了,该说的都说了,祝大家好运,一次成功,哈哈。今天工作量大了点,一下子写了这么多,脑子有点晕沉沉的,赶紧去吃点好的补补去,呵呵,撤了,再聊,未完待续~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2014-12-24 08:31:13 来自手机 | 显示全部楼层
这个很实用啊,第一次知道单片机的ADC还有自校准功能

出0入0汤圆

发表于 2014-12-24 08:40:47 | 显示全部楼层
这个资料不错 ,ADC自校准 !

出0入0汤圆

发表于 2014-12-24 08:44:31 | 显示全部楼层
话说ST的也有adc校准功能,不过是每次使用adc前要开启一下自校准,算术半自动校准吧?

出100入101汤圆

发表于 2014-12-24 08:45:03 | 显示全部楼层
这个也需要AD支持才行。

出0入0汤圆

发表于 2014-12-24 08:49:46 | 显示全部楼层
学习了,猜想内部肯定是有一个基准来进行校准

出0入0汤圆

发表于 2014-12-24 08:54:20 | 显示全部楼层
这个对应该有很大帮助的哦

出0入0汤圆

发表于 2014-12-24 09:00:38 | 显示全部楼层
还没注意过, 学习了

出0入0汤圆

发表于 2014-12-24 09:14:28 | 显示全部楼层
看原版资料,还是不错的,谢谢分享了

出0入0汤圆

发表于 2014-12-24 09:19:21 来自手机 | 显示全部楼层
浪里白条 发表于 2014-12-24 08:49
学习了,猜想内部肯定是有一个基准来进行校准

我猜是“归零”,类似以前的指针万用表

出0入0汤圆

发表于 2014-12-24 09:29:18 | 显示全部楼层
ijlc1314 发表于 2014-12-24 09:19
我猜是“归零”,类似以前的指针万用表

归零校准的原理是什么呢?

出0入0汤圆

发表于 2014-12-24 16:16:03 | 显示全部楼层
浪里白条 发表于 2014-12-24 09:29
归零校准的原理是什么呢?

我猜测而已,具体并不清楚

出0入0汤圆

发表于 2015-1-5 23:37:54 来自手机 | 显示全部楼层
st的f3系列也是16位

出0入0汤圆

发表于 2015-1-6 00:24:56 来自手机 | 显示全部楼层
好吧,的确屌爆了

出0入0汤圆

发表于 2015-8-27 12:33:36 | 显示全部楼层
写得好,正在看这块,就是不知道用来干什么,现在知道了

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-4-25 08:04

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

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