TA的每日心情 | 无聊 2016-10-8 20:34 |
---|
签到天数: 10 天 连续签到: 1 天 [LV.3]偶尔看看II
|
接前面的帖子
【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校准了一下,温度测量的值比没校准要好一些,如果能找个已经校准好的温度计来对比一下就更好了。 |
|