Stlm75与Hts221都是ST的传感器,有官方例程,我只是做了个搬运而已,Spg30网上也有驱动示例,所以我只是拿别人的代码过来水一贴
/**
******************************************************************************
* @file bsp_i2c.c
* @author
* @version V1.1
* @date Mar 5, 2021
* @brief
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "bsp_i2c.h"
/* Private Typedef -----------------------------------------------------------*/
/* Private Define ------------------------------------------------------------*/
#define I2Cx_TIMEOUT_MAX 3000
#define I2Cx_MAXTRIALSIFERROR 50
/* Private Enum --------------------------------------------------------------*/
/* Private Struct ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Extern variables ---------------------------------------------------------*/
/* Private Functions Prototypes-----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* Extern Functions ---------------------------------------------------------*/
/**
* @brief 向指定的地址写入一个字节的值
* @param Addr: I2C地址
* @param Reg: 写地址
* @param Value: 要写的数据
* @retval 执行状态码
*/
HAL_StatusTypeDef I2Cx_WriteData( I2C_HandleTypeDef *hi2c, uint16_t Addr, uint8_t Reg, uint8_t Value )
{
return ( HAL_I2C_Mem_Write( hi2c, Addr, (uint16_t)Reg, I2C_MEMADD_SIZE_8BIT, &Value, 1, I2Cx_TIMEOUT_MAX ) );
}
/**
* @brief 向指定的寄存器地址写入多个数据
* @param Addr: I2C地址I2C地址
* @param Reg: 写地址
* @param RegSize: 写地址大小 (8BIT or 16BIT)
* @param pBuffer: 要写的数据
* @param Length: 数据长度
* @retval 执行状态码
*/
HAL_StatusTypeDef I2Cx_WriteBuffer( I2C_HandleTypeDef *hi2c, uint16_t Addr, uint8_t Reg, uint16_t RegSize, uint8_t *pBuffer, uint16_t Length )
{
return ( HAL_I2C_Mem_Write( hi2c, Addr, (uint16_t)Reg, RegSize, pBuffer, Length, I2Cx_TIMEOUT_MAX ) );
}
/**
* @brief 从指定的地址读出一个字节的内容
* @param Addr: I2C地址
* @param Reg: 读地址
* @retval 成功返回读出的数据,错误返回HAL_ERROR
*/
uint8_t I2Cx_ReadData( I2C_HandleTypeDef *hi2c, uint16_t Addr, uint8_t Reg )
{
uint8_t value = 0;
/* Check the communication status */
if ( HAL_OK != HAL_I2C_Mem_Read( hi2c, Addr, Reg, I2C_MEMADD_SIZE_8BIT, &value, 1, I2Cx_TIMEOUT_MAX ) )
return HAL_ERROR;
return value;
}
/**
* @brief 从指定的寄存器地址读出多个数据
* @param Addr: I2C地址I2C地址
* @param Reg: 读地址
* @param RegSize: 读地址大小 (8BIT or 16BIT)
* @param pBuffer: 存储读出数据的缓冲区
* @param Length: 数据长度
* @retval 执行状态码
*/
HAL_StatusTypeDef I2Cx_ReadBuffer( I2C_HandleTypeDef *hi2c, uint16_t Addr, uint8_t Reg, uint16_t RegSize, uint8_t *pBuffer, uint16_t Length )
{
return ( HAL_I2C_Mem_Read( hi2c, Addr, (uint16_t)Reg, RegSize, pBuffer, Length, I2Cx_TIMEOUT_MAX ) );
}
/**
* @brief 检查指定地址的I2C设备通讯是否正常
* @note 只用于Rom设备
* @param DevAddress: 设备地址
* @param Trials: 测试值
* @retval 状态
*/
HAL_StatusTypeDef I2Cx_IsDeviceReady( I2C_HandleTypeDef *hi2c, uint16_t DevAddress )
{
return ( HAL_I2C_IsDeviceReady( hi2c, DevAddress, I2Cx_MAXTRIALSIFERROR, I2Cx_TIMEOUT_MAX ) );
}
/********************************* END OF FILE *********************************/
/**
******************************************************************************
* @file module_stlm75.c
* @author
* @version V1.1
* @date Mar 5, 2021
* @brief
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "module_stlm75.h"
#include "bsp_i2c.h"
#include "tool.h"
/* Private Typedef -----------------------------------------------------------*/
/* Private Define ------------------------------------------------------------*/
/* 设备地址 */
#define STLM75_I2C_ADDRESS 0x90
/*
* STLM75 命令寄存器
*/
/* Read Access Only */
#define STLM75_REG_TEMP 0x00 /* Temperature Register of LM75 */
/* Read/Write Access */
#define STLM75_REG_CONF 0x01 /* Configuration Register of LM75 */
#define STLM75_REG_THYS 0x02 /* Temperature Register of LM75 */
#define STLM75_REG_TOS 0x03 /* Over-temp Shutdown threshold Register of LM75 */
/*
* STLM75 模式选择
*/
#define STLM75_CONTINUOUS_MODE ((uint8_t)0x00)
#define STLM75_ONE_SHOT_MODE ((uint8_t)0x01)
#define STLM75_COMPARATOR_MODE ((uint8_t)0x00)
#define STLM75_INTERRUPT_MODE ((uint8_t)0x02)
/*
* Alert outside range Limit Temperature 12° <-> 40°c
*/
#define STLM75_TEMPERATURELIMITHIGH 40
#define STLM75_TEMPERATURELIMITlow 12
/* Private Enum --------------------------------------------------------------*/
/* Private Struct ------------------------------------------------------------*/
/* Stlm75温度传感器配置结构体 */
typedef struct
{
uint8_t AlertMode; /* Alert Mode Temperature out of range*/
uint8_t ConversionMode; /* Continuous/One Shot Mode */
uint8_t ConversionResolution; /* Temperature Resolution */
uint8_t ConversionRate; /* Number of measure per second */
uint8_t TemperatureLimitHigh; /* High Temperature Limit Range */
uint8_t TemperatureLimitLow; /* Low Temperature Limit Range */
}STLM75_InitTypeDef;
/* Private variables ---------------------------------------------------------*/
/* Extern variables ---------------------------------------------------------*/
/* Private Functions Prototypes-----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Writes one byte to the TSENSOR.
* @param DevAddress: Target device address
* @param pBuffer: Pointer to data buffer
* @param WriteAddr: TSENSOR's internal address to write to.
* @param Length: Number of data to write
*/
static uint8_t STLM75_Write( uint8_t* pBuffer, uint8_t WriteAddr, uint16_t Length )
{
return ( I2Cx_WriteBuffer( &hi2c1, STLM75_I2C_ADDRESS, WriteAddr, I2C_MEMADD_SIZE_8BIT, pBuffer, Length ) );
}
/**
* @brief Reads one byte from the TSENSOR.
* @param DevAddress: Target device address
* @param pBuffer : pointer to the buffer that receives the data read from the TSENSOR.
* @param ReadAddr : TSENSOR's internal address to read from.
* @param Length: Number of data to read
*/
static uint8_t STLM75_Read( uint8_t* pBuffer, uint8_t ReadAddr, uint16_t Length )
{
return ( I2Cx_ReadBuffer( &hi2c1, STLM75_I2C_ADDRESS, ReadAddr, I2C_MEMADD_SIZE_8BIT, pBuffer, Length ) );
}
/**
* @brief 检查指定地址的I2C设备通讯是否正常
* @note 只用于Rom设备
* @param DevAddress: 设备地址
* @param Trials: 测试值
* @retval 状态
*/
static uint8_t STLM75_IsDeviceReady( void )
{
return ( I2Cx_IsDeviceReady( &hi2c1, STLM75_I2C_ADDRESS ) );
}
/* Extern Functions ---------------------------------------------------------*/
/**
* @brief STLM75温度传感器初始化
* @param void
* @note void
* @retval 初始化状态
*/
uint8_t STLM75_Init( void )
{
uint8_t confreg = 0;
uint16_t tempreg = 0;
/* 检查设备是否正常 */
if ( STLM75_IsDeviceReady() != HAL_OK ) {
Db_Error("Stlm75 device is error!!!");
return HAL_ERROR;
}
do {
/* Set the Configuration Register */
confreg = (uint8_t)( STLM75_COMPARATOR_MODE | STLM75_CONTINUOUS_MODE );
if ( STLM75_Write( &confreg, STLM75_REG_CONF, 1 ) != HAL_OK )
break;
/* Set the Temperature Registers */
/* Keep the sign bit and shift the temperature value (as given value is integer, the 0.5 digit is not set) */
tempreg = ( ( ( STLM75_TEMPERATURELIMITHIGH & 0x007F) << 8) | ( STLM75_TEMPERATURELIMITHIGH & 0x8000 ) );
if ( STLM75_Write( (uint8_t*)(&tempreg), STLM75_REG_TOS, 2 ) != HAL_OK )
break;
tempreg = ( ( ( STLM75_TEMPERATURELIMITlow & 0x007F) << 8) | ( STLM75_TEMPERATURELIMITlow & 0x8000) );
if ( STLM75_Write( (uint8_t*)(&tempreg), STLM75_REG_THYS, 2 ) != HAL_OK )
break;
return HAL_OK;
} while ( 0 );
return HAL_ERROR;
}
/**
* @brief Read The Temperature Sensor Status
* @param void
* @retval Status
*/
uint8_t STLM75_ReadStatus( void )
{
uint8_t tmp = 0;
/* Read Status register */
STLM75_Read( &tmp, STLM75_REG_CONF, 1 );
/* Return Temperature Sensor Status */
return (uint8_t)(tmp);
}
/**
* @brief Read ID address of STLM75
* @param void
* @retval ID name
*/
uint16_t STLM75_ReadTemp( void )
{
uint16_t tempreg = 0;
uint16_t tmp = 0;
/* Read Temperature registers */
STLM75_Read( (uint8_t*)(&tempreg), STLM75_REG_TEMP, 2 );
tmp = ((tempreg & 0x00FF) << 8) | ((tempreg & 0xFF00) >> 8);
tempreg = (((tmp & 0x7F80) >> 7) | (tmp & 0x8000));
/* Return Temperature value */
return ( tempreg / 2 );
}
/********************************* END OF FILE *********************************/
/**
******************************************************************************
* @file module_stlm75.c
* @author
* @version V1.1
* @date Mar 5, 2021
* @brief
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "module_stlm75.h"
#include "bsp_i2c.h"
#include "tool.h"
/* Private Typedef -----------------------------------------------------------*/
/* Private Define ------------------------------------------------------------*/
/* 设备地址 */
#define STLM75_I2C_ADDRESS 0x90
/*
* STLM75 命令寄存器
*/
/* Read Access Only */
#define STLM75_REG_TEMP 0x00 /* Temperature Register of LM75 */
/* Read/Write Access */
#define STLM75_REG_CONF 0x01 /* Configuration Register of LM75 */
#define STLM75_REG_THYS 0x02 /* Temperature Register of LM75 */
#define STLM75_REG_TOS 0x03 /* Over-temp Shutdown threshold Register of LM75 */
/*
* STLM75 模式选择
*/
#define STLM75_CONTINUOUS_MODE ((uint8_t)0x00)
#define STLM75_ONE_SHOT_MODE ((uint8_t)0x01)
#define STLM75_COMPARATOR_MODE ((uint8_t)0x00)
#define STLM75_INTERRUPT_MODE ((uint8_t)0x02)
/*
* Alert outside range Limit Temperature 12° <-> 40°c
*/
#define STLM75_TEMPERATURELIMITHIGH 40
#define STLM75_TEMPERATURELIMITlow 12
/* Private Enum --------------------------------------------------------------*/
/* Private Struct ------------------------------------------------------------*/
/* Stlm75温度传感器配置结构体 */
typedef struct
{
uint8_t AlertMode; /* Alert Mode Temperature out of range*/
uint8_t ConversionMode; /* Continuous/One Shot Mode */
uint8_t ConversionResolution; /* Temperature Resolution */
uint8_t ConversionRate; /* Number of measure per second */
uint8_t TemperatureLimitHigh; /* High Temperature Limit Range */
uint8_t TemperatureLimitLow; /* Low Temperature Limit Range */
}STLM75_InitTypeDef;
/* Private variables ---------------------------------------------------------*/
/* Extern variables ---------------------------------------------------------*/
/* Private Functions Prototypes-----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief Writes one byte to the TSENSOR.
* @param DevAddress: Target device address
* @param pBuffer: Pointer to data buffer
* @param WriteAddr: TSENSOR's internal address to write to.
* @param Length: Number of data to write
*/
static uint8_t STLM75_Write( uint8_t* pBuffer, uint8_t WriteAddr, uint16_t Length )
{
return ( I2Cx_WriteBuffer( &hi2c1, STLM75_I2C_ADDRESS, WriteAddr, I2C_MEMADD_SIZE_8BIT, pBuffer, Length ) );
}
/**
* @brief Reads one byte from the TSENSOR.
* @param DevAddress: Target device address
* @param pBuffer : pointer to the buffer that receives the data read from the TSENSOR.
* @param ReadAddr : TSENSOR's internal address to read from.
* @param Length: Number of data to read
*/
static uint8_t STLM75_Read( uint8_t* pBuffer, uint8_t ReadAddr, uint16_t Length )
{
return ( I2Cx_ReadBuffer( &hi2c1, STLM75_I2C_ADDRESS, ReadAddr, I2C_MEMADD_SIZE_8BIT, pBuffer, Length ) );
}
/**
* @brief 检查指定地址的I2C设备通讯是否正常
* @note 只用于Rom设备
* @param DevAddress: 设备地址
* @param Trials: 测试值
* @retval 状态
*/
static uint8_t STLM75_IsDeviceReady( void )
{
return ( I2Cx_IsDeviceReady( &hi2c1, STLM75_I2C_ADDRESS ) );
}
/* Extern Functions ---------------------------------------------------------*/
/**
* @brief STLM75温度传感器初始化
* @param void
* @note void
* @retval 初始化状态
*/
uint8_t STLM75_Init( void )
{
uint8_t confreg = 0;
uint16_t tempreg = 0;
/* 检查设备是否正常 */
if ( STLM75_IsDeviceReady() != HAL_OK ) {
Db_Error("Stlm75 device is error!!!");
return HAL_ERROR;
}
do {
/* Set the Configuration Register */
confreg = (uint8_t)( STLM75_COMPARATOR_MODE | STLM75_CONTINUOUS_MODE );
if ( STLM75_Write( &confreg, STLM75_REG_CONF, 1 ) != HAL_OK )
break;
/* Set the Temperature Registers */
/* Keep the sign bit and shift the temperature value (as given value is integer, the 0.5 digit is not set) */
tempreg = ( ( ( STLM75_TEMPERATURELIMITHIGH & 0x007F) << 8) | ( STLM75_TEMPERATURELIMITHIGH & 0x8000 ) );
if ( STLM75_Write( (uint8_t*)(&tempreg), STLM75_REG_TOS, 2 ) != HAL_OK )
break;
tempreg = ( ( ( STLM75_TEMPERATURELIMITlow & 0x007F) << 8) | ( STLM75_TEMPERATURELIMITlow & 0x8000) );
if ( STLM75_Write( (uint8_t*)(&tempreg), STLM75_REG_THYS, 2 ) != HAL_OK )
break;
return HAL_OK;
} while ( 0 );
return HAL_ERROR;
}
/**
* @brief Read The Temperature Sensor Status
* @param void
* @retval Status
*/
uint8_t STLM75_ReadStatus( void )
{
uint8_t tmp = 0;
/* Read Status register */
STLM75_Read( &tmp, STLM75_REG_CONF, 1 );
/* Return Temperature Sensor Status */
return (uint8_t)(tmp);
}
/**
* @brief Read ID address of STLM75
* @param void
* @retval ID name
*/
uint16_t STLM75_ReadTemp( void )
{
uint16_t tempreg = 0;
uint16_t tmp = 0;
/* Read Temperature registers */
STLM75_Read( (uint8_t*)(&tempreg), STLM75_REG_TEMP, 2 );
tmp = ((tempreg & 0x00FF) << 8) | ((tempreg & 0xFF00) >> 8);
tempreg = (((tmp & 0x7F80) >> 7) | (tmp & 0x8000));
/* Return Temperature value */
return ( tempreg / 2 );
}
/********************************* END OF FILE *********************************/
/**
******************************************************************************
* @file module_sgp30.c
* @author HuZhang
* @version V1.1
* @date Mar 5, 2021
* @brief
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "module_sgp30.h"
#include "i2c.h"
#include "tool.h"
/* Private Typedef -----------------------------------------------------------*/
/* Private Define ------------------------------------------------------------*/
/* CRC8校验参数 */
#define CRC8_POLYNOMIAL 0x31
#define CRC8_INITIAALIZATION 0xFF
/* I2C地址 */
#define SGP30_ADDR 0x58
#define SGP30_ADDR_WRITE ( SGP30_ADDR << 1 )
#define SGP30_ADDR_READ ( ( SGP30_ADDR << 1 ) + 1 )
/* Private Enum --------------------------------------------------------------*/
typedef enum {
/* 初始化空气质量测量 */
INIT_AIR_QUALITY = 0x2003,
/* 开始空气质量测量 */
MEASURE_AIR_QUALITY = 0x2008
}sgp30_cmd;
/* Private Struct ------------------------------------------------------------*/
struct sgp30_data_t {
uint16_t co2;
uint16_t tvoc;
}sgp30Data;
/* Private variables ---------------------------------------------------------*/
/* Extern variables ---------------------------------------------------------*/
/* Private Functions Prototypes-----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief CRC-8校验
* @param message:要校验的数据
* @param initial_value:要校验的数据
* @note void
* @retval void
*/
uint8_t CheckCrc8( const uint8_t* message )
{
uint8_t remainder; /* 余数 */
uint8_t i = 0, j = 0; /* 循环变量 */
/* 初始化 */
remainder = CRC8_INITIAALIZATION;
for ( j = 0; j < 2; j++ ) {
remainder ^= message[ j ];
/* 从最高位开始依次计算 */
for ( i = 0; i < 8; i++ ) {
if ( remainder & 0x80 ) {
remainder = ( remainder << 1 ) ^ CRC8_POLYNOMIAL;
}
else {
remainder = ( remainder << 1 );
}
}
}
/* 返回计算的CRC码 */
return remainder;
}
/**
* @brief 软复位SGP30
* @param void
* @retval 成功返回HAL_OK
*/
static uint8_t sgp30SoftReset( void )
{
uint8_t cmd = 0x06;
return HAL_I2C_Master_Transmit( &hi2c1, SGP30_ADDR_WRITE, &cmd, 1, 0xFFFF );
}
/**
* @brief spg指令发送
* @param cmd:指令
* @note void
* @retval 发送结果
*/
static uint8_t spg30CmdSend ( sgp30_cmd cmd )
{
uint8_t cmdBuffer[2];
cmdBuffer[ 0 ] = cmd >> 8;
cmdBuffer[ 1 ] = cmd;
return HAL_I2C_Master_Transmit( &hi2c1, SGP30_ADDR_WRITE, cmdBuffer, 2, 0xFFFF );
}
/* Extern Functions ---------------------------------------------------------*/
/**
* @brief 初始化空气传感器-spg30
* @param void
* @note void
* @retval void
*/
uint8_t sgp30Init ( void )
{
/* 复位 */
if ( HAL_OK != sgp30SoftReset() )
return HAL_ERROR;
HAL_Delay( 100 );
return spg30CmdSend( INIT_AIR_QUALITY );
}
/**
* @brief sgp30获取空气质量参数
* @param sgp30Data:二氧化碳浓度 甲醛浓度
* @note void
* @retval void
*/
uint8_t spg30GetArgument ( uint16_t *sgp30Data )
{
uint8_t status;
uint8_t recv_buffer[6] = { 0 };
/* 启动测量 */
status = spg30CmdSend( MEASURE_AIR_QUALITY );
if ( status != HAL_OK ) {
Db_Error("sgp30 start fail\r\n");
return HAL_ERROR;
}
HAL_Delay(100);
/* 读取测量数据 */
status = HAL_I2C_Master_Receive( &hi2c1, SGP30_ADDR_READ, (uint8_t*)recv_buffer, 6, 0xFFFF );
if ( status != HAL_OK ) {
Db_Error("I2C Master Receive fail\r\n");
return HAL_ERROR;
}
/* 校验接收的测量数据 */
if ( CheckCrc8( &recv_buffer[ 0 ] ) != recv_buffer[ 2 ]) {
Db_Error("co2 recv data crc check fail\r\n");
return HAL_ERROR;
}
if ( CheckCrc8( &recv_buffer[ 3 ] ) != recv_buffer[ 5 ]) {
Db_Error("tvoc recv data crc check fail\r\n");
return HAL_ERROR;
}
/* 转换测量数据 */
sgp30Data[ 0 ] = recv_buffer[ 0 ] << 8 | recv_buffer[ 1 ];
sgp30Data[ 1 ] = recv_buffer[ 3 ] << 8 | recv_buffer[ 4 ];
return HAL_OK;
}
/********************************* END OF FILE *********************************/