使用STM32F103单片机实现HDC2080温湿度传感器读取
·
此程序使用STM32F103C8T6单片机驱动,使用模拟IIC,IO口使用PB8、PB9 。
此程序只读取了HDC2080的温湿度信息,想要读取其它信息,使用DC2080_Write_Byte(Address, Data)函数,将Address更改为想要读取的寄存器地址,Data更改为配置信息即可。
IIC.c和IIC.h是通用代码,也可以使用自己以前编写好的代码。
话不多说,直接上程序。
IIC.c
#include "IIC.h"
static void CPU_Delay_US(uint16_t n)
{
delay_us(n); //延时函数根据主频自己写就行了
}
//IIC初始化
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
RH_SDA_GPIO_CLK_ENABLE(); //使能GPIOH时钟
RH_SCL_GPIO_CLK_ENABLE(); //使能GPIOH时钟
//PH4,5初始化设置
GPIO_Initure.GPIO_Pin=RH_SCL_PIN;
GPIO_Initure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
GPIO_Initure.GPIO_Speed=GPIO_Speed_50MHz; //快速
GPIO_Init(RH_SCL_GPIO_Port,&GPIO_Initure);
GPIO_Initure.GPIO_Pin=RH_SDA_PIN;
GPIO_Initure.GPIO_Mode=GPIO_Mode_Out_OD; //推挽输出
GPIO_Init(RH_SDA_GPIO_Port,&GPIO_Initure);
RH_IIC_SDA(1);
RH_IIC_SCL(1);
}
// 产生I2C起始信号
void IIC_Start(void)
{
RH_SDA_OUT();
RH_IIC_SDA(1);
RH_IIC_SCL(1);
CPU_Delay_US(4);
RH_IIC_SDA(0);
CPU_Delay_US(4);
RH_IIC_SCL(0);
}
// 产生I2C停止信号
void IIC_Stop(void)
{
RH_SDA_OUT();
RH_IIC_SCL(0);
RH_IIC_SDA(0);
CPU_Delay_US(4);
RH_IIC_SCL(1);
CPU_Delay_US(4);
RH_IIC_SDA(1);
}
// 等待应答信号到来
uint8_t IIC_Wait_Ack(void)
{
uint16_t ucErrTime = 0;
RH_SDA_IN();
RH_IIC_SDA(1);
CPU_Delay_US(1);
RH_IIC_SCL(1);
CPU_Delay_US(1);
while(RH_READ_SDA)
{
ucErrTime++;
if (ucErrTime > 250)
{
IIC_Stop();
return 1;
}
}
RH_IIC_SCL(0);
return 0;
}
// 产生ACK应答
void IIC_Ack(void)
{
RH_IIC_SCL(0);
RH_SDA_OUT();
RH_IIC_SDA(0);
CPU_Delay_US(2);
RH_IIC_SCL(1);
CPU_Delay_US(2);
RH_IIC_SCL(0);
}
// 不产生ACK应答
void IIC_NAck(void)
{
RH_IIC_SCL(0);
RH_SDA_OUT();
RH_IIC_SDA(1);
CPU_Delay_US(2);
RH_IIC_SCL(1);
CPU_Delay_US(2);
RH_IIC_SCL(0);
}
// I2C发送一个字节
void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
RH_SDA_OUT();
RH_IIC_SCL(0);
for (t = 0; t < 8; t++)
{
RH_IIC_SDA((txd & 0x80) >> 7);
txd <<= 1;
CPU_Delay_US(2);
RH_IIC_SCL(1);
CPU_Delay_US(2);
RH_IIC_SCL(0);
CPU_Delay_US(2);
}
}
// I2C读取一个字节
uint8_t IIC_Read_Byte(unsigned char ack)
{
unsigned char i, receive = 0;
RH_SDA_IN();
for (i = 0; i < 8; i++)
{
RH_IIC_SCL(0);
CPU_Delay_US(2);
RH_IIC_SCL(1);
receive <<= 1;
if (RH_READ_SDA)
receive++;
CPU_Delay_US(1);
}
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
IIC.h
#ifndef __IIC_H
#define __IIC_H
#include "stm32f10x.h"
#include "SysInit.h"
#include "delay.h"
#include <math.h>
#define RH_SDA_PIN GPIO_Pin_9
#define RH_SDA_GPIO_Port GPIOB
#define RH_SDA_GPIO_CLK_ENABLE() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
#define RH_SCL_PIN GPIO_Pin_8
#define RH_SCL_GPIO_Port GPIOB
#define RH_SCL_GPIO_CLK_ENABLE() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
#define RH_SDA_IN() {RH_SDA_GPIO_Port->CRH&=0xFFFFFF0F;RH_SDA_GPIO_Port->CRH|=8<<4;} //PB9输入模式
#define RH_SDA_OUT() {RH_SDA_GPIO_Port->CRH&=0xFFFFFF0F;RH_SDA_GPIO_Port->CRH|=3<<4;} //PB9输出模式
#define RH_IIC_SCL(x) do{ x ? GPIO_SetBits(RH_SCL_GPIO_Port, RH_SCL_PIN):GPIO_ResetBits(RH_SCL_GPIO_Port, RH_SCL_PIN);}while(0) /* SCL */
#define RH_IIC_SDA(x) do{ x ? GPIO_SetBits(RH_SDA_GPIO_Port, RH_SDA_PIN):GPIO_ResetBits(RH_SDA_GPIO_Port, RH_SDA_PIN);}while(0) /* SDA */
#define RH_READ_SDA GPIO_ReadInputDataBit(RH_SDA_GPIO_Port, RH_SDA_PIN) /* 读取SDA */
//IIC初始化
void IIC_Init(void);
// 产生I2C起始信号
void IIC_Start(void);
// 产生I2C停止信号
void IIC_Stop(void);
// 等待应答信号到来
uint8_t IIC_Wait_Ack(void);
// 产生ACK应答
void IIC_Ack(void);
// 不产生ACK应答
void IIC_NAck(void);
// I2C发送一个字节
void IIC_Send_Byte(uint8_t txd);
// I2C读取一个字节
uint8_t IIC_Read_Byte(unsigned char ack);
#endif
HDC2080_IIC.h
#ifndef __HDC2080_IIC_H
#define __HDC2080_IIC_H
#include "stm32f10x.h"
#include "SysInit.h"
#include "delay.h"
#include <math.h>
#include "IIC.h"
//温湿度结构体
typedef struct
{
float HumiValue;
uint8_t HumiValue_state;
float TempValue;
uint8_t TempValue_state;
}HDC2080RH;
extern HDC2080RH HDC2080RH_SENRH;
void HDC2080_ReadTemperatureHumidity(HDC2080RH *Sen);
#endif
HDC2080_IIC.c
#include "HDC2080_IIC.h"
HDC2080RH HDC2080RH_SENRH;
#define HDC2080_ADDR 0x40
// 向HDC2080写入一个字节数据
void HDC2080_Write_Byte(uint8_t Address, uint8_t Data)
{
IIC_Start();
IIC_Send_Byte((HDC2080_ADDR << 1) | 0);
IIC_Wait_Ack();
IIC_Send_Byte(Address);
IIC_Wait_Ack();
IIC_Send_Byte(Data);
IIC_Wait_Ack();
IIC_Stop();
}
// 向 HDC2080 发送命令
void HDC2080_SendCommand(uint16_t command)
{
IIC_Start();
IIC_Send_Byte((HDC2080_ADDR << 1) | 0x00);
IIC_Wait_Ack();
IIC_Send_Byte(command);
IIC_Wait_Ack();
IIC_Stop();
}
// 从HDC2080读取多个字节数据
void HDC2080_Read_Bytes(uint8_t Address, uint8_t *buf, uint8_t len)
{
IIC_Start();
IIC_Send_Byte((HDC2080_ADDR << 1) | 0);
IIC_Wait_Ack();
IIC_Send_Byte(Address);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte((HDC2080_ADDR << 1) | 1);
IIC_Wait_Ack();
while (len)
{
if (len == 1)
*buf = IIC_Read_Byte(0);
else
*buf = IIC_Read_Byte(1);
buf++;
len--;
}
IIC_Stop();
}
uint8_t HDC2080_Read_B(uint8_t Address)
{
uint8_t Data_buf;
IIC_Start();
IIC_Send_Byte((HDC2080_ADDR << 1) | 0x01);
IIC_Wait_Ack();
IIC_Send_Byte(Address);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte((HDC2080_ADDR << 1) | 1);
IIC_Wait_Ack();
Data_buf = IIC_Read_Byte(0);
IIC_Stop();
return Data_buf;
}
// 读取HDC2080温湿度数据
void HDC2080_ReadTemperatureHumidity(HDC2080RH *Sen)
{
uint8_t data[4];
uint8_t TimeFlag = 0;
Sen->TempValue_state = 0;
HDC2080_Write_Byte(0x0F, 0x01);// 触发测量 地址 0x0F 测量配置寄存器
while((HDC2080_Read_B(0x0F) & 0x01)&& (TimeFlag++<250));// 等待测量完成,测量完成时0x0F寄存器第8位自行清除。
delay_ms(10); // 如果没有此延时,上电首次读取时,湿度值为0。此延时可适当减小。
HDC2080_Read_Bytes(0x00, data, 4);// 读取温度和湿度数据 寄存器地址0x00~0x03分别是:温度低8位、温度高8位、湿度低8位、湿度高8位
// 解析温度数据
uint16_t tempRaw = (data[1] << 8) | data[0];
Sen->TempValue = ((float)tempRaw / 65536.0) * 165.0 - 40.5;
if(Sen->TempValue < 0) Sen->TempValue_state = 1;
// 解析湿度数据
uint16_t humiRaw = (data[3] << 8) | data[2];
Sen->HumiValue = ((float)humiRaw / 65536.0) * 100.0;
}
在主程序中初始化IO口后,直接调用函数HDC2080_ReadTemperatureHumidity(&HDC2080RH_SENRH);
将HDC2080RH_SENRH.TempValue和HDC2080RH_SENRH.HumiValue进行输出即可。
更多推荐


所有评论(0)