一、SGM58031
SGM58031是精密模数转换器(ADC)的16位分辨率,其设计精度高,功耗低,易于实现,具有片上基准和振荡器,采用IIC通信,3.3-5V供电。
图1.0 芯片封装
图1.1 芯片引脚
图1.2 芯片地址
图1.3 芯片寄存器地址
电压转换公式(取决于PGA配置):
ADC值 > 0X8000 :采样点电压值 = (0xFFFF - ADC值) / 32768.0 * 增益对应的电压值
ADC值 < 0X8000 :采样点电压值 = ADC值 / 32768.0 * 增益对应的电压值
二、热敏电阻分压转实际温度
本次实验采用的热敏电阻是NCU15WF104D60RC,它是一个负温度系数(NTC)热敏电阻,阻值为100K。原理就是在热敏电阻的基础上再串联一个电阻,形成一个串联分压电路,随着的温度变化热敏电阻的阻值也随之变化,然后经过ADC采样,最终把电压换算成温度。
图2.4 NCU15WF104D60RC热敏电阻参数
图2.5 硬件分压电路
NTC热敏电阻温度计算公式:Rt = R * exp(B * (1 / T1 - 1 / T2))
Rt:随着温度变化的阻值
R:25℃时的阻值,100k
B常数:4250
T1:开尔文温度等于273.15 + 热敏电阻当前阻值对应的摄氏度
T2:273.15+25(K度)
根据图2.5得出
R1:100000.0
R2:200000.0
B常数:4250.0
VCC:3.3
T2:(273.15 + 25)(K度)
温度转换公式:温度值 = ((1 / (log( ((R2 * VCC) / HUB_TMP1点的电压值 - R2) / R1) / B + (1 / T2))) - 273.15 + 0.5)
三、程序
SGM58031源文件:
#include "sgm58031.h"
#include "bsp_iic.h"
#include "esp_log.h"
static const char *TAG = "SMG85031";
/**
* @brief 往SGM发送两个字节函数
* @param
* @arg dev_addr: 器件地址
* @arg reg_addr 寄存器地址
* @arg send_data 发送的数据
* @retval
* @arg ESP_OK:发送成功 ESP_FAIL:发送失败
**/
esp_err_t SGM_SendBytes(uint8_t dev_addr,uint8_t reg_addr,uint16_t send_data)
{
uint8_t write_data[2] = {0};
write_data[0] = (send_data >> 8) & 0x00ff;
write_data[1] = send_data & 0x00ff;
#if I2C_HARDWARE
return I2C_Master_WriteBytes(dev_addr,reg_addr,write_data,sizeof(write_data),200);
#else
EspI2cWriteBytes(dev_addr,reg_addr,write_data,sizeof(write_data));
return ESP_OK;
#endif
}
/**
* @brief 读取SGM两个字节函数
* @param
* @arg dev_addr: 器件地址
* @arg reg_addr: 寄存器地址
* @arg *read_data: 读取的数据
* @retval
* @arg ESP_OK:读取成功 ESP_FAIL:读取失败
**/
esp_err_t SGM_ReadBytes(uint8_t dev_addr,uint8_t reg_addr,uint16_t *read_data)
{
uint8_t reg_data[2] = {0};
esp_err_t ret = ESP_OK;
#if I2C_HARDWARE
ret = I2C_Master_ReadBytes(dev_addr,reg_addr,reg_data,sizeof(reg_data),200);
#else
EspI2cReadBytes(dev_addr,reg_addr,reg_data,sizeof(reg_data));
#endif
*read_data = (uint16_t)((reg_data[0] << 8) | reg_data[1]);
return ret;
}
/**
* @brief SGM配置函数
* @param
* @arg mux 配置连接的引脚
* @retval 无
**/
void SGM_Config(uint32_t mux)
{
// uint16_t reg_value = 0x0;
const smg58031_register_config_t smg58031_config = {
.reg.COMP_QUE = DISABLE_COMPARATOR, //禁用比较器并将ALERT / RDY引脚设置为高阻态
.reg.COMP_LAT = NONLATCHING_COMPARATOR, //非锁存比较器
.reg.COMP_POL = ACTIVE_LOW, //Aler引脚,低电平有效
.reg.COMP_MODE = TRADITIONAL_COMPARATOR, //传统比较器
.reg.DR = RATE_100, //100 SPS
.reg.MODE = POWER_DOWN_SINGLE_SHOT_MODE, //连续转换模式
.reg.PGA = GAIN_1_4096V, //增益为1,引脚最大输入电压为±4.096 + 0.3V
.reg.MUX = mux, //MUX选通的连接到PGA的引脚为AIN0_GND
.reg.OS = BEGIN_A_SINGLE_CONVERSION, //开启一次转换
};
// ESP_LOGI(TAG,"CONVERSION_REG WRITE:%#x\n",smg58031_config.value);
SGM_SendBytes(SGM58031_ADDR,CONFIG_REG,smg58031_config.value);
// SGM_ReadBytes(SGM58031_ADDR,CONFIG_REG,®_value);
// ESP_LOGI(TAG,"CONVERSION_REG READ:%#x\n",reg_value);
}
/**
* @brief 获取SGM数据函数
* @param 无
* @retval
* @arg 获取的数据
**/
void Get_SGM_Data(float *hub_temp)
{
float voltage = 0;
uint16_t adc_value = 0;
static uint32_t ain_num = AIN0_GND;
if(SGM_ReadBytes(SGM58031_ADDR,CONVERSION_REG,&adc_value) == ESP_OK)
{
voltage = adc_value / 32768.0 * 4.096;
if(voltage > 0)
{
*hub_temp = GET_NTC_TEMPRATURE(voltage);
}
ESP_LOGI(TAG,"voltage:%.2f HUB_TEMP:%.2f \n",voltage,*hub_temp);
}
SGM_Config(ain_num);
ain_num++;
if(ain_num > AIN3_GND)
{
ain_num = AIN0_GND;
}
}
SGM58031头文件:
#ifndef _SGM58031_H_
#define _SGM58031_H_
#include <stdio.h>
#include "esp_err.h"
#include "math.h"
//NTC热敏电阻温度计算公式:Rt = R * exp(B * (1 / T1 - 1 / T2))
#define R1 100000.0 //100k热敏电阻
#define R2 200000.0 //200K固定串联分压电阻
#define T2 (273.15 + 25.0) //K度
#define B 4250.0 //B常数
#define VCC 3.3 //串联电阻总电压
//U2 = R2*VCC/(R1+R2)
//R1 = (R2 * VCC) / U2 - R2
//Rt = (R2 * VCC) / voltage - R2; //热敏电阻当前阻值
#define GET_NTC_TEMPRATURE(u2_voltage) ((1 / (log( ((R2 * VCC) / u2_voltage - R2) / R1) / B + (1 / T2))) - 273.15 + 0.5)
//SGM58031设备地址
#define SGM58031_ADDR 0x4B
//SGM58031内部寄存器地址
#define CONVERSION_REG 0x00 //AD值转换寄存器,16bit数据,默认值0x0000,只读
#define CONFIG_REG 0x01 //配置寄存器,默认0x8583,可读可写
#define LO_THRESH_REG 0x02 //比较器阈值下限,默认0x8000
#define HI_THRESH_REG 0x03 //比较器阈值上限,默认0x7FFF
#define CONFIG1_REG 0x04 //扩展配置寄存器,默认0x0000
#define CHIP_ID_REG 0x05 //芯片ID,默认0x0080
#define GN_TRIM1_REG 0x06 //增益修正,默认0x03FA
typedef union
{
uint16_t value;
struct{
uint8_t COMP_QUE:2;
uint8_t COMP_LAT:1;
uint8_t COMP_POL:1;
uint8_t COMP_MODE:1;
uint8_t DR:3;
uint8_t MODE:1;
uint8_t PGA:3;
uint8_t MUX:3;
uint8_t OS:1;
}reg;
}smg58031_register_config_t;
//运行状态或单次转换位
//运行状态或单次转换启动此位确定设备的运行状态。 OS只能在掉电状态下写入,并且在转换正在进行时无效。
enum OS
{
NO_EFFECT = 0, //无效
BEGIN_A_SINGLE_CONVERSION //开启一次转换
};
//输入多路复用器配置
//这些位配置输入多路复用器
enum MUX
{
AIN0_AIN1 = 0, //MUX选通的连接到PGA的引脚为AIN0和AIN1
AIN0_AIN3,
AIN1_AIN3,
AIN2_AIN3,
AIN0_GND,
AIN1_GND,
AIN2_GND,
AIN3_GND
};
//可编程增益放大器配置
//这些位设置可编程增益放大器的FSR
//此参数表示ADC缩放的满量程范围。 请勿对器件的模拟输入施加超过VDD + 0.3 V的电压
enum PGA
{
GAIN_2_3_6144V = 0, //增益为2/3,引脚最大输入电压为±6.144 + 0.3V
GAIN_1_4096V, //增益为1,引脚最大输入电压为±4.096 + 0.3V
GAIN_2_2048V, //增益为2,引脚最大输入电压为±2.048 + 0.3V
GAIN_4_1024V, //增益为4,引脚最大输入电压为±1.024 + 0.3V
GAIN_8_0512V, //增益为8,引脚最大输入电压为±0.512 + 0.3V
GAIN_16_0256V, //增益为16,引脚最大输入电压为±0.256 + 0.3V
GAIN_16_0256V1, //增益为16,引脚最大输入电压为±0.256 + 0.3V
GAIN_16_0256V2 //增益为16,引脚最大输入电压为±0.256 + 0.3V
};
//设备运行模式
//该位控制操作模式。
enum MODE
{
CONTINUOUS_CONVERSION_MODE = 0, //连续转换模式
POWER_DOWN_SINGLE_SHOT_MODE //掉电单次模式
};
//数据速率
//这些位控制数据速率设置。
enum DR
{
RATE_6 = 0, //6.25 SPS
RATE_12, //12.5 SPS
RATE_25, //25.5 SPS
RATE_50, //50 SPS
RATE_100, //100 SPS
RATE_200, //200 SPS
RATE_400, //400 SPS
RATE_800 //800 SPS
};
//比较器模式
//该位配置比较器工作模式di
enum COMP_MODE
{
TRADITIONAL_COMPARATOR = 0, //传统比较器
WINDOW_COMPARATOR //窗口比较器
};
//比较器极性
//该位控制ALERT / RDY引脚的极性
enum COMP_POL
{
ACTIVE_LOW = 0, //低电平有效
ACTIVE_HIGH //高电平有效
};
//比较器锁存
//该位控制ALERT / RDY引脚在置位后是锁存还是在转换后的阈值上限和下限范围内清零
enum COMP_LAT
{
NONLATCHING_COMPARATOR = 0, //非锁存比较器
LATCHING_COMPARATOR //锁存比较器
};
//比较器队列和失能
//这些位执行两个功能。 设置为11时,比较器禁用,ALERT / RDY引脚设置为高阻态。 当设置为任何其他值时,ALERT / RDY引脚和比较器功能被使能,并且设置值确定在断言ALERT / RDY引脚之前超过所需的上限或下限的连续转换次数
enum COMP_QUE
{
ASSERT_AFTER_ONE_CONVERSION = 0, //一次转换后断言
ASSERT_AFTER_TOW_CONVERSION, //两次转换后断言
ASSERT_AFTER_FOUR_CONVERSION, //四次转换后断言
DISABLE_COMPARATOR //禁用比较器并将ALERT / RDY引脚设置为高阻态
};
void SGM_Config(uint32_t mux);
void Get_SGM_Data(float *hub_temp);
#endif
四、验证
硬件需要采集四路电压,软件循环切换通道,实验数据如下:
图4.6 实验数据