IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32F1 & SHT3x温湿度模块 -> 正文阅读

[嵌入式]STM32F1 & SHT3x温湿度模块

STM32F1 & SHT3x温湿度模块

提示:以下程序是基于STM32F103和SHT3x系列硬件



一、STM32CubeMX工程配置

说明:本例程采用模拟IIC,所以需要把相应IO配置为推完输出,默认为高电平
在这里插入图片描述

二、程序&说明

1.模拟IIC程序

myiic.c

#include "myiic.h"
#include "delay.h"

//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA(1);	  	  
	IIC_SCL(1);
	delay_us(4);
 	IIC_SDA(0);//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL(0);//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL(0);
	IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL(1); 
	IIC_SDA(1);//发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
uint8_t IIC_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	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);//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL(0);
	SDA_OUT();
	IIC_SDA(0);
	delay_us(2);
	IIC_SCL(1);
	delay_us(2);
	IIC_SCL(0);
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL(0);
	SDA_OUT();
	IIC_SDA(1);
	delay_us(2);
	IIC_SCL(1);
	delay_us(2);
	IIC_SCL(0);
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//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);   //对TEA5767这三个延时都是必须的
		IIC_SCL(1);
		delay_us(2); 
		IIC_SCL(0);	
		delay_us(2);
	}	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
uint8_t IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    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();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

myiic.h

#ifndef _MYIIC_H
#define _MYIIC_H

#include "delay.h"
#include "main.h"

//IO方向设置
#define SDA_IN()  {GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=(uint32_t)8<<0;}	//PB7输入模式
#define SDA_OUT() {GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=(uint32_t)3<<0;} 	//PB7输出模式

//IO操作
#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)) //SCL
#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)) //SDA
#define READ_SDA    HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8)					//输入SDA

//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口(无需调用)				 
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(uint8_t txd);			//IIC发送一个字节
uint8_t IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
uint8_t IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号

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.hdelay.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);	//SHT30命令写入

void SHT3x_Init(void)		//SHT30初始化
{
	IIC_Start();
	IIC_Send_Byte(SHTx_Device_ADDR << 1 | Write_DATA);	//写入地址和写命令
	SHT3x_WriteCommand(PERI_HIGH_1_CMD);								//设置为周期读取频率为1hz
	IIC_Stop();
}

static void SHT3x_WriteCommand(uint16_t COMMAND)	//SHT30命令写入
{
	IIC_Wait_Ack();
	IIC_Send_Byte(COMMAND >> 8);		//传输高8位
	IIC_Wait_Ack();
	IIC_Send_Byte(COMMAND & 0xFF);	//传输低8位
	IIC_Wait_Ack();
}

void SHT3x_READ_TEMP_Humi(uint16_t *dat)	//SHT3x读取数据
{
	IIC_Start();
	IIC_Send_Byte(SHTx_Device_ADDR << 1 | Write_DATA); //写入地址和写命令
	SHT3x_WriteCommand(READOUT_FOR_PERIODIC_MODE);		 //读取周期测量寄存器中的值
	
	//下面是开始读取数据,其中的指针dat存放结果,前三个存放温度值,后三个是湿度值,在前三个温度值里面,
	//dat[0]是温度的高八位,dat[1]是低八位,dat[2]是CRC校验
   
	IIC_Start();
	IIC_Send_Byte(SHTx_Device_ADDR << 1 | Read_DATA);	//写入地址和读命令
	IIC_Wait_Ack();

	//前五次读取都要发送ack信号,最后一次就不用发了。
	dat[0] = IIC_Read_Byte(1);	//温度的高八位
	dat[1] = IIC_Read_Byte(1);	//温度的低八位
	dat[2] = IIC_Read_Byte(1);	//温度的CRC位
	
	dat[3] = IIC_Read_Byte(1);	//湿度的高八位
	dat[4] = IIC_Read_Byte(1);	//湿度的低八位
	dat[5] = IIC_Read_Byte(0);	//湿度的CRC位
	IIC_Stop();
}

/*	
	CRC校验函数(是确保通信过程中数据传输没问题的,没有缺少任何数据,
	当我们接收到数据后,按照一定的方式计算一个crc校验码,
	经过和提供的crc校验码进行比较,如果两个码一样,那么数据就是没问题的。)
*/
int CRC8_Compute(uint8_t *check_data, uint8_t num_of_data)
{
	uint8_t bit;        // bit mask
	uint8_t crc = 0xFF; // calculated checksum
	uint8_t byteCtr;    // byte counter

	// calculates 8-Bit checksum with given polynomial
	for(byteCtr = 0; byteCtr < num_of_data; byteCtr++)
	{
		crc ^= (check_data[byteCtr]);
		//crc校验,最高位是1就^0x31
		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);// calculates 8-Bit checksum
 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校验
  crc_result=SHT3x_CRC8_Check(temporary,2,temporary[2]);
  //crc校验要是不成功就返回1,同时不会更新温度值
  if(crc_result==0)
  {
		//把2个8位数据拼接为一个16位的数据
		data=((uint16_t)temporary[0] << 8) | temporary[1];
		//温度转换,将16位温度数据转化为10进制的温度数据,这里保留了一位小数,data_process.SHT30_temperature这是一个全局变量
		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校验
  crc_result=SHT3x_CRC8_Check(temporary,2,temporary[2]);
  if(crc_result==0)
  {
		//参考上面温度的代码
		data=((uint16_t)temporary[0] << 8) | temporary[1];
		//湿度转换,将16位温度数据转化为10进制的温度数据,这里保留了一位小数,data_process.SHT30_temperature这是一个全局变量
		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,		//1s测量一次(1Hz)
	
	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,	//1s测量10次(10Hz)
	
	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);										//SHT30初始化
void SHT3x_READ_TEMP_Humi(uint16_t *dat);	//写一个命令给SHT30,并读取数据
uint8_t SHT3x_Data_Process(void);					//温湿度测量函数

// CRC校验函数
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
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-17 12:06:30  更:2021-07-17 12:06:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:22:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码