本帖最后由 hu9jj 于 2020-1-22 09:39 编辑
在EEWORLD论坛获得了SHT31温湿度传感器评测机会,自己画了一块扩展板,将SHT31评测板上的传感器I2C通讯的数据读出来,由于读此数据不属于主从的任一方式,所以我称之为“截取”I2C数据。正好获得了一块STM32L412评测板,于是便用于本次评测。显示部分采用LCD5110,这类显示屏驱动已经很成熟,代码稍作修改便可,所以本贴的重点放在截取SHT31传感器数据上,下面是Nucleo-L412KB评测板:
这是评测板的正面:
这是反面:
下面是主角SHT31评测板:
这个评测板的背面有多个探针触点,用于调试或扩展用:
为此我专门打样了一块扩展板:
在扩展板上焊接好接触**,以便能从评测板上引出相应的信号线,然后用卡簧固定住SHT31评测板:
扩展板的背面布置了连接锂电池的卡簧,这样可以利用锂电池来为SHT31供电,避免换电池的烦恼:
然后通过杜邦线将这些器件连接起来:
从SHT31的数据手册以及通过逻辑分析仪抓取的时序图得知SHT31评测板上的传感器I2C通讯是收到读地址后连续输出6个字节数据,即16位的温度数据+8位的CRC校验和16位的湿度数据和8位的CRC校验,我们只要将这些数据截取出来就行。
这是数据手册上的资料:
这是逻辑分析仪抓取的时序图:
前面说过,我们不能用正常的主从方式进行I2C通讯,而只能抓取其中的数据,不能发出任何回应,否则会影响到SHT31评测板上的正常通讯。为此,只能自己编写了一段截取I2C数据的代码:
/******************************************************
*程 序 名:Read_I2C
*作 用:读取I2C总线上的数据
*输入参数:无
*返回参数:读到的数据(1字节)
******************************************************/
uint8_t Read_I2C(void)
{
uint8_t dat,i;
//开始读一字节数据
for(i=0;i<8;i++){
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 0);
dat <<= 1;
if(HAL_GPIO_ReadPin(SI2C_SDA_GPIO_Port,SI2C_SDA_Pin) == 1) dat |= 0x01;
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 1);
}
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 0);
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 1); //等待ACK
return dat;
}
取出传感器数据后,按照手册给出的公式计算出温度值和湿度值:
为了简化,计算温度时没有考虑0度以下的情况,下面是相应的代码:
/******************************************************
*程 序 名:Intercept_I2C
*作 用:截取I2C总线上的数据并显示到LCD
*输入参数:无
*返回参数:
******************************************************/
void Intercept_I2C(void)
{
uint8_t i,d[7];
uint32_t temp=0,hum=0;
//等待I2C开始信号
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin)==1){
while(HAL_GPIO_ReadPin(SI2C_SDA_GPIO_Port,SI2C_SDA_Pin)==1);
}
for(i = 0; i < 7; i++)
d = Read_I2C();
temp = d[1];
temp <<= 8;
temp |= d[2];
temp = (temp * 17500 / 65535) - 4500;
hum = d[4];
hum <<= 8;
hum |= d[5];
hum = hum * 10000 / 65535;
LCD_write_value(30,4,5,2,0,temp);
LCD_write_value(30,3,5,2,0,hum);
HAL_Delay(2); //回避写命令
}
虽然在调试过程中遇到不少问题,但终于逐个解决,最终能正确显示出温、湿度数据了。
|