【Eval-ADuCM360MKZ评估板】ADI公司24bits的ADC(三):PT100温度测量改进--ADC校准

作者:
上传时间为: 2016-09-19 08:44 AM
2016-09-19
阅读:

接前面的帖子

【Eval-ADuCM360MKZ评估板】ADI公司24bits的ADC(一):开箱+新建工程+测试

【Eval-ADuCM360MKZ评估板】ADI公司24bits的ADC(二):ADC功能测试

【Eval-ADuCM360MKZ评估板】ADI公司24bits的ADC(三):用PT100电阻实现温度测量

之前上一贴中已经用本评估板实现了温度测量,但是测试手指的温度竟然达到了36℃!而我竟然没有发烧!

既然我没有发烧,那么就说明这个温度测得不准,就应该想办法让它测得更准一些;

想到了两个办法:

一是提高测量精度,比如将ADC的性能配置得更加优秀,让它测电压测得更准确一些;

二是重新刻度,比如找个准确的温度计作为参考,按照目前这个板子的实测值刻度一个“准确”的值;

现在找不到准确的温度计,那么就先把ADC好好配置一下吧,对ADC进行校准就是一条路。

①看文档、查资料,了解校准方法;

②编写ADC校准程序,并调试;

③分析,总结,并发帖。

详细过程如下:

①看文档、查资料,了解校准方法;

ADC的出厂值或许对这个温度测量来说,不够准确,那么就需要在使用AD转换之前校准一下;

这款芯片的ADC主要有四种校准模式,主要分失调校准和增益校准;

跟校准有关的寄存器如下:

ADC的模式控制寄存器2_downto_0位

失调校准寄存器

增益校准寄存器

②编写ADC校准程序,并调试;

直接在上一次的程序基础上增加校准配置,ADC0和ADC1都加上

/**
  * @brief  ADC0_Init
  * @param  iStart:ADC状态
  *	- 0 or ADCMDE_ADCMD_OFF for power down.
  *	- 1 or ADCMDE_ADCMD_CONT for continuous conversion.
  *	- 2 or ADCMDE_ADCMD_SINGLE for Single conversion.
  *   - 3 or ADCMDE_ADCMD_IDLE for idle mode.
  *	- 4 or ADCMDE_ADCMD_INTOCAL for offset calibration.
  *	- 5 or ADCMDE_ADCMD_INTGCAL for gain calibration.
  *	- 6 or ADCMDE_ADCMD_SYSOCAL for system offset calibration.
  *	- 7 or ADCMDE_ADCMD_SYSGCAL for system gain calibration.
  * @retval None
  * @brief  配置ADC0参数,并使能ADC0中断
  */	
void ADC0_Init(int iStart)
{
   // Masks in dividual ADC interupt flags 中断控制器
   AdcMski(pADI_ADC0,ADCMSKI_RDY,1);              // Enable ADC ready interrupt source		
   // Sets filter details 配置滤波器参数
   AdcFlt(pADI_ADC0,124,14,FLT_NORMAL|ADCFLT_NOTCH2|ADCFLT_CHOP); // ADC filter set for 3.75Hz update rate with chop on enabled
   // Sets ADC measurement range 设置ADC测量范围
   // 使用内部参考电压,增益=1,有符号整型输出
   AdcRng(pADI_ADC0,ADCCON_ADCREF_INTREF,ADCMDE_PGA_G1,ADCCON_ADCCODE_INT); // Internal reference selected, Gain of 4, Signed integer output
   // Configures ADC buffers 配置ADC的BUFFER
   // Turn off input buffers to ADC and external reference
   // 关闭外部参考缓冲,打开正负缓冲电源,绕过正负缓冲旁路
   AdcBuf(pADI_ADC0,ADCCFG_EXTBUF_OFF,ADCCON_BUFBYPN|ADCCON_BUFBYPP|ADCCON_BUFPOWP|ADCCON_BUFPOWN); 
   // 配置成测电流引脚
   AdcPin(pADI_ADC0,ADCCON_ADCCN_AGND,ADCCON_ADCCP_AIN1);      // P->AIN1,N->AGND
   
   printf ("\n\r出厂值:\n\r");
   printf ("ADC0_OF:%8x    ADC0INTGN:%8x\n\r",pADI_ADC0->OF,pADI_ADC0->INTGN);
   // ADC校准
   AdcGo(pADI_ADC0,ADCMDE_ADCMD_IDLE);          // 先进入空闲模式
   AdcGo(pADI_ADC0,ADCMDE_ADCMD_INTOCAL);       // 内部零电平校准
   while((AdcSta(pADI_ADC0) & BIT5) != BIT5);   // 等待校准完成
   AdcGo(pADI_ADC0,ADCMDE_ADCMD_INTGCAL);       // 内部满量程校准
   while((AdcSta(pADI_ADC0) & BIT5) != BIT5);   // 等待校准完成 
   AdcGo(pADI_ADC0,ADCMDE_ADCMD_SYSOCAL);       // 系统零电平校准
   while((AdcSta(pADI_ADC0) & BIT5) != BIT5);   // 等待校准完成
   AdcGo(pADI_ADC0,ADCMDE_ADCMD_SYSGCAL);       // 内部满量程校准
   while((AdcSta(pADI_ADC0) & BIT5) != BIT5);   // 等待校准完成
   printf ("\n\r校准值:\n\r");
   printf ("ADC0_OF:%8x    ADC0INTGN:%8x\n\r",pADI_ADC0->OF,pADI_ADC0->INTGN);
   
   // ADC初始状态
   AdcGo(pADI_ADC0,iStart);
   // 中断使能
   NVIC_EnableIRQ(ADC0_IRQn);
}


/**
  * @brief  ADC1_Init
  * @param  iStart:ADC状态
  *	- 0 or ADCMDE_ADCMD_OFF for power down.
  *	- 1 or ADCMDE_ADCMD_CONT for continuous conversion.
  *	- 2 or ADCMDE_ADCMD_SINGLE for Single conversion.
  *   - 3 or ADCMDE_ADCMD_IDLE for idle mode.
  *	- 4 or ADCMDE_ADCMD_INTOCAL for offset calibration.
  *	- 5 or ADCMDE_ADCMD_INTGCAL for gain calibration.
  *	- 6 or ADCMDE_ADCMD_SYSOCAL for system offset calibration.
  *	- 7 or ADCMDE_ADCMD_SYSGCAL for system gain calibration.
  * @retval None
  * @brief  配置ADC1参数,并使能ADC1中断
  */	
void ADC1_Init(int iStart)
{
   // Masks in dividual ADC interupt flags 中断控制器
   AdcMski(pADI_ADC1,ADCMSKI_RDY,1);              // Enable ADC ready interrupt source		
   // Sets filter details 配置滤波器参数
   AdcFlt(pADI_ADC1,124,14,FLT_NORMAL|ADCFLT_NOTCH2|ADCFLT_CHOP); // ADC filter set for 3.75Hz update rate with chop on enabled
   // Sets ADC measurement range 设置ADC测量范围
   // 使用内部参考电压,增益=1,有符号整型输出
   AdcRng(pADI_ADC1,ADCCON_ADCREF_INTREF,ADCMDE_PGA_G1,ADCCON_ADCCODE_INT); // Internal reference selected, Gain of 4, Signed integer output
   // Configures ADC buffers 配置ADC的BUFFER
   // Turn off input buffers to ADC and external reference
   // 关闭外部参考缓冲,打开正负缓冲电源,绕过正负缓冲旁路
   AdcBuf(pADI_ADC1,ADCCFG_EXTBUF_OFF,ADCCON_BUFBYPN|ADCCON_BUFBYPP|ADCCON_BUFPOWP|ADCCON_BUFPOWN); 
   // 配置成测电流引脚
   AdcPin(pADI_ADC1,ADCCON_ADCCN_AIN0,ADCCON_ADCCP_AIN1);      // P->AIN1,N->AIN0   

   printf ("\n\r出厂值:\n\r");
   printf ("ADC1_OF:%8x    ADC1INTGN:%8x\n\r",pADI_ADC1->OF,pADI_ADC1->INTGN);
   // ADC校准
   AdcGo(pADI_ADC1,ADCMDE_ADCMD_IDLE);          // 先进入空闲模式
   AdcGo(pADI_ADC1,ADCMDE_ADCMD_INTOCAL);       // 内部零电平校准
   while((AdcSta(pADI_ADC1) & BIT5) != BIT5);   // 等待校准完成
   AdcGo(pADI_ADC1,ADCMDE_ADCMD_INTGCAL);       // 内部满量程校准
   while((AdcSta(pADI_ADC1) & BIT5) != BIT5);   // 等待校准完成 
   AdcGo(pADI_ADC1,ADCMDE_ADCMD_SYSOCAL);       // 系统零电平校准
   while((AdcSta(pADI_ADC1) & BIT5) != BIT5);   // 等待校准完成
   AdcGo(pADI_ADC1,ADCMDE_ADCMD_SYSGCAL);       // 内部满量程校准
   while((AdcSta(pADI_ADC1) & BIT5) != BIT5);   // 等待校准完成
   printf ("\n\r校准值:\n\r");
   printf ("ADC1_OF:%8x    ADC1INTGN:%8x\n\r",pADI_ADC1->OF,pADI_ADC1->INTGN);
   
   // ADC初始状态
   AdcGo(pADI_ADC1,iStart);
   // 中断使能
   NVIC_EnableIRQ(ADC1_IRQn);
}

先编译再跑一下,校准成功了,相关寄存器的值相比出厂值稍微有些变化:

用校准后的ADC测电压来计算温度,运行了一段时间之后:

手放上去一段时间之后:

温度比没校准的时候让人愿意接受一些了。

③分析,总结,并发帖;

把ADC校准了一下,温度测量的值比没校准要好一些,如果能找个已经校准好的温度计来对比一下就更好了。

全部评论 ()
条评论
写评论

创建讨论帖子

登录 后参与评论
系统提示