收到板子有2周了,恰逢上海迎台风,在家用G401调下SHT30温湿度传感器。
前期准备:G401开发板,SHT30传感器
硬件连接:通过硬件IIC1接口,板子上对应的是PB6(I2c1_scl),PB7(I2c_sda)脚。
实物连接如图:
软件部分:国民官方给我们提供很多外设的例子,我们可以参考
将G401做i2c主设备,sht30做slave,那么需要确定sht30的地址,从手册里可以看到,
地址是0x44,但实际代码里使用时,需要结合读写位,所以定义实际地址为
硬件使用iic的流程为,先初始化gpio作为iic的功能。
GPIO_Structure_Initialize(&i2c1_gpio);
/*PB6 -- SCL; PB7 -- SDA*/
i2c1_gpio.Pin = I2Cx_SCL_PIN | I2Cx_SDA_PIN;
i2c1_gpio.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
i2c1_gpio.GPIO_Mode = GPIO_MODE_AF_OD;
i2c1_gpio.GPIO_Alternate = GPIO_AF_I2C;
i2c1_gpio.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(GPIOx, &i2c1_gpio);
然后初始化i2c master控制器的参数,主要是总线模式,地址,寻址模式,通信速率,最后打开i2c的使能。
I2C_Initializes_Structure(&i2c1_master);
i2c1_master.BusMode = I2C_BUSMODE_I2C;
i2c1_master.DutyCycle = I2C_SMDUTYCYCLE_1;
i2c1_master.OwnAddr1 = 0x44; // sht30 addr
i2c1_master.AckEnable = I2C_ACKEN;
i2c1_master.AddrMode = I2C_ADDR_MODE_7BIT;
i2c1_master.ClkSpeed = CLK_SPEED_400K; /* 100k */
I2C_Initializes(I2Cx, &i2c1_master);
I2C_ON(I2Cx);
此时我们可以对外设SHT30进行读写,这个流程是先复位SHT30,命令为
uint8_t SHT30_Reset(void)
{
uint8_t res = 0;
res = SHT30_Send_Cmd(SOFT_RESET_CMD);
//SysTick_Delay_Ms(20);
return res;
}
其中命令封装到了枚举类型里,
typedef enum{
SOFT_RESET_CMD = 0x30A2,
HIGH_ENABLE_CMD = 0x2C06,
HIGH_1_CMD = 0x2130,
READ_FOR_PERIODIC_MODE = 0xE000,
}SHT30_CMD;
然后我们可以给SHT30发送周期性的读写命令,每秒读一次,0x2130,其依据是
体现在程序里:
uint8_t SHT30_Send_Cmd(uint16_t cmd)
{
uint8_t cmd_buffer[2];
cmd_buffer[0] = cmd >> 8;
cmd_buffer[1] = cmd;
return i2c_master_send(cmd_buffer, 2);
}
其中i2c_master_send里需要更改i2c slave的地址,
I2C_7bit_Addr_Send(I2C1, SHT30_ADDRESS_WRITE, I2C_DIRECTION_SEND);
后续我们就可以周期性读取SHT30数据。
while (1)
{
SysTick_Delay_Ms(1000);
if((res = SHT30_Read_Dat(recv_dat)) == 0){
if(SHT30_Dat_To_Float(recv_dat,&temp,&hum) == 0)
{
log_info("N32G401 hard iic master temperature = %f, humidity = %f\r\n", temp, hum);
}else{
log_info("crc check fail.\r\n");
}
}else{
log_info("read SHT30 data error res = %d\r\n",res);
}
}
需要注意crc校验
uint8_t SHT30_Dat_To_Float(uint8_t* const dat, float* temperature, float* humidity)
{
uint16_t recv_temperature = 0;
uint16_t recv_humidity = 0;
if(CheckCrc8(dat, 0xFF) != dat[2] || CheckCrc8(&dat[3], 0xFF) != dat[5])
return 1;
recv_temperature = ((uint16_t)dat[0]<<8)|dat[1];
*temperature = -45 + 175*((float)recv_temperature/65535);
recv_humidity = ((uint16_t)dat[3]<<8)|dat[4];
*humidity = 100 * ((float)recv_humidity / 65535);
return 0;
}
实际串口输出效果如图: