STM32F1 & SHT3x温湿度模块
提示:以下程序是基于STM32F103和SHT3x系列硬件
一、STM32CubeMX工程配置
说明:本例程采用模拟IIC,所以需要把相应IO配置为推完输出,默认为高电平
二、程序&说明
1.模拟IIC程序
myiic.c
#include "myiic.h"
#include "delay.h"
void IIC_Start(void)
{
SDA_OUT();
IIC_SDA(1);
IIC_SCL(1);
delay_us(4);
IIC_SDA(0);
delay_us(4);
IIC_SCL(0);
}
void IIC_Stop(void)
{
SDA_OUT();
IIC_SCL(0);
IIC_SDA(0);
delay_us(4);
IIC_SCL(1);
IIC_SDA(1);
delay_us(4);
}
uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
SDA_IN();
IIC_SDA(1);delay_us(1);
IIC_SCL(1);delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
return 1;
}
}
IIC_SCL(0);
return 0;
}
void IIC_Ack(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(0);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}
void IIC_NAck(void)
{
IIC_SCL(0);
SDA_OUT();
IIC_SDA(1);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}
void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
SDA_OUT();
IIC_SCL(0);
for(t=0;t<8;t++)
{
IIC_SDA((txd&0x80)>>7);
txd<<=1;
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
delay_us(2);
}
}
uint8_t IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
SDA_IN();
for(i=0;i<8;i++ )
{
IIC_SCL(0);
delay_us(2);
IIC_SCL(1);
receive<<=1;
if(READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
myiic.h
#ifndef _MYIIC_H
#define _MYIIC_H
#include "delay.h"
#include "main.h"
#define SDA_IN() {GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=(uint32_t)8<<0;}
#define SDA_OUT() {GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=(uint32_t)3<<0;}
#define IIC_SCL(n) (n ? HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET))
#define IIC_SDA(n) (n ? HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET))
#define READ_SDA HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8)
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Byte(uint8_t txd);
uint8_t IIC_Read_Byte(unsigned char ack);
uint8_t IIC_Wait_Ack(void);
void IIC_Ack(void);
void IIC_NAck(void);
void IIC_Write_One_Byte(uint8_t daddr,uint8_t addr,uint8_t data);
uint8_t IIC_Read_One_Byte(uint8_t daddr,uint8_t addr);
#endif
以上底层是基于STM32F103,若要使用在STM32其他系列上请自行移植 提示:需要修改delay.h 和delay.c 文件,注意时序,并且更改myiic.h 中的引脚配置,如下图(注::F4和F1的IO方向设置寄存器不一样,请自行查看数据手册进行修改)
2,SHT3x底层
sht3x.c
#include "sht3x.h"
#include "myiic.h"
_TW data_process;
static void SHT3x_WriteCommand(uint16_t COMMAND);
void SHT3x_Init(void)
{
IIC_Start();
IIC_Send_Byte(SHTx_Device_ADDR << 1 | Write_DATA);
SHT3x_WriteCommand(PERI_HIGH_1_CMD);
IIC_Stop();
}
static void SHT3x_WriteCommand(uint16_t COMMAND)
{
IIC_Wait_Ack();
IIC_Send_Byte(COMMAND >> 8);
IIC_Wait_Ack();
IIC_Send_Byte(COMMAND & 0xFF);
IIC_Wait_Ack();
}
void SHT3x_READ_TEMP_Humi(uint16_t *dat)
{
IIC_Start();
IIC_Send_Byte(SHTx_Device_ADDR << 1 | Write_DATA);
SHT3x_WriteCommand(READOUT_FOR_PERIODIC_MODE);
IIC_Start();
IIC_Send_Byte(SHTx_Device_ADDR << 1 | Read_DATA);
IIC_Wait_Ack();
dat[0] = IIC_Read_Byte(1);
dat[1] = IIC_Read_Byte(1);
dat[2] = IIC_Read_Byte(1);
dat[3] = IIC_Read_Byte(1);
dat[4] = IIC_Read_Byte(1);
dat[5] = IIC_Read_Byte(0);
IIC_Stop();
}
int CRC8_Compute(uint8_t *check_data, uint8_t num_of_data)
{
uint8_t bit;
uint8_t crc = 0xFF;
uint8_t byteCtr;
for(byteCtr = 0; byteCtr < num_of_data; byteCtr++)
{
crc ^= (check_data[byteCtr]);
for(bit = 8; bit > 0; --bit)
{
if(crc & 0x80)
crc = (crc << 1) ^ 0x31;
else
crc = (crc << 1);
}
}
return crc;
}
int SHT3x_CRC8_Check(uint8_t *p,uint8_t num_of_data,uint8_t CrcData)
{
uint8_t crc;
crc = CRC8_Compute(p, num_of_data);
if(crc != CrcData)
{
return 1;
}
return 0;
}
uint8_t SHT3x_Data_Process(void)
{
uint8_t temporary[3];
uint16_t data;
uint8_t crc_result;
SHT3x_READ_TEMP_Humi(data_process.sht30_data_buffer);
temporary[0]=data_process.sht30_data_buffer[0];
temporary[1]=data_process.sht30_data_buffer[1];
temporary[2]=data_process.sht30_data_buffer[2];
crc_result=SHT3x_CRC8_Check(temporary,2,temporary[2]);
if(crc_result==0)
{
data=((uint16_t)temporary[0] << 8) | temporary[1];
data_process.SHT30_temperature = ((175.0f * ((float)data) / 65535.0f - 45.0f) *1.0f);
}
else
{
return 1;
}
temporary[0]=data_process.sht30_data_buffer[3];
temporary[1]=data_process.sht30_data_buffer[4];
temporary[2]=data_process.sht30_data_buffer[5];
crc_result=SHT3x_CRC8_Check(temporary,2,temporary[2]);
if(crc_result==0)
{
data=((uint16_t)temporary[0] << 8) | temporary[1];
data_process.SHT30_humidity = ((100.0f * (float)data / 65535.0f) *1.0f);
return 0;
}
else
{
return 2;
}
}
sht3x.h
#ifndef __SHT3x_H
#define __SHT3x_H
#include "stm32f1xx_hal.h"
#include "myiic.h"
#include "usart.h"
typedef enum{
SHTx_Device_ADDR = 0x44,
Write_DATA = 0x00,
Read_DATA = 0x01,
SOFT_RESET_CMD = 0x30A2,
CLOCK_HIGH_ENABLED_CMD = 0x2C06,
CLOCK_MEDIUM_ENABLED_CMD = 0x2C0D,
CLOCK_LOW_ENABLED_CMD = 0x2C10,
CLOCK_HIGH_DISABLED_CMD = 0x2400,
CLOCK_MEDIUM_DISABLED_CMD = 0x240B,
CLOCK_LOW_DISABLED_CMD = 0x2416,
PERI_HIGH_0_5_CMD = 0x2032,
PERI_MEDIUM_0_5_CMD = 0x2024,
PERI_LOW_0_5_CMD = 0x202F,
PERI_HIGH_1_CMD = 0x2130,
PERI_MEDIUM_1_CMD = 0x2126,
PERI_LOW_1_CMD = 0x212D,
PERI_HIGH_2_CMD = 0x2236,
PERI_MEDIUM_2_CMD = 0x2220,
PERI_LOW_2_CMD = 0x222B,
PERI_HIGH_4_CMD = 0x2334,
PERI_MEDIUM_4_CMD = 0x2322,
PERI_LOW_4_CMD = 0x2329,
PERI_HIGH_10_CMD = 0x2737,
PERI_MEDIUM_10_CMD = 0x2721,
PERI_LOW_10_CMD = 0x272A,
HEATER_ENABLED_CMD = 0x306D,
HEATER_DISABLED_CMD = 0x3066,
READ_STATUS_CMD = 0xF32D,
CLEAR_STATUS_CMD = 0x3041,
READOUT_FOR_PERIODIC_MODE = 0xE000,
}SHT30_CMD;
typedef struct
{
unsigned short int sht30_data_buffer[6];
float SHT30_temperature;
float SHT30_humidity;
}_TW;
extern _TW data_process;
void SHT3x_Init(void);
void SHT3x_READ_TEMP_Humi(uint16_t *dat);
uint8_t SHT3x_Data_Process(void);
int CRC8_Compute(uint8_t *check_data, uint8_t num_of_data);
int SHT3x_CRC8_Check(uint8_t *p,uint8_t num_of_data,uint8_t CrcData);
#endif
3,使用说明
- 调用
SHT3x_Init 初始化函数 - 周期调用
SHT3x_Data_Process 数据测量函数 - 所需数据在结构体
data_process 中
|