【ESP32-C3-DevKitM-1】ESP32-C3的硬件I2C+SHT30
<p style="text-align:justify"><span style="font-size:10.5pt"><span style="font-family:Calibri"><b><span style="font-size:14.0000pt"><span style="font-family:黑体"><span style="font-weight:bold">4、I2C的评测</span></span></span></b></span></span></p><p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal">ESP32-C3有一组硬件I2C,支持主机和从机模式,速度可支持标准模式和快速模式,最高可达800Kbit/s,但受限于SDA和SDL的上拉强度,芯片内部的SDA和SDL脚有上拉电阻可以配置。同时,引脚可以任意映射,如下图</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"><span style="font-size:16px;"><span style="font-family:Calibri"><span style="font-family:宋体"><font face="宋体">接下来我将使用硬件</font>I2C<font face="宋体">来驱动温湿度传感器</font><font face="Calibri">SHT30</font></span></span></span></p>
<p style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="125%"><span style="font-family:Calibri"><b><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:bold"><font face="宋体">1、初始化</font>I2C</span></span></span></span></b></span></span></span></span></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><font face="宋体">因为</font>GPIO<font face="宋体">没有默认,所以要指定</font><font face="Calibri">GPIO</font><font face="宋体">作为</font><font face="Calibri">SDA</font><font face="宋体">和</font><font face="Calibri">SCL</font><font face="宋体">,还要选择</font><font face="Calibri">I2C</font><font face="宋体">的</font><font face="Calibri">mode</font><font face="宋体">,这里我们选择</font><font face="Calibri">Master</font><font face="宋体">,同时使能内部上拉,还要配置</font><font face="Calibri">I2C</font><font face="宋体">的时钟速度,这里我们选用</font><font face="Calibri">100KHz</font><font face="宋体">,最后调用</font></span></span></span><span style="font-size:12.0000pt"><span style="background:#e8f2fe"><span style="font-family:Consolas"><span style="125%"><span style="color:#000000">i2c_param_config</span></span></span></span></span><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><font face="宋体">和</font></span></span></span><span style="font-size:12.0000pt"><span style="background:#e8f2fe"><span style="font-family:Consolas"><span style="125%"><span style="color:#000000">i2c_driver_install</span></span></span></span></span><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><font face="宋体">来完成配置,这里注意一下</font>I2C<font face="宋体">的端口</font></span></span></span><span style="font-size:12.0000pt"><span style="background:#e8f2fe"><span style="font-family:Consolas"><span style="125%"><span style="color:#000000">i2c_master_port</span></span></span></span></span><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><font face="宋体">我这里是</font></span></span></span><span style="font-size:12.0000pt"><span style="background:#e8f2fe"><span style="font-family:Consolas"><span style="125%"><span style="color:#000000">I2C_NUM_0</span></span></span></span></span><span style="font-size:12.0000pt"><span style="background:#e8f2fe"><span style="font-family:宋体"><span style="125%"><span style="color:#000000"><font face="宋体">,</font></span></span></span></span></span><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><font face="宋体">具体程序见下图。</font></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><font face="宋体">还有一些宏定义</font></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="125%"><span style="font-family:Calibri"><b><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:bold"><font face="宋体">2、配置</font>I2C的相关函数</span></span></span></span></b></span></span></span></span></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><font face="宋体">这里直接调用</font>API<font face="宋体">就行了,同时为了提高移植性,我将官方的</font><font face="Calibri">API</font><font face="宋体">封装了一下,这样</font><font face="Calibri">SHT30</font><font face="宋体">在调用的时候可以灵活切换软硬件</font><font face="Calibri">I2C</font><font face="宋体">驱动函数,见下图</font></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><font face="宋体">下图是在</font>SHT30<font face="宋体">头文件里的宏定义,可以实现软硬件</font><font face="Calibri">I2C</font><font face="宋体">灵活切换</font></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><b><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:bold">3、配置SHT30的函数</span></span></span></span></b></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal">SHT30的驱动函数网上也比较多,我就不细讲了,讲一些核心函数,我这里选用Singleshot模式来采集数据,首先要初始化SHT30,这里比较简单,就是I2C的初始化,见下图</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><b><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:bold">4、配置读取SHT30数据的函数</span></span></span></span></b></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal"><font face="宋体">首先要讲一下</font>ESP32-C3的I2C的一些基本操作,包括主机向从机写入数据和主机从从机读取数据,具体的在官方编程指南了写的很明白了,见下图</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="color:#ff0000"><span style="font-weight:normal"><font face="宋体">这里需要注意一点,上边的步骤缺一不可</font></span></span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal"><font face="宋体">具体要怎么通过</font>I2C来操作SHT30呢,当然是参考官方数据手册,下图是Singleshot模式的操作时序图</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal">1、首先,发送开始信号,再发送write header,我这里是0x88,然后再发送16位的配置命令,比如配置成高重复性或者低重复性,这个可以参考数据手册或者互联网,我就不细讲了,最后发送停止信号,见下图的程序</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-justify:inter-ideograph"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="font-weight:normal"><font face="宋体">这里的</font>Sht30_WriteCommand就是发送两次8位数据,依次是高8位和低8位</span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal"><font face="宋体">同时,因为发送的</font>3组8位数据都是有ACK响应的,所以要将使能主机检查ACK,也就是设置ACK_CHECK_EN</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal">2、延时至少1ms,也就是SCL free,这时候SHT30正在测量</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal">3、发送开始信号,写入read header,我这里的值为0x89,根据时序图,SHT30会返回一个NACK,所以可以不使能主机检查ACK,也就是设置ACK_CHECK_DIS,最后发送停止信号</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal">4、再延时大于1ms</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal">5、再次发送开始信号,再写入read header,如果转换好了,SHT30会发送一个ACK,没有的话可以稍微延长延时时间,然后依次读写6组8位的SHT30返回的数据,</span></span></span></span><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="color:#ff0000"><span style="font-weight:normal"><font face="宋体">这里注意一下,收到前</font>5组数据时要发送ACK,最后1组不需要(虽然加了也没什么关系),然后再发送停止信号就好了。这里还需要注意一点,在读数据时一定要将从设备发送过来的数据全部读完,不然会莫名出问题的,踩了坑)</span></span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal">6、最后要验证收到的数据的正确性,要进行CRC验证,具体算法我就不讲了,大家可以看数据手册。其中temp和humi是CRC数据,如果数据验证正确,再对原始数据进行转换成真实数据。</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal"><font face="宋体">下图为</font>CRC验证算法和数据转换算法</span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"> </p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal"><font face="宋体">最后在主函数调用如下函数</font></span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p align="justify" style="text-align:justify"><span style="font-size:10.5pt"><span style="text-autospace:ideograph-numeric"><span style="text-justify:inter-ideograph"><span style="125%"><span style="font-family:Calibri"><span style="font-size:12.0000pt"><span style="font-family:宋体"><span style="125%"><span style="font-weight:normal"><font face="宋体">用串口打印如下结果,成功驱动</font></span></span></span></span></span></span></span></span></span></p>
<p align="justify" style="text-align:justify"></p>
<p>欢迎讨论和指正</p>
<p>文章排版还是非常好的。功能设计的也很清晰!</p>
<p>通过<span style="color:#333333">I2C来操作SHT30写的很详细,评测的很赞</span></p>
<p>这个i2c的图看着有点复杂啊</p>
freebsder 发表于 2021-7-9 21:53
这个i2c的图看着有点复杂啊
<p>感觉还好吧</p>
<p> </p>
页:
[1]