一,环境
单片机: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 头文件
c
#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 hspi1
extern 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文件
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); //使能放大,放大倍数4
ADS124_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 cmd
uint8_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 = RREG
uint8_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 = WREG
txBuff[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转换代码
头文件
c
#ifndef __PT100_H
#define __PT100_H
#include "main.h"
float PT100_GetTemp(uint32_t adcValue,uint8_t gain);
#endif
C文件
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度以上系数
#endif
float 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;
}