SHT3x 简介
sht3x 是一个温度湿度类型的sensor,该系列有sht30、sht31、sht35 误差精度等是各不相同的,当然价格也是不同的。 可以在网上搜索Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital了解更更多。
IIC读写
ADSP 中的iic读写默认是寄存器地址是八位,sht3x从手册上看,没有寄存器地址这个概念。 取而代之是command,分为高八位和低八位,这个可以理解为16位寄存器地址。看下图可以, 这个是设置sensor周期模式的设置方式,首先写iic地址得到ack后,再写cmd MSB得到ack后,最后写cmd LSB得到ack,没有以后了。 按照传统的iic读写。后面应该读写这个地址的数据。这个比较特殊,本人还是第一次见到。
下图是读取sensor的温湿度数据(周期性,提前设置的读取频率想关),严格按照时序要求,可以获取温湿度数据以及crc校验,来验证读写的数据的正确性。
crc验证,文档上和网上都有,这里不再赘述。
MCU 读写
一开始没有sht3x msm9809w平台下(ADSP)的驱动,找个一块stm32板子飞线先调试通,再使用hts221驱动去改,代码如下:
void sht3x_init()
{
u8 err= 0;
delay_ms(250);
//0x2130 表示周期模式 周期1ms
IIC_Start();
IIC_Send_Byte(0x88);
err = IIC_Wait_Ack();
if(err)
printf("\r\nack err 1");
IIC_Send_Byte(0x21);
err = IIC_Wait_Ack();
if(err)
printf("\r\nack err 2");
IIC_Send_Byte(0x30);
err = IIC_Wait_Ack();
if(err)
printf("\r\nack err 3");
IIC_Stop();
delay_ms(150);
printf("\r\n sht3x_init");
}
void sht30_read_temp_humi(u8 *p)
{
u8 err;
u8 i;
IIC_Start();
IIC_Send_Byte(0x88);
err = IIC_Wait_Ack();
if(err)
printf("\r\nack err 1");
IIC_Send_Byte(0xe0);
err = IIC_Wait_Ack();
if(err)
printf("\r\nack err 2");
IIC_Send_Byte(0x00);
err = IIC_Wait_Ack();
if(err)
printf("\r\nack err 3");
IIC_Start();
IIC_Send_Byte(0x89);
err = IIC_Wait_Ack();
if(err)
printf("\r\nack err 4");
p[0] = IIC_Read_Byte(1);
p[1] = IIC_Read_Byte(1);
p[2] = IIC_Read_Byte(1);
p[3] = IIC_Read_Byte(1);
p[4] = IIC_Read_Byte(1);
p[5] = IIC_Read_Byte(0);
IIC_Stop();
//打印读取读取数据
printf("\r\nread data= ");
for(i=0; i<6; i++){
printf("-0x%02x",p[i]);
}
}
int sht30_data(u8 *p)
{
u16 data;
u8 crc_result;
float temp,humi;
sht30_read_temp_humi(p);
//crc校验
crc_result=sht30_crc8_check(p,2,p[2]);//crc 没有贴出来
if(crc_result==0)
{
data=((u16)p[0] << 8) | p[1];
temp = ((175.0 * ((float)data) / 65535.0 - 45.0) );
printf("\r\ntemp=%f",temp);
}else {
printf("\r\n crc temp err");
return 1;
}
//crc校验
crc_result=sht30_crc8_check(p+3,2,p[5]);
if(crc_result==0){
//参考上面温度的代码
data=((u16)p[3] << 8) | p[4];
humi = ((100.0 * (float)data / 65535.0) );
printf("\r\nhumi=%f",humi);
return 0;
}else{
printf("\r\n crc humi");
return 2;
}
}
周期性调用sht30_data 可以读取温湿度
MSM8909w 平台下的调试
首先修改iic读写,默认8位寄存器地址,改成16位寄存器地址,参考其他该平台下的驱动可以做找到
// change I2C config to use 16-bit register addresses
device_info[0].port_config.bus_config.i2c->reg_addr_type = SNS_DDF_I2C_REG_ADDR_16BIT; //add huangcheng 2020-05-06 16bit iic address
// Open communication port to the device.
status = sns_ddf_open_port(&state->port_handle, &device_info->port_config);
添加device_info[0].port_config.bus_config.i2c->reg_addr_type = SNS_DDF_I2C_REG_ADDR_16BIT; 寄存器地址就变成16读写了。接下来就是验证,
reg[0] = 0x30;//Set sampling period 0x2130
reg[1] = 0x21;
status = sns_dd_hts222_write_regs(0x3021, reg, 0); //2130(cmd)1hz get data, force write 1 byte ,1->0 write 0 byte ??? --OK
if (status!=SNS_DDF_SUCCESS){
DD_MSG_0(ERROR, "HC write 0x2130 failed");
return status;
}
按照MCU的去写器件地址应该写0x2130,尝试了好久iic读写不成功,用示波器抓图看到第二个数据没返回ack,仔细对了下数据发现写的是0x30 0x21,和文档上的刚好是相反的,把0x2130 改成0x3021 iic能正常读写。写个数,一开始不知道可不可以写0个,写个了两个,把0x3021再写一遍可以成功,测试使用0 也是可以成功的。
上述已经把iic 搞定了。
ADSP获取数据里面的坑!!!
由于是拿hts221 驱动修改过来的,首先看懂hts221 驱动的代码,代码阅读能力差,只能多加打印信息,看代码的probe init getdata 等相关的函数调用
首先proble 有读iic chipid 的不成功直接返回了,直接注释掉。init 也用也注释掉,设置sht3x读频率0x3021(1s一次)。由于注释reset 导致上层怎样也看不到数据,底层根本没报数据,继续添加打印,才找到这个问题,根本原因在于对hts221驱动不熟悉,没办法重新研究hts221寄存器手册,结合代码对比,有些运行要通过寄存器的状态来判读,修改验证了N多次,终于可以读到数据了,数据不对,crc 是OK的。这个折腾了3天,才找到原因。主要原因总结下
1 、iic 的问题和驱动需要修改的问题上述已经说明
2、iic继续报错,温湿度是分开读取的,设置周期1s一次,不能间隔小于这个时间,不能分开读取,在某个一读取后,利用全局变量供另一个使用。
3、数据计算不对,没有找到打印小数的函数,自带的函数%f 打印不出来,其他驱动也没找到,就扩大100,这样打印的数据OK
humid_adc=(uint16_t)((reg[3]<<8)|reg[4]);
humi = (10000.0*((float)humid_adc)/65535.0); // x 100, 32.32 -> 3232
DD_MSG_1(MED, "tmpt %d", humi);
humi_h = (humi/100) << 16;
humi_l = (humi%100)*65536/100;
DD_MSG_1(MED, "humi_h %d", humi_h);
DD_MSG_1(MED, "humi_l %d", humi_l);
humi = humi_h + humi_l;
DD_MSG_1(MED, "humi h<<16 + l*65536/100 %d", humi);
*humid = humi;
DD_MSG_1(MED, "tmptx100 %d", *humid);
DD_MSG_1(MED, " humi %d", *humid);
4、数据上报不对
#define Q16INT(a) ((a)>>16)
#define Q16DEC2(a) ((((a)>=0?(a):-(a))&0x0000FFFF)*100/65536)
这是打印转化的函数,反过来推理上报数据的格式,高16 位放整数部分,低16位放大100倍放小数,这样反过来推精度有点误差,实际验证相差0.01(100倍的情况下),这样上层能获取的数据,基本调试通,但是按照驱动的要求休眠,复位,以及单次、周期、状态信息的读取还没完善,以后完善补充本文。最有一句,没有驱动提供,对于新手来说真是个坑!
2020-05-14