糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > STM32 GPIO模拟I2C的SHT20温湿度采样

STM32 GPIO模拟I2C的SHT20温湿度采样

时间:2020-04-14 09:02:45

相关推荐

STM32 GPIO模拟I2C的SHT20温湿度采样

要用GPIO模拟I2C,那么首先就得弄清楚I2C的时序。

1.I2C总线通信时序

2.起始与结束时序

//起始信号uint8_t I2c_StartCondition(){uint8_t rv = NO_ERROR;SDA_OUT();SCL_OUT();/* StartCondition(S): A high to low transition on the SDA line while SCL is high._______SCL: |________SDA: |_____*/SDA_H();delay_us(2);SCL_H();delay_us(2);SDA_L();//先于SCL前拉低delay_us(2);SCL_L();//拉低SCL便于之后的操作delay_us(2);return rv;}

//终止信号uint8_t I2c_StopCondition(void){uint8_t rv = NO_ERROR;SDA_OUT();/* StopCondition(P): A low to high transition on the SDA line while SCL is high.————————————SCL: — — —_____SDA: ___|*/SCL_L();SDA_L();delay_us(2);SCL_H();delay_us(2);SDA_H();delay_us(2);return rv;}

3.读写时序

//写一个byteuint8_t I2c_WriteByte(uint8_t byte){uint8_t rv = NO_ERROR;uint8_t mask;/* Data line changes must happened when SCL is low */SDA_OUT();SCL_L();/* 1Byte=8bit, MSB send: bit[7]-->bit[0] */for(mask=0x80; mask>0; mask>>=1){if((mask & byte) == 0){SDA_L();}else{SDA_H();}delay_us(5); // data set-up time (t_SU;DAT)SCL_H();delay_us(5); // SCL high time (t_HIGH)SCL_L();delay_us(5); // data hold time(t_HD;DAT)}/* clk #9 wait ACK/NAK from slave */SDA_IN();SCL_H(); // clk #9 for ackdelay_us(5); // data set-up time (t_SU;DAT)//从机应答if( READ_SDA() )rv = ACK_ERROR;OUT:SCL_L();delay_us(20);return rv;}

//读一个byteuint8_t I2c_ReadByte(uint8_t *byte, uint8_t ack){uint8_t rv = NO_ERROR;uint8_t mask;*byte = 0x00;SDA_IN();/* 1Byte=8bit, MSB send: bit[7]-->bit[0] */for(mask = 0x80; mask > 0; mask >>= 1){SCL_H(); // start clock on SCL-linedelay_us(2); // clock set-up time (t_SU;CLK)if(READ_SDA())*byte |= mask; // read bitSCL_L();delay_us(2); // data hold time(t_HD;DAT)}/* clk #9 send ACK/NAK to slave */if(ack == ACK){SDA_OUT();SDA_L(); // send Acknowledge if necessary}else if( ack == NAK ){SDA_OUT();SDA_H(); // send NotAcknowledge if necessary}delay_us(1); // data set-up time (t_SU;DAT)SCL_H(); // clk #9 for ackdelay_us(2); // SCL high time (t_HIGH)OUT:SCL_L();delay_us(2); // wait to see byte package on scopereturn rv;}

注意:

1.无论是写入一个byte还是读出一个byte,都是从MSB到LSB

2.要改变SDA状态时,都是在SCL为低时改变,如果在SCL为高时改变,将被视为开始或结束信号。

4.封装收发信号

//接受从机发来的信号int I2C_Master_Receive(uint8_t addr, uint8_t *buf, int len){int i;int rv = NO_ERROR;uint8_t byte;I2c_StartCondition();rv = I2c_WriteByte(addr);if( rv ){sht20_printf("Send I2C read address failure, rv=%d\n", rv);goto OUT;}for (i=0; i<len; i++){if( !I2c_ReadByte(&byte, ACK) ){buf[i] = byte;}elsegoto OUT;}OUT:I2c_StopCondition();return rv;}

//发送一个命令int I2C_Master_Transmit(uint8_t addr, uint8_t *data, int bytes){int i;int rv = NO_ERROR;if(!data){return PARM_ERROR;}sht20_printf("I2C Mastr start transimit [%d] bytes data to addr [0x%02x]\n", bytes, addr);I2c_StartCondition();rv = I2c_SendAddress(addr);if( rv ){goto OUT;}for (i=0; i<bytes; i++){if( NO_ERROR != (rv=I2c_WriteByte(data[i])) ){break;}}OUT:I2c_StopCondition();return rv;}

5.主函数

采用默认的采样精度,温度采样精度14bit,湿度采样精度12bit,采样测量时间如下图1:

图1采样测量时间

图2命令

注意:

1. I2C总线上的从机都有自己的地址,方便主机选择通信,sht20的地址为0x40,加上最后一位读写位的话,写地址为0x80,读地址为0x81。(非保持主机模式采样)

2. 发送采样命令后要等待采样测量时间之后再去读取数据。

//没有检查检验和short sht20_sample_temp_or_hum(uint8_t cmd){uint8_t data[2];unsigned short sht20_data=0;int rv;//uint8_t tran_cmd=0xF3;rv=I2C_Master_Transmit(0x80,&cmd,1);if(0!=rv)return -1;if(cmd==0xf3)HAL_Delay(85);else if(cmd==0xf5)HAL_Delay(29);rv=I2C_Master_Receive(0x81,data,sizeof(data));if(0!=rv)return -1;sht20_data=data[0];sht20_data=(sht20_data<<8);sht20_data+=data[1]&0xFC;if(cmd==0xf3){sht20_data=(short)((-46.85+175.72*sht20_data/65536)*(10));//计算}else if(cmd==0xf5){sht20_data=(short)((-6.0+125.0*sht20_data/65536)*(10));//计算}printf("sht20_data=%d\n",sht20_data);return sht20_data;}

运行结果:

温度测量:

湿度测量:(单位用H代替)

如果觉得《STM32 GPIO模拟I2C的SHT20温湿度采样》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。