要用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.读写时序

 

//写一个byte
uint8_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;
}
//读一个byte
uint8_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温湿度采样相关推荐

  1. STM32 通用GPIO模拟I2C实现

    STM32 通用GPIO模拟I2C实现 通用GPIO模拟I2C通信实现样例 1 GPIO初始化 #ifdef HW_I2C1 //硬件I2C初始化//PA8-I2C1_SCLGPIO_StructIn ...

  2. 外设驱动库开发笔记8:GPIO模拟I2C驱动

    I2C总线简单方便,是我们经常使用的一种总线.但有时候我们的MCU没有足够多的I2C控制器来实现我们的应用,所幸我可以使用普通的GPIO引脚来模拟低速的I2C总线通信.这一节我们就来实现使用软件通过普 ...

  3. STM32实现基于I2C的AHT20温湿度采集

    STM32实现基于I2C的AHT20温湿度采集 I2C通信协议 软件I2C与 硬件I2C 代码实现 烧录 硬件连接 烧录并运行 参考 I2C通信协议 I2C协议简介 IC( Inter-- Integ ...

  4. STM32使用模拟I2C读取硒翔30mL流量传感器

    使用模拟I2C读取硒翔30mL/min流量传感器 该工程使用某些采样次数和时间不同会采集到的报文有问题. 我建议是可以换个次数和时间调下. 如果报文有问题的话 就修改延时就好了,延时指的是I2C每发送 ...

  5. STM32单片机硬件I2C读取AHT10温湿度传感器数据

    STM32使用硬件IIC读取AHT10温湿度传感器的数据并显示在0.96寸OLED屏上. 我用的单片机是STM32F103C8T6,程序用的是ST标准库写的. STM32使用硬件I2C读取SHTC3温 ...

  6. GPIO模拟I2C程序实现

    GPIO模拟I2C程序实现. I2C是由Philips公司发明的一种串行数据通信协议,仅使用两根信号线:SerialClock(简称SCL)和SerialData(简称SDA).I2C是总线结构,1个 ...

  7. Linux I2C子系统分析之(一) ----- 用GPIO模拟I2C总线

    在drivers/i2c/busses下包含各种I2C总线驱动,如S3C2440的I2C总线驱动i2c-s3c2410.c,使用GPIO模拟I2C总线的驱动i2c-gpio.c,这里只分析i2c-gp ...

  8. S5PV210之GPIO模拟I2c时序之pcf8591与at24xx linux3.0.8驱动

    目录:一. 说明 二. 驱动程序说明及问题 三. 案例一       四. 案例二 一. 说明 mini210开发板上带了at24c08, 看了linux内核自带的at24.c的驱动程序,编译下载到看 ...

  9. linux源码gpio模拟i2c,linux内核gpio模拟i2c实例.doc

    linux内核gpio模拟i2c实例.doc linux内核GPIO模拟I2C实例2010-10-11作者:cvip302814来源:cvip302814的blog前言:在许多情况下,我们并没有足够的 ...

  10. i2c 驱动五:gpio模拟i2c

    有关linux的i2c相关文章有一下几篇,他们互相关联,应该一同看: - i2c 驱动一:简介 - i2c 驱动二:devfs文件系统 - i2c 驱动三:自己实现设备和驱动分离 - i2c 驱动四: ...

最新文章

  1. 新车模、新舵机、新体验
  2. The NVIDIA driver on your system is too old
  3. 印发 指南 通知_通知设计的综合指南
  4. 获取可用密码算法的列表
  5. java random用法_JAVA面试题(1)
  6. 计算机网络第七版总结报告,计算机网络(第七版)第一章总结(超详细!)
  7. Kubernetes 版本锁定到1.12.3
  8. 大数据系列之分布式数据库HBase-1.2.4+Zookeeper 安装及增删改查实践
  9. Java开发环境搭建及开发软件和服务器安装与配置
  10. 云南省电子计算机高级,计算机基础知识-云南省电子信息高级技工学校.ppt
  11. 苹果手机壳_潮牌刺绣苹果8 Plus手机壳,让爱机焕然一新
  12. 微信公众号验签过程详解--前端和后端的操作
  13. centos 6.5 安装qt5.2
  14. 气象报告是什么计算机领域,计算机辅助翻译系统在亚运气象服务方面的应用报告...
  15. 【论文】 各高校的毕业论文的Latex模板链接
  16. S1200和博途软件通讯测试,S7-1200博途和组态王软件通讯(高端培训).pdf
  17. qt 设计师界面 图片_如果没有设计界面,设计师会发生什么?
  18. ZOJ 1428 Magazine Delivery
  19. 【操作系统基础】操作系统的分类与发展
  20. 关于三角形面积的公式与格点多边形面积计算算法的讨论

热门文章

  1. C# 绘制矩形方框读写内存类 cs1.6人物透视例子
  2. 立创 EDA #学习笔记10# | 常用连接器元器件识别 和 蜂鸣器驱动电路
  3. CoolShell-第4题
  4. 如何正确认识网络工程师
  5. [黑客入门]花无涯新手入门教程笔记
  6. threejs 三面体_three.js几何体对象_三维建模_郭隆邦技术博客
  7. 第一次跳槽总结(产品经理,简历面试)
  8. 10个技巧,帮你改进UI设计
  9. python分析掷骰子游戏
  10. 【GIS开发】批量下载和拼接地图瓦片(Python)