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

作者:
上传时间为: 2016-09-13 09:03 AM
2016-09-13
阅读:

接前面的帖子:

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

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

这块板是用铂电阻测温的,铂电阻的阻值会随温度变化,变化很接近线性,适用于高精度测温;

本板子用的是PT100,这是百度上搜到的描述:“PT后的100即表示它在0℃时阻值为100欧姆,在100℃时它的阻值约为138.5欧姆。它的工作原理:当PT100在0摄氏度的时候他的阻值为100欧姆,它的的阻值会随着温度上升它的阻值是成匀速增涨的。”

如此看来:测温即测电阻-->测电阻可用测电压和电流再相除的到-->电流实际上也是测电压再用电阻换算而来;

因此实际实现方法就是使用ADC采集电压,然后换算成电流,再换算成电阻,通过PT100的阻值--温度关系得出温度;

之前上一贴中已经做好测温设计的准备工作,那么就可以使用ADC和铂电阻进行测温了:

①看板子电路图,看芯片手册等文档,看网上前人使用铂电阻测温的分享资料,了解铂电阻特性及其测温方法,理清这块板测温的思路;

②编写测温程序,并调试;

③分析,总结,并发帖。

详细过程如下:

①看板子电路图,看芯片手册等文档,看网上前人使用铂电阻测温的分享资料,了解铂电阻特性及其测温方法,理清这块板测温的思路;

这是本板子的测温电路的原理图:

铂电阻跟5K6的电阻串联,测出5K6电阻的电流即为铂电阻的电流,再测出铂电阻两端电压,就可以计算出电阻值了;

其中AIN1、AIN0、AIN6、REFIN+可以接到ADC,AIN1的电压除以5K6就得到了电流,AIN1与AIN0的差分电压可以直接测出来;

AIN6、REFIN+不知道做什么用的……

但是看了下芯片手册ADC部分,看到了这个:

这里有个电流源,可以连接到6脚,AIN6就可以用来给这条路提供电流;

再看到关于这个电流源的说明:

这里写明了可以用来激励外部的RTD传感器,就是本板子上的PT100RTD;

那么现在的思路就是:用AIN6提供激励电流,用AIN1测电流,用AIN1和AIN0测电压;

这个芯片aducm360有两个ADC,可以用其中一个测电流,一个测电压,但是测电流和测电压都用到了AIN1,就是不知道一个引脚可以同时连接

到两个ADC么;

在手册里找到这个:

这里已经找到依据,AIN1可以同时连到两个ADC,那么接下来就可以照着这个思路写程序了:

用AIN6提供激励电流,用AIN1和AGND连接到ADC0测电流,用AIN1和AIN0连接到ADC1测电压;

②编写测温程序,并调试;

照着思路和电路图、手册写程序,配置好激励电流源,配置好ADC0和ADC1,然后开始测温;

先写adc.c

/**
  ******************************************************************************
  * @file    adc.c
  * @author  YangJie
  * @version V1.0
  * @date    2016-9-9
  * @brief   adc function
  ******************************************************************************
  * @attention
  *            ADC0用来测电流
  *            ADC1用来测电压
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include	"adc.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
int32_t adc0_data = 0;
int32_t adc1_data = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/




/**
  * @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
   // 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    
   // ADC初始状态
   AdcGo(pADI_ADC1,iStart);
   // 中断使能
   NVIC_EnableIRQ(ADC1_IRQn);
}




/**
  * @brief  IEXCCON_Init
  * @param  None
  * @retval None
  * @brief  配置激励电流
  */
void IEXCCON_Init(void)
{
   // 配置PIN6上输出电流
   IexcCfg(IEXCCON_PD_off,       // IEXCCON_PD_Off to enable Excitation Current source block
            IEXCCON_REFSEL_Int,  // IEXCCON_REFSEL_Int to select Internal Current reference resistor
            IEXCCON_IPSEL1_AIN6, // IEXCCON_IPSEL1_AIN6 to output IEXC1 to AIN6
            IEXCCON_IPSEL0_Off   // IEXCCON_IPSEL0_Off to disable IEXC0
           );
   // 1.2V/5K6 = 214uA,最大只能设200uA,不然超过ADC上限1.2V
   IexcDat(IEXCDAT_IDAT_100uA,IDAT0En);   // IEXCDAT_IDAT_100uA to output 100uA,IDAT0En to enable 10uA source
}




