si7051高精度温度传感器驱动程序
本文的si7051高精度温度传感器驱动程序是基于nrf52832的蓝牙soc,读者可以根据自己的mcu类型进行移植
io驱动文件 i2c.h和i2c.c
i2c.h
#ifndef I2C_H__
#define I2C_H__
#include "nrf_delay.h"
#include "nrf_gpio.h"
#define IIC_OK 0
#define IIC_ERR 0
#define ACK 0
#define NACK 1
#define WaitAckTime 5000
//i2c端口定义
#define IIC_SDA_PIN 7
#define IIC_SCL_PIN 8
#define IIC_SDA_IN {nrf_gpio_cfg_input(IIC_SDA_PIN,NRF_GPIO_PIN_NOPULL);}
#define IIC_SDA_R nrf_gpio_pin_read(IIC_SDA_PIN)
#define IIC_SDA_H {nrf_gpio_cfg_output(IIC_SDA_PIN);nrf_gpio_pin_set(IIC_SDA_PIN);}
#define IIC_SDA_L {nrf_gpio_cfg_output(IIC_SDA_PIN);nrf_gpio_pin_clear(IIC_SDA_PIN);}
#define IIC_SCL_H {nrf_gpio_cfg_output(IIC_SCL_PIN);nrf_gpio_pin_set(IIC_SCL_PIN);}
#define IIC_SCL_L {nrf_gpio_cfg_output(IIC_SCL_PIN);nrf_gpio_pin_clear(IIC_SCL_PIN);}
typedef struct
{
unsigned short IIC_Speed;
} IIC_ControlDef;
extern IIC_ControlDef IIC_ControlStruct;
void IIC_SpeedCtl ( unsigned short Speed );
unsigned short IIC_Read_Speed ( void );
void IIC_Init ( void );
void IIC_Start ( void );
void IIC_Stop ( void );
void IIC_Ack ( void );
uint8_t IIC_WaitAck ( unsigned int TimeOut );
void IIC_NAck ( void );
uint8_t IIC_SendByte ( unsigned char Byte, uint8_t ack);
uint8_t I2C_RecvByte(void);
uint8_t IIC_RecvByte ( uint8_t Ack );
#endif
i2c.c
#include "stdint.h"
#include "i2c.h"
#include "nrf_gpio.h"
/* 变量定义 */
IIC_ControlDef IIC_ControlStruct; //IIC控制结构体
/* IIC速度控制 */
void IIC_SpeedCtl ( unsigned short Speed )
{
IIC_ControlStruct.IIC_Speed = Speed;
}
/* 读取IIC速度 */
unsigned short IIC_Read_Speed ( void )
{
return IIC_ControlStruct.IIC_Speed;
}
/* IIC的IO初始化 */
void IIC_Init ( void )
{
IIC_SpeedCtl ( 5 );
IIC_SDA_H;
IIC_SCL_H;
}
void IIC_Start ( void )
{
IIC_SDA_H
IIC_SCL_H
nrf_delay_us ( IIC_Read_Speed() );
IIC_SDA_L
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_L
}
void IIC_Stop ( void )
{
IIC_SDA_L
IIC_SCL_L
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_H
nrf_delay_us ( IIC_Read_Speed() );
IIC_SDA_H
}
void IIC_Ack ( void )
{
IIC_SCL_L
IIC_SDA_L
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_H
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_L
IIC_SDA_H
}
uint8_t IIC_WaitAck ( unsigned int TimeOut )
{
IIC_SDA_H
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_H
nrf_delay_us ( IIC_Read_Speed() );
IIC_SDA_IN
while ( IIC_SDA_R )
{
if ( !(--TimeOut) )
{
IIC_Stop();
return IIC_ERR;
}
nrf_delay_us ( IIC_Read_Speed() );
}
IIC_SCL_L
return IIC_OK;
}
void IIC_NAck ( void )
{
IIC_SCL_L
IIC_SDA_H
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_H
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_L
}
//IIC_SendByte
uint8_t IIC_SendByte ( unsigned char Byte, uint8_t ack)
{
unsigned char count = 0;
IIC_SCL_L;
for ( ; count < 8; count++ )
{
if ( Byte & 0x80 )
IIC_SDA_H
else
IIC_SDA_L
Byte <<= 1;
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_H
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_L
}
if(!ack)
{
if ( IIC_WaitAck ( WaitAckTime ) )
{
IIC_Stop();
return IIC_ERR;
}
}
return IIC_OK;
}
//I2C_RecvByte
uint8_t I2C_RecvByte(void)
{
uint8_t i;
uint8_t value = 0;
IIC_SDA_IN
for (i = 0; i < 8; i++)
{
value <<= 1;
IIC_SCL_H
nrf_delay_us ( IIC_Read_Speed() );
if (IIC_SDA_R )
{
value++;
}
IIC_SCL_L
nrf_delay_us ( IIC_Read_Speed() );
}
return value;
}
//IIC_RecvByte
uint8_t IIC_RecvByte ( uint8_t Ack )
{
uint8_t count = 0, receive = 0;
IIC_SDA_IN
for ( ; count < 8; count++ )
{
IIC_SCL_L
nrf_delay_us ( IIC_Read_Speed() );
IIC_SCL_H
receive <<= 1;
if ( IIC_SDA_R )
receive++;
nrf_delay_us ( IIC_Read_Speed() );
}
if ( Ack )
IIC_NAck();
else
IIC_Ack();
return receive;
}
温度传感器驱动文件 si7051.h和si7051.c
si7051.h
#ifndef SI7051_H__
#define SI7051_H__
#include "i2c.h"
#define SENSOR_EN_PIN 10
//器件地址
#define SI7051_IIC_SLAVE_ADDR 0x40
#define SI7051_IIC_READ_ADDR ((SI7051_IIC_SLAVE_ADDR << 1) | 0x00)
#define SI7051_IIC_WRITE_ADDR ((SI7051_IIC_SLAVE_ADDR << 1) | 0x01)
#define TEMP_COV_TIME 12 //等待温度测量时间12ms
#define TEMP_DATA_LEN 2 //温度数据长度2字节 整数部分和小数部分
#define SERIAL_NUMBER_SI7050 0x32
#define SERIAL_NUMBER_SI7051 0x33
#define SERIAL_NUMBER_SI7053 0x35
#define SERIAL_NUMBER_SI7054 0x36
#define SERIAL_NUMBER_SI7055 0x37
//命令符
#define SI7051_CMD_MES_TEM_HOLD 0xE3 //温度测量,hold master mode
#define SI7051_CMD_MES_TEM_NO_HOLD 0xF3 //温度测量,no hold master mode
#define SI7051_CMD_RESET 0xFE //复位
#define SI7051_CMD_W_USER_REG 0xE6 //写用户寄存器
#define SI7051_CMD_R_USER_REG 0xE7 //读用户寄存器
#define SI7051_CMD_R_ID_1 0xFA0F //读器件id第一个字节
#define SI7051_CMD_R_ID_2 0xFCC9 //读器件id第二个字节
#define SI7051_CMD_R_FW_VER 0x84B8 //读固件版本
#define USER_REG_RES0_MASK 1
#define USER_REG_RES1_MASK (1<<7)
#define USER_REG_RES0_NO_MASK (~1)
#define USER_REG_RES1_NO_MASK (~(1<<7))
#define MEA_RESOLUTION_14BIT(x) (((x)&USER_REG_RES0_NO_MASK)&USER_REG_RES1_NO_MASK)
#define MEA_RESOLUTION_13BIT(x) (((x)&USER_REG_RES0_NO_MASK)|USER_REG_RES1_MASK)
#define MEA_RESOLUTION_12BIT(x) (((x)|USER_REG_RES0_MASK)&USER_REG_RES1_NO_MASK)
#define MEA_RESOLUTION_11BIT(x) (((x)|USER_REG_RES0_MASK)|USER_REG_RES1_MASK)
void SI7051_power_enable(void);
void SI7051_power_disable(void);
void SI7051_Init ( void );
uint8_t SI7051_IIC_Operation ( uint16_t cmd, uint8_t *wBuf, uint8_t wNum, uint8_t *rBuf, uint8_t rNum);
void temp_to_degrees ( uint8_t *temp, uint16_t *degrees);
void temp_to_int_frac ( uint8_t *temp, uint8_t *int_frac);
void temp_to_CHAR ( uint8_t *temp, uint8_t *cDegree);
#endif
si7051.c
#include "si7051.h"
#include "stdint.h"
#include "stdio.h"
//SI7051_IIC_Operation
//cmd : 命令字符,一个或2个bytes
//wBuf : 待写入的数据
//wNum : 待写入的字节数
//rBuf : 待读取的数据
//rNum : 待读取的字节数
uint8_t SI7051_IIC_Operation ( uint16_t cmd, uint8_t *wBuf, uint8_t wNum, uint8_t *rBuf, uint8_t rNum)
{
switch(cmd)
{
/* 温度测量,hold master mode 数据长度 = 2 bytes */
case SI7051_CMD_MES_TEM_HOLD:
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_WRITE_ADDR, ACK) ) //发送设备地址(写)
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)cmd, ACK ) ) //发送命令
return IIC_ERR;
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_READ_ADDR, ACK ) ) //发送设备地址(读)
return IIC_ERR;
nrf_delay_ms(TEMP_COV_TIME); //clock stretch during measurement 测量的时间 (TODO)
while(rNum--)
{
if ( rNum == 0 )
*rBuf = IIC_RecvByte ( NACK );
else
*rBuf = IIC_RecvByte ( ACK );
rBuf++;
}
IIC_Stop();
break;
/* 温度测量,no hold master mode 数据长度 = 2 bytes */
case SI7051_CMD_MES_TEM_NO_HOLD:
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_WRITE_ADDR, ACK) ) //发送设备地址(写)
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)cmd, ACK ) ) //发送命令
return IIC_ERR;
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_READ_ADDR, NACK ) ) //发送设备地址(读)
return IIC_ERR;
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_READ_ADDR, ACK ) ) //发送设备地址(读)
return IIC_ERR;
while(rNum--)
{
if ( rNum == 0 )
*rBuf = IIC_RecvByte ( NACK );
else
*rBuf = IIC_RecvByte ( ACK );
rBuf++;
}
IIC_Stop();
break;
/* 复位 */
case SI7051_CMD_RESET:
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_WRITE_ADDR, ACK ) ) //发送设备地址(写)
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)cmd, ACK ) ) //发送命令
return IIC_ERR;
IIC_Stop();
break;
/* 写用户寄存器 数据长度 = 1 bytes */
case SI7051_CMD_W_USER_REG:
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_WRITE_ADDR, ACK ) ) //发送设备地址(写)
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)cmd, ACK ) ) //发送命令
return IIC_ERR;
while ( wNum-- )
{
if ( IIC_SendByte ( *wBuf, ACK ) )
return IIC_ERR;
wBuf++;
}
IIC_Stop();
break;
/* 读用户寄存器 数据长度 = 1 bytes */
case SI7051_CMD_R_USER_REG:
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_WRITE_ADDR, ACK ) ) //发送设备地址(写)
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)cmd, ACK ) ) //发送命令
return IIC_ERR;
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_READ_ADDR, ACK ) ) //发送设备地址(读)
return IIC_ERR;
while(rNum--)
{
if ( rNum == 0 )
*rBuf = IIC_RecvByte ( NACK );
else
*rBuf = IIC_RecvByte ( ACK );
rBuf++;
}
IIC_Stop();
break;
/* 读器件id第一个字节 数据长度 = 8 bytes */
/* SNA_3 CRC SNA_2 CRC SNA_1 CRC SNA_0 CRC = 8 bytes */
case SI7051_CMD_R_ID_1:
/* 读器件id第二个字节 数据长度 = 6 bytes */
/* SNB_3 SNB_2 CRC SNB_1 SNB_0 CRC = 6 bytes */
case SI7051_CMD_R_ID_2:
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_WRITE_ADDR, ACK ) ) //发送设备地址(写)
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)(cmd >> 8), ACK ) ) //发送命令高字节
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)cmd , ACK) ) //发送命令低字节
return IIC_ERR;
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_READ_ADDR, ACK ) ) //发送设备地址(读)
return IIC_ERR;
while(rNum--)
{
if ( rNum == 0 )
*rBuf = IIC_RecvByte ( NACK );
else
*rBuf = IIC_RecvByte ( ACK );
rBuf++;
}
IIC_Stop();
break;
/* 读固件版本 数据长度 = 1 bytes*/
case SI7051_CMD_R_FW_VER:
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_WRITE_ADDR, ACK ) ) //发送设备地址(写)
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)(cmd >> 8), ACK ) ) //发送命令高字节
return IIC_ERR;
if ( IIC_SendByte ( (uint8_t)cmd, ACK ) ) //发送命令低字节
return IIC_ERR;
IIC_Start();
if ( IIC_SendByte ( SI7051_IIC_READ_ADDR, ACK ) ) //发送设备地址(读)
return IIC_ERR;
*rBuf = IIC_RecvByte ( NACK );
IIC_Stop();
break;
default:
break;
}
return IIC_OK;
}
/* 温度传感器电源使能 */
void SI7051_power_enable(void)
{
nrf_gpio_cfg_output(SENSOR_EN_PIN);
nrf_gpio_pin_set(SENSOR_EN_PIN);
}
/* 温度传感器电源失能 */
void SI7051_power_disable(void)
{
nrf_gpio_cfg_output(SENSOR_EN_PIN);
nrf_gpio_pin_clear(SENSOR_EN_PIN);
}
/* 温度传感器初始化 */
void SI7051_Init ( void )
{
uint8_t wUserReg = 0;
uint8_t rUserReg = 0;
uint8_t rID[8] = {0};
IIC_Init();
SI7051_power_enable();
SI7051_IIC_Operation ( SI7051_CMD_R_ID_2, &wUserReg, 0, rID, 8); //读ID
if(rID[0] != SERIAL_NUMBER_SI7051)
{
printf("[E] Temp sensor chip not ok\r\n");
return;
}
printf("[D] Temp sensor chip ok\r\n");
//复位后的用户寄存器默认值为0b00111010 :14bit Vdd ok
SI7051_IIC_Operation ( SI7051_CMD_RESET, &wUserReg, 1, &rUserReg, 1);//复位
SI7051_IIC_Operation ( SI7051_CMD_R_USER_REG, &wUserReg, 1, &rUserReg, 1);//读用户寄存器
wUserReg = MEA_RESOLUTION_14BIT(rUserReg); //分辨率设为14bit
SI7051_IIC_Operation ( SI7051_CMD_W_USER_REG, &wUserReg, 1, &rUserReg, 1);//写用户寄存器
printf("[D] Temp sensor init ok\r\n");
}