本文共 4536 字,大约阅读时间需要 15 分钟。
为了实现GD32开发板上使用软件模拟I2C读取SHT30温湿度传感器的功能,我们需要编写相应的驱动程序和应用程序。以下是详细的步骤说明:
初始化I2C引脚
soft_i2c.c文件中,初始化I2C总线的时钟和数据线。void IIC_Init(void) { rcu_periph_clock_enable(RCU_GPIOB); // 启用GPIOB时钟 gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6); // PB6(IIC_SCL)设置为推挽输出 gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7); // PB7(IIC_SDA)设置为推挽输出 gpio_bit_set(GPIOB, GPIO_PIN_6); // 确保SCL引脚拉高 gpio_bit_set(GPIOB, GPIO_PIN_7); // 确保SDA引脚拉高} 编写us延时函数
void delay_us(uint32_t nus) { uint32_t ticks; uint32_t told, tnow, tcnt = 0; uint32_t reload = SysTick->LOAD; // 滴答定时器的重装载值 ticks = nus * 120; // 转换为对定时器节拍的计算 told = SysTick->VAL; // 刚进入函数时的计数器值 while (1) { tnow = SysTick->VAL; if (tnow != told) { if (tnow < told) { tcnt += told - tnow; } else { tcnt += reload - tnow + told; } if (tcnt >= ticks) break; told = tnow; } }} 实现I2C通信函数
void IIC_Start(void) { SDA_OUT(); // SDA引脚输出 IIC_SDA(1); // SDA拉高 IIC_SCL(1); // SCL拉高 delay_us(4); // 等待SCL和SDA稳定 IIC_SDA(0); // SDA拉低 delay_us(4); // 等待SCL和SDA稳定 IIC_SCL(0); // SCL拉低} void IIC_Stop(void) { SDA_OUT(); // SDA引脚输出 IIC_SCL(0); // SCL拉低 IIC_SDA(0); // SDA拉低 delay_us(4); // 等待SCL和SDA稳定 IIC_SCL(1); // SCL拉高 delay_us(4); // 等待SCL和SDA稳定 IIC_SDA(1); // SDA拉高 delay_us(4); // 等待SCL和SDA稳定} void IIC_ACK(void) { SDA_OUT(); IIC_SCL(0); delay_us(2); IIC_SDA(0); delay_us(2); IIC_SCL(1); delay_us(2); IIC_SCL(0); delay_us(1);} void IIC_NACK(void) { SDA_OUT(); IIC_SCL(0); delay_us(2); IIC_SDA(1); delay_us(2); IIC_SCL(1); delay_us(2); IIC_SCL(0); delay_us(1);} uint8_t IIC_wait_ACK(void) { uint8_t t = 200; SDA_OUT(); IIC_SDA(1); delay_us(1); IIC_SCL(0); delay_us(1); SDA_IN(); // 释放数据线 delay_us(1); while (READ_SDA) { t--; delay_us(1); if (t == 0) { IIC_SCL(0); return 1; } delay_us(1); } delay_us(1); IIC_SCL(1); delay_us(1); IIC_SCL(0); delay_us(1); return 0;} void IIC_SendByte(uint8_t byte) { uint8_t BitCnt; SDA_OUT(); IIC_SCL(0); for (BitCnt = 0; BitCnt < 8; BitCnt++) { if ((byte & 0x80) != 0) { IIC_SDA(1); } else { IIC_SDA(0); } byte <<= 1; delay_us(2); IIC_SCL(1); delay_us(2); IIC_SCL(0); delay_us(2); }} uint8_t IIC_RcvByte(void) { uint8_t retc = 0; uint8_t BitCnt; SDA_IN(); delay_us(1); for (BitCnt = 0; BitCnt < 8; BitCnt++) { IIC_SCL(0); delay_us(2); IIC_SCL(1); retc = retc << 1; if (READ_SDA) { retc |= 1; } delay_us(1); } IIC_SCL(0); return retc;} 初始化SHT30传感器
uint8_t SHT3x_Init(void) { // 初始化传感器地址和其他配置 return 0;} 读取传感器编号
uint8_t SHT3x_ReadSerialNumber(uint32_t* serialNumber) { // 发送读取传感器编号命令并接收数据 return 0;} 单次读取温湿度数据
uint8_t SHT3x_Get_Humiture_single(double* Tem_val, double* Hum_val) { // 发送测量命令并接收数据 return 0;} 周期读取温湿度数据
uint8_t SHT3x_Get_Humiture_periodic(double* Tem_val, double* Hum_val) { // 设置为周期读取模式并读取数据 return 0;} 数据校验函数
uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value) { // CRC8校验 return 0;} int main(void) { // 初始化系统时钟、UART、I2C等 systick_config(); LED_init(); uart_init(115200); // 其他初始化 printf("Hello world! \r\n"); while (NB_Start()) { // 处理NBIoT模块的通信 } // 初始化SHT30传感器 if (0 == SHT3x_Init()) { printf("SHT3x_Init OK \r\n"); } else { printf("SHT3x_Init ERR \r\n"); } // 设置定时任务读取温湿度数据 while (1) { if (update_flag == 1) { update_flag = 0; // 采集数据并上传到EMQ if (SHT3x_Get_Humiture_periodic(&Tem_val, &Hum_val) == 0) { // 生成数据包并发送 // ... } else { printf("Get_Humiture ERR\r\n"); } } // 处理NBIoT模块的收数据 }} 通过以上步骤,可以实现使用软件模拟I2C读取SHT30温湿度传感器的功能,并将数据上传到云端,完成一个完整的开发流程。
转载地址:http://qtqsz.baihongyu.com/