此程序使用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进行输出即可。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