本文使用CH592X软件模拟iic驱动SHT21,
1.i2c.c
#include "i2c.h" #include "CH59x_common.h" #define IIC_SCL_PIN GPIO_Pin_15 // PB15-SCL #define IIC_SDA_PIN GPIO_Pin_14 // PB14-SDA #define IIC_SCL_H() R32_PB_DIR &= ~IIC_SCL_PIN #define IIC_SCL_L() R32_PB_DIR |= IIC_SCL_PIN #define IIC_SDA_H() R32_PB_DIR &= ~IIC_SDA_PIN #define IIC_SDA_L() R32_PB_DIR |= IIC_SDA_PIN #define SCL_read() (R32_PB_PIN & IIC_SCL_PIN) #define SDA_read() (R32_PB_PIN & IIC_SDA_PIN) void IIC_Init() { GPIOB_ModeCfg(IIC_SCL_PIN, GPIO_ModeIN_PU); // 初始化为上拉输入 GPIOB_ModeCfg(IIC_SDA_PIN, GPIO_ModeIN_PU); // 初始化为上拉输入 GPIOB_ResetBits(IIC_SCL_PIN | IIC_SDA_PIN); // 配置默认输出低电平,保证在切换IO引脚为输出方向时能够及时输出低电平 IIC_SCL_H(); // SCL拉高 IIC_SDA_H(); // SDA拉高 } void IIC_Delay() { mDelayuS(10); // 可根据实际情况调整延时时间 } void IIC_START() { IIC_SDA_H(); IIC_SCL_H(); IIC_Delay(); IIC_SDA_L(); IIC_Delay(); IIC_SCL_L(); } void IIC_STOP() { IIC_SDA_L(); IIC_SCL_H(); IIC_Delay(); IIC_SDA_H(); IIC_Delay(); } int IIC_WaitAck() { IIC_SCL_L(); IIC_Delay(); IIC_SDA_H(); IIC_Delay(); IIC_SCL_H(); IIC_Delay(); if (SDA_read()) { IIC_SCL_L(); return 0; } IIC_SCL_L(); return 1; } void IIC_SendByte(uint8_t SendByte) { uint8_t i = 8; while (i--) { IIC_SCL_L(); IIC_Delay(); if (SendByte & 0x80) IIC_SDA_H(); else IIC_SDA_L(); SendByte <<= 1; IIC_Delay(); IIC_SCL_H(); IIC_Delay(); } IIC_SCL_L(); } uint8_t IIC_ReadByte() { uint8_t i = 8; uint8_t ReceiveByte = 0; IIC_SDA_H(); while (i--) { ReceiveByte <<= 1; IIC_SCL_L(); IIC_Delay(); IIC_SCL_H(); IIC_Delay(); if (SDA_read()) ReceiveByte |= 0x01; } IIC_SCL_L(); return ReceiveByte; }
2.i2c.h
#ifndef I2C_H #define I2C_H #include "CH59x_common.h" extern void IIC_Init(); extern void IIC_Delay(); extern void IIC_START(); extern void IIC_STOP(); extern int IIC_WaitAck(); extern void IIC_SendByte(uint8_t SendByte); extern uint8_t IIC_ReadByte(); #endif
3.sht21.c
#include "sht21.h" void sht21_reset() { IIC_START(); IIC_SendByte(SHT21_ADDR << 1); IIC_WaitAck(); IIC_SendByte(SOFT_RESET); IIC_WaitAck(); IIC_STOP(); } void sht21_write_command(uint8_t command) { IIC_START(); IIC_SendByte(SHT21_ADDR << 1); IIC_WaitAck(); IIC_SendByte(command); IIC_WaitAck(); IIC_STOP(); } uint16_t sht21_read_data() { uint16_t data = 0; IIC_START(); IIC_SendByte((SHT21_ADDR << 1) | 0x01); IIC_WaitAck(); data = IIC_ReadByte(); data <<= 8; data |= IIC_ReadByte(); IIC_STOP(); return data; } float sht21_get_temperature() { sht21_write_command(TRIGGER_TEMP_MEASUREMENT_HOLD); mDelaymS(100); // 等待测量完成,根据数据手册,温度测量最长需85ms uint16_t raw_temp = sht21_read_data(); float temperature = -46.85 + 175.72 * raw_temp / 65536.0; return temperature; } float sht21_get_humidity() { sht21_write_command(TRIGGER_HUMIDITY_MEASUREMENT_HOLD); mDelaymS(100); // 等待测量完成,根据数据手册,湿度测量最长需22ms uint16_t raw_humidity = sht21_read_data(); float humidity = -6.0 + 125.0 * raw_humidity / 65536.0; return humidity; }
4.sht21.h
#ifndef SHT21_H #define SHT21_H #include "i2c.h" #include "CH59x_common.h" #define SHT21_ADDR 0x40 // SHT21的I2C地址 // SHT21的命令 #define TRIGGER_TEMP_MEASUREMENT_HOLD 0xE3 #define TRIGGER_HUMIDITY_MEASUREMENT_HOLD 0xE5 #define WRITE_USER_REG 0xE6 #define READ_USER_REG 0xE7 #define SOFT_RESET 0xFE extern void sht21_reset(); extern void sht21_write_command(uint8_t command); extern uint16_t sht21_read_data(); extern float sht21_get_temperature(); extern float sht21_get_humidity(); #endif
5.main.c
IIC_Init(); sht21_reset(); float temperature = sht21_get_temperature(); float humidity = sht21_get_humidity(); PRINT("Temperature: %.2f C, Humidity: %.2f %%RH\n", temperature, humidity);
串口打印输出:

浙公网安备 33010602011771号