/**
  * @brief  ADC0_Int_Handler
  * @param  None
  * @retval None
  * @brief  ADC0中断服务函数
  */	
void ADC0_Int_Handler()
{
   volatile unsigned int adc_status_0 = 0;
   
   adc_status_0 = AdcSta(pADI_ADC0);   // read ADC status register
   adc0_data = AdcRd(pADI_ADC0);       // read ADC result register
}


/**
  * @brief  ADC1_Int_Handler
  * @param  None
  * @retval None
  * @brief  ADC1中断服务函数
  */	
void ADC1_Int_Handler()
{
   volatile unsigned int adc_status_1 = 0;
   
   adc_status_1 = AdcSta(pADI_ADC1);   // read ADC status register
   adc1_data = AdcRd(pADI_ADC1);       // read ADC result register
}



再为它写一个adc.h
/**
  ******************************************************************************
  * @file    adc.h
  * @author  YangJie
  * @version V1.0
  * @date    2016-9-9
  * @brief   adc function
  ******************************************************************************
  * @attention
  ******************************************************************************
  */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ADC_H
#define __ADC_H 


/* Includes ------------------------------------------------------------------*/
#include <ADuCM360.h>
#include	"AdcLib.h"
#include	"IexcLib.h"

/* Exported variables ---------------------------------------------------------*/
extern  int32_t adc0_data;
extern  int32_t adc1_data;

/* Exported functions ------------------------------------------------------- */
void ADC0_Init(int iStart);
void ADC1_Init(int iStart);
void IEXCCON_Init(void);

#endif
然后在main.c里进行温度换算
/**
  ******************************************************************************
  * @file    main.c
  * @author  YangJie
  * @version V1.0
  * @date    2016-9-9
  * @brief   Main program body
  ******************************************************************************
  * @attention
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <ADuCM360.h>
#include	"clock.h"
#include "Serial.h"
#include	"delay.h"
#include	"LED.h"
#include	"adc.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
   Clk_Init(); 
   SER_Init();
   delay_init();
   LED_Init();
   ADC0_Init(ADCMDE_ADCMD_CONT);
   ADC1_Init(ADCMDE_ADCMD_CONT);
   IEXCCON_Init();
   
   printf ("\n\r\n\r初始化成功!\n\r\n\r");
   
   /* Infinite loop */
   while (1)
   {
      float value_i = 0.0,value_v = 0.0,value_r = 0.0,value_t = 0.0;
      static uint8_t i = 0;
      
      value_i = (1.2 / 268435456) * adc0_data / 5600;
      value_v = (1.2 / 268435456) * (-adc1_data);
      value_r = value_v / value_i;
      value_t = (value_r - 111.67 ) / 0.387 + 30;   // 30几度处每度0.387欧姆
      
      printf ("\n\r%3d  I: fA   U: fV  R: fΩ  T: f℃\n\r",i++,value_i,value_v,value_r,value_t);
      
      LED_on();
      delay_ms(500);
      LED_off();
      delay_ms(500);
   }
}









编译完成后到板子上跑一下,还可以,ADC没校准,温度也没有校准,大概行;

跑了一段时间后的温度:

手放上去后的温度会升高一些:

感觉手的温度应该不会有这么高,而且还在慢慢上涨,这个东西还需要校准一下才能准;

③分析,总结,并发帖;

至此,已经把温度测量做出来了,就是没有校准过,如果真的要作为一个高精度温度计,还有很多事情要做。

备注:实际测试过,目前这种情况(ADC0P->AIN1,ADC0N->AGND,ADC1P->AIN1,ADC1N->AIN0),把AIN1连到ADC0的负输入端和ADC1的正输入端,实际上还是能正常工作,而手册上写的是同一引脚可以同时连两个ADC的正输入端。

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

创建讨论帖子

登录 后参与评论
系统提示