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 头文件

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;
}
相关推荐
李永奉3 小时前
51单片机-实现红外遥控模块教程
单片机·嵌入式硬件·51单片机
辛集电子4 小时前
【STM32】位带操作
stm32·单片机·嵌入式硬件
wei-dong-183797540084 小时前
嵌入式硬件工程师每日提问
嵌入式硬件·电源拓扑结构
MOS管-冠华伟业4 小时前
微硕WSF4012 N+P双沟MOS管,驱动汽车智能座椅“无感”升降气泵
单片机·嵌入式硬件
沐欣工作室_lvyiyi4 小时前
基于单片机的汽车防碰撞刹车系统(论文+源码)
单片机·嵌入式硬件·stm32单片机·汽车·毕业设计
点灯小铭5 小时前
基于51单片机宠物喂食系统设计
单片机·mongodb·毕业设计·51单片机·课程设计·宠物
机器视觉知识推荐、就业指导5 小时前
STM32 外设驱动模块:声音传感器模块
stm32·单片机·嵌入式硬件
亿道电子Emdoor5 小时前
【ARM】MDK-Functions界面设置
stm32·单片机·嵌入式硬件
学不动CV了6 小时前
ARM单片机中断及中断优先级管理详解
c语言·arm开发·stm32·单片机·嵌入式硬件·51单片机