stm32cubemx硬件IIC驱动SGP40Voc传感器

目录

1.cubemx的IIC配置

2.SGP40的软件编写


1.cubemx的IIC配置

2.SGP40的软件编写

#ifndef  __SGP40_H__
#define  __SGP40_H__

#include "main.h"

#define SGP40_SEIF_SUCESS         0xD4   //all tests passed successfully
#define SGP40_SEIF_FAIL           0x4B   //one or more tests have failed

typedef enum{
		sgp40_measure_raw_signal = 0x260F,
		sgp40_execute_self_test = 0x280E,   //传感器自检
		sgp4x_turn_heater_off = 0x3615,    //关闭加热板并进入空闲模式
		sgp4x_get_serial_number = 0x3682,   //获得该传感器的序列号
		sgp40_soft_reset = 0x0006, //复位传感器
}SGP40Commond;



uint8_t SGP40_MeasureRaw(float humidity,float temperature);
uint8_t SGP40_MeasureVocIndex(float humidity,float temperature,float * Voc,uint16_t *Voc_AD);
void SGP40_reset(void);
uint8_t SGP40_Read_Dat(uint8_t* dat,uint8_t Size);
uint8_t SGP40_Init(void);


#endif

#include "SGP40.h"


#include "i2c.h"

#include <rtthread.h>
#include <rtdbg.h>

#define SGP40_ADDR_WRITE    0x59<<1         //10110010
#define SGP40_ADDR_READ     (0x59<<1)+1     //10110011

#define SGP40_CRC8_POLYNOMIAL 0x31
static uint8_t SGP40_CheckCrc8(uint8_t* const message, uint8_t initial_value)
{
    uint8_t  remainder;     //余数
    uint8_t  i = 0, j = 0;  //循环变量

    /* 初始化 */
    remainder = initial_value;

    for(j = 0; j < 2;j++)
    {
        remainder ^= message[j];

        /* 从最高位开始依次计算  */
        for (i = 0; i < 8; i++)
        {
            if (remainder & 0x80)
            {
                remainder = (remainder << 1)^SGP40_CRC8_POLYNOMIAL;
            }
            else
            {
                remainder = (remainder << 1);
            }
        }
    }

    /* 返回计算的CRC码 */
    return remainder;
}
/**
 * @brief   将SGP40接收的3字节数据进行CRC校验
 * @param   dat  —— 存储接收数据的地址(3个字节数组)
 * @retval  校验成功  —— 返回0
 *          校验失败  —— 返回1
*/
uint8_t SGP40_Dat_CRC(uint8_t* const dat)
{
    if(SGP40_CheckCrc8(dat, 0xFF) != dat[2])
        return 1;
	else
		return 0;
}

/**
 * @brief   向SGP40发送一条指令
 * @param   cmd —— SGP40指令(SGP40Commond中枚举定义),
 * @retval  成功返回HAL_OK
*/
static uint8_t  SGP40_Send_Cmd(SGP40Commond cmd)
{
    uint8_t cmd_buffer[2];
    cmd_buffer[0] = cmd >> 8;
    cmd_buffer[1] = cmd;
    return HAL_I2C_Master_Transmit(&hi2c1, SGP40_ADDR_WRITE, (uint8_t*) cmd_buffer, 2, 0x00FF);
}
/**
 * @brief   向SGP40发送测量指令
 * @param   cmd —— SGP40指令(SGP40Commond中枚举定义),
 * @retval  成功返回HAL_OK
*/
uint8_t SGP40_MeasureRaw(float humidity,float temperature)
{
    uint8_t cmd_buffer[8];
	uint16_t rhticks = 0;
	uint16_t tempticks = 0;
    cmd_buffer[0] = 0x26;
    cmd_buffer[1] = 0x0F;
	rhticks = (uint16_t)((humidity * 65535) / 100 + 0.5f);
	cmd_buffer[2] = rhticks >> 8;
	cmd_buffer[3] = rhticks & 0xFF;
	cmd_buffer[4] = SGP40_CheckCrc8(cmd_buffer + 2, 0xFF);
	tempticks = (uint16_t)(((temperature + 45) * 65535) / 175);
	cmd_buffer[5] = tempticks >> 8;
	cmd_buffer[6] = tempticks & 0xFF;
	cmd_buffer[7] = SGP40_CheckCrc8(cmd_buffer + 5, 0xFF);
    return HAL_I2C_Master_Transmit(&hi2c1, SGP40_ADDR_WRITE, (uint8_t*) cmd_buffer, 8, 0x00FF);
}
/**
 * @brief   向SGP4获得数据
 * @param   
 * @retval  成功返回HAL_OK
*/
uint8_t SGP40_MeasureVocIndex(float humidity,float temperature,float * Voc,uint16_t *Voc_AD)
{
    uint8_t voc[3] = {0};
	if(SGP40_MeasureRaw(temperature, humidity)==0)
	{
			rt_thread_mdelay(30);
			if(SGP40_Read_Dat(voc,3) == 0)
			{
					if(SGP40_CheckCrc8(voc,0xff) == voc[2])  //校验正确
					{
							*Voc_AD = voc[0]<<8|voc[1];
							* Voc = (*Voc_AD)*3.3/65535;
					}
					else
						return 3;
			}
			else
			{
					return 2;
			}
	}
	else
	{
			return 1;
	}
	return 0;
}
/**
 * @brief   自检SGP40
 * @param   none
 * @retval  成功返回 0
*/
uint8_t SGP40_SEIF(void)
{
		uint8_t Temp[3] = {0};
		SGP40_Send_Cmd(sgp40_execute_self_test);   //自检   
		rt_thread_mdelay(320);        //数据手册定义
		if(SGP40_Read_Dat(Temp, 3)==HAL_OK)
		{
					if(SGP40_Dat_CRC(Temp)!=0) return 1;
					else
					{
							if(Temp[0]!=SGP40_SEIF_SUCESS)
							{
									rt_kprintf("SGP40_SEIF_Fali\r\n");
									return 1;
							}
							else
								return 0;
					}
		}
		else
		{
				rt_kprintf("SGP40_READ_DAT_FAIL\r\n");
				return 1;
		}
}
/**
 * @brief   复位SGP40
 * @param   none
 * @retval  none
*/
void SGP40_reset(void)
{
    SGP40_Send_Cmd(sgp40_soft_reset);
    rt_thread_mdelay(20);
}

/**
 * @brief   从SGP40读取一次数据
 * @param   dat —— 存储读取数据的地址(6个字节数组)
 * @retval  成功 —— 返回HAL_OK
*/
uint8_t SGP40_Read_Dat(uint8_t* dat,uint8_t Size)
{
    return HAL_I2C_Master_Receive(&hi2c1, SGP40_ADDR_READ, dat, Size, 0xFFFF);
}
/**
 * @brief   初始化SGP40
 * @param   none
 * @retval  成功返回HAL_OK
 * @note    周期测量模式
*/
uint8_t SGP40_Init(void)
{
		if(SGP40_SEIF()==0)
		{
				return 0;
		}
		else
		{
				rt_kprintf("SGP40_SEIF_Fali\r\n");
				return HAL_ERROR;
		}
}


欢迎指正

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值