STM32的HAL库驱动ADS124S08进行PT100温度采集
一,环境
单片机:STM32F405RGT6
开发IDE:keil
STM32CubeMX版本:6.15.0
二,简介
2.1 ADS124S08芯片
使用SPI接口与单片机通信。做PT100温度采集,使用差分方式,占了4个信号口,所以12通道,实际驱动3个PT100。
2.2 PT100测温电路
基本原理:使用2个端口,控制恒流源输出IDAC1,IDAC2,另外两个端口采集差分信号。REFP0,REFN0,用于ADC基准(比例测量法)。
三,单片机配置
SPI频率不能超过10MHz。
配置1个DRDY引脚输入,用于采集芯片转换完成信号。(可以不用,芯片支持寄存器读取数据)
四,程序
4.1 头文件
#ifndef __ADS124_H
#define __ADS124_H #include "main.h"
#include "spi.h" //SPI速度不得超过10MHz//命令定义
#define CMD_WAKEUP 0X02 //从掉电模式唤醒
#define CMD_POWERDOWN 0X04 //进入掉电模式
#define CMD_RESET 0X06 //复位
#define CMD_START 0X08 //启动转换
#define CMD_STOP 0X0A //停止转换#define CMD_SYOCAL 0X16 //系统偏移校准
#define CMD_SYGCAL 0X17 //系统增益校准
#define CMD_SFOCAL 0X19 //自身偏移校准#define CMD_RDATA 0X12 //使用命令读取数据
#define CMD_RREG 0X20 //读寄存器,具体用法参考规格书
#define CMD_WREG 0X40 //写寄存器,具体用法参考规格书/*以下18个寄存器*/
#define REG_ID 0X00 //最后一位 0=ADS124S08,1=ADS124S06
#define REG_STATUS 0X01
#define REG_INPMUX 0X02
#define REG_PGA 0X03
#define REG_DATARATE 0X04
#define REG_REF 0X05
#define REG_IDACMAG 0X06
#define REG_IDACMUX 0X07
#define REG_VBIAS 0X08
#define REG_SYS 0X09
#define REG_OFCAL0 0X0A
#define REG_OFCAL1 0X0B
#define REG_OFCAL2 0X0C
#define REG_FSCAL0 0X0D
#define REG_FSCAL1 0X0E
#define REG_FSCAL2 0X0F
#define REG_GPIODAT 0X10
#define REG_GPIOCON 0X11/*增益控制,PGA_ENABLE与下面的GAIN组合成1个字节
放大8倍,则 PGA_ENABLE | GAIN_8
*/
#define PGA_ENABLE 0X08
#define PGA_DISABLE 0X00
#define GAIN_1 0X00
#define GAIN_2 0X01
#define GAIN_4 0X02
#define GAIN_8 0X03
#define GAIN_16 0X04
#define GAIN_32 0X05
#define GAIN_64 0X06
#define GAIN_128 0X07/*速度控制,BIT0-BIT3控制,
需要读取REG_DATARATE寄存器,再修改
*/
#define SPS_2_5 0X00
#define SPS_5 0X01
#define SPS_10 0X02
#define SPS_16_6 0X03
#define SPS_20 0X04 //默认
#define SPS_50 0X05
#define SPS_60 0X06
#define SPS_100 0X07
#define SPS_200 0X08
#define SPS_400 0X09
#define SPS_800 0X0A
#define SPS_1000 0X0B
#define SPS_2000 0X0C
#define SPS_4000 0X0D/* */
/************************************************************************//************************************************************************/
/************************************************************************/typedef struct
{char chipName[15];uint8_t gain;float sampleSpeed;
}ads124Info_T;#define ADS124_COM_PORT hspi1extern ads124Info_T g_tAds124Info;void ADS124_Init(void);
void ADS124_GetPara(void);
void ADS124_WriteCmd(uint8_t cmd);
void ADS124_WriteOneReg(uint8_t reg,uint8_t dat);
uint8_t ADS124_ReadOneReg(uint8_t reg);
void ADS124_ReadAllReg(uint8_t *reg);
uint32_t ADS124_GetADC(void);#endif
4.2 C文件
#include "ads124s08.h"
#include "string.h"uint8_t g_ucADS124Reg[18];
ads124Info_T g_tAds124Info;#define ADS124_GetRdy() HAL_GPIO_ReadPin(ADS124_DRDY_GPIO_Port,ADS124_DRDY_Pin)static void ADS124_CS(uint8_t sta)
{if(sta) HAL_GPIO_WritePin(ADS124_CS_GPIO_Port,ADS124_CS_Pin,GPIO_PIN_SET);else HAL_GPIO_WritePin(ADS124_CS_GPIO_Port,ADS124_CS_Pin,GPIO_PIN_RESET);
}void ADS124_Init()
{uint8_t txBuff[3];HAL_GPIO_WritePin(ADS124_RST_GPIO_Port,ADS124_RST_Pin,GPIO_PIN_RESET);HAL_Delay(500);HAL_GPIO_WritePin(ADS124_RST_GPIO_Port,ADS124_RST_Pin,GPIO_PIN_SET);HAL_Delay(500);ADS124_WriteOneReg(REG_IDACMUX,0X03); //idac1=AIN0 IDAC2=AIN3 ADS124_WriteOneReg(REG_PGA,PGA_ENABLE | GAIN_4); //使能放大,放大倍数4ADS124_WriteOneReg(REG_REF,0X02);//内部基准永远开,(要用IDAC,必须开)ADS124_WriteOneReg(REG_IDACMAG,0X05); //idac电流设置为500ua,(同时使能了IDAC1和IDAC2,会有1000ua)ADS124_WriteOneReg(REG_INPMUX,0X12); //Positive and Negtive ADC input selection,0X12 = AIN1(P) AIN2(N)ADS124_WriteCmd(CMD_SFOCAL);// 自偏移校准HAL_Delay(500); ADS124_WriteCmd(CMD_SYOCAL);// 系统偏移校准HAL_Delay(500);ADS124_WriteCmd(CMD_SYGCAL);// 增益校准HAL_Delay(500);ADS124_WriteCmd(CMD_START);// 开始转换命令
}/*
* 写命令
*/
void ADS124_WriteCmd(uint8_t cmd)
{ADS124_CS(0);HAL_SPI_Transmit(&ADS124_COM_PORT,&cmd,1,100);ADS124_CS(1);
}void ADS124_GetPara(void)
{ADS124_ReadAllReg(g_ucADS124Reg);//芯片型号识别if(g_ucADS124Reg[REG_ID] & 0x01){strcpy(g_tAds124Info.chipName,"ADS124S06");}else{strcpy(g_tAds124Info.chipName,"ADS124S08");}//放大倍数switch(g_ucADS124Reg[REG_PGA] & 0X07){case 0:g_tAds124Info.gain = 1;break;case 1:g_tAds124Info.gain = 2;break;case 2:g_tAds124Info.gain = 4;break;case 3:g_tAds124Info.gain = 8;break;case 4:g_tAds124Info.gain = 16;break;case 5:g_tAds124Info.gain = 32;break;case 6:g_tAds124Info.gain = 64;break;case 7:g_tAds124Info.gain = 128;break;default:break;}//转换速度switch(g_ucADS124Reg[REG_DATARATE] & 0X0f){case 0:g_tAds124Info.sampleSpeed = 2.5f;break;case 1:g_tAds124Info.sampleSpeed = 5.0f;break;case 2:g_tAds124Info.sampleSpeed = 10.0f;break;case 3:g_tAds124Info.sampleSpeed = 16.6f;break;case 4:g_tAds124Info.sampleSpeed = 20.0f;break;case 5:g_tAds124Info.sampleSpeed = 50.0f;break;case 6:g_tAds124Info.sampleSpeed = 60.0f;break;case 7:g_tAds124Info.sampleSpeed = 100.0f;break;case 8:g_tAds124Info.sampleSpeed = 200.0f;break;case 9:g_tAds124Info.sampleSpeed = 400.0f;break;case 10:g_tAds124Info.sampleSpeed = 800.0f;break;case 11:g_tAds124Info.sampleSpeed = 1000.0f;break;case 12:g_tAds124Info.sampleSpeed = 2000.0f;break;case 13:g_tAds124Info.sampleSpeed = 4000.0f;break;case 14:g_tAds124Info.sampleSpeed = 4000.0f;break;default:break;}
}/*
* 直接读取数据,检测到DRDY下降沿后,直接读取,数据由
* 3字节 = ADC数据
* 4字节 = 状态+ADC数据
* 5字节 = 状态+ADC数据+CRC校验
*/
//uint32_t ADS124_GetADC(void)
//{
// uint8_t readBuff[3];
// uint32_t value;// while(ADS124_GetRdy());
//
// ADS124_CS(0);
// HAL_SPI_Receive(&ADS124_COM_PORT,readBuff,3,100);
// ADS124_CS(1);
//
// value = readBuff[0]<<16 | readBuff[1]<<8 | readBuff[2];
// return value;
//
//}/*
* 命令读取数据,无需检测DRDY状态指示,直接读取,数据由
* 3字节 = ADC数据
* 4字节 = 状态+ADC数据
* 5字节 = 状态+ADC数据+CRC校验
*/
uint32_t ADS124_GetADC(void)
{uint8_t txBuff[4] = {0x12}; //RDATA cmduint8_t rxBuff[4];uint32_t value;ADS124_CS(0);HAL_SPI_TransmitReceive(&ADS124_COM_PORT,txBuff,rxBuff,4,100);ADS124_CS(1);value = rxBuff[1]<<16 | rxBuff[2]<<8 | rxBuff[3];return value;
}uint8_t ADS124_ReadOneReg(uint8_t reg)
{uint8_t txBuff[3] = {CMD_RREG,0x00,0x00}; //0x20 = RREGuint8_t rxBuff[3];txBuff[0] |= reg;ADS124_CS(0);HAL_SPI_TransmitReceive(&ADS124_COM_PORT,txBuff,rxBuff,3,100);ADS124_CS(1);return rxBuff[2];
}void ADS124_ReadAllReg(uint8_t *reg)
{for(uint8_t i=0; i<18; i++){*reg = ADS124_ReadOneReg(i);reg++;}
}void ADS124_WriteOneReg(uint8_t reg,uint8_t dat)
{uint8_t txBuff[3] = {CMD_WREG,0x00,0x00}; //0x40 = WREGtxBuff[0] |= reg;txBuff[2] = dat;ADS124_CS(0);HAL_SPI_Transmit(&ADS124_COM_PORT,txBuff,3,100);ADS124_CS(1);
}
5,使用
头文件包含后,使用
ADS124_Init();
ADS124_GetPara();
初始化和参数获取。
ADS124_GetADC();获取数据
目前只配置了一个PT100进行采样,如果要配置3个,则要进行通道转换。。
6,附PT100转换代码
头文件
#ifndef __PT100_H
#define __PT100_H#include "main.h"float PT100_GetTemp(uint32_t adcValue,uint8_t gain);
#endif
C文件
#include "pt100.h"
#include "math.h"#define PT385 //使用PT385#define RES_REF 1000.0F //基准电阻
#define PT100_R0 100.0F //PT100标称电阻//计算公式 R = R0 [1 + A t + B t^2 + C (t – 100) t^3]#ifdef PT385#define A 3.9083E-3
#define B -5.775E-7
#define C_M -4.183E-12 //0度以下系数
#define C_P 0 //0度以上系数#else
#define A 3.9827E-3
#define B -5.875E-7
#define C_M -4.171E-12 //0度以下系数
#define C_P 0 //0度以上系数#endiffloat PT100_GetTemp(uint32_t adcValue,uint8_t gain)
{double r_rtd;double temperature = 0.0;r_rtd = RES_REF * adcValue / (4194304 * gain);// 计算电阻比double r_ratio = r_rtd / PT100_R0;// 区分温度在0度以上和0度以下的情况if (r_ratio >= 1.0) {// 0度以上使用二次方程: R(T)/R0 = 1 + A*T + B*T²// 使用二次方程求根公式: T = [-A + sqrt(A² + 4*B*(R(T)/R0 - 1))]/(2*B)temperature = (-A + sqrt(A*A + 4*B*(r_ratio - 1)))/(2*B);} else {// 0度以下使用四次方程: R(T)/R0 = 1 + A*T + B*T² + C_M*(T-100)*T³// 这里使用牛顿迭代法求解double t_old = -100.0; // 初始猜测值double t_new = 0.0;double error = 1.0;int max_iterations = 50; // 最大迭代次数double tolerance = 0.001; // 容差int iterations = 0;while (error > tolerance && iterations < max_iterations) {// 计算当前温度下的电阻比double r_calc = 1.0 + A*t_old + B*t_old*t_old + C_M*(t_old - 100.0)*t_old*t_old*t_old;// 计算导数double dr_dt = A + 2*B*t_old + C_M*(4*t_old*t_old*t_old - 300*t_old*t_old);// 牛顿迭代t_new = t_old - (r_calc - r_ratio)/dr_dt;// 计算误差error = fabs(t_new - t_old);// 更新温度t_old = t_new;iterations++;}temperature = t_old;}return (float)temperature;
}