TA的每日心情 | 无聊 2016-10-8 20:34 |
---|
签到天数: 10 天 连续签到: 1 天 [LV.3]偶尔看看II
|
接前面的帖子:
【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的正输入端。 |
|