测试第四课,了解ESP32-C3的 I2C 总线使用,与SHT21 温湿度传感器通讯
这一课把基础介绍放在前面,先看基本流程,再去修改代码

目录

  • 前言
  • 1、 ESP32-C3 I2C基础介绍
    • 1.1 I2C初始化
    • 1.2 I2C读写
  • 2、 I2C 示例测试 — SHT21驱动移植
    • 2.1 驱动移植修改
    • 2.2 测试

前言

接下来的ESP32-C3 功能测试都是基于自己设计的开发板:

自己画一块ESP32-C3 的开发板(第一次使用立创EDA)(PCB到手)

开发环境是乐鑫官方的 ESP-IDF, 基于VScode插件搭建好的:

ESP32-C3 VScode开发环境搭建(基于乐鑫官方ESP-IDF——Windows和Ubuntu双环境)

在开发板上面,我画了一个 HTU21D I2C温湿度传感器(和 SHT21 pin to pin,驱动也一样),使用的是 GPIO3 (SDA)和GPIO10 (SCL):

示例程序我们选用i2c_self_test,要注意这个示例的说明,下图中右边介绍这一部分,好好看看:

1、 ESP32-C3 I2C基础介绍

对于ESP32-C3 I2C的介绍,乐鑫的官网的说明链接如下:

乐鑫官方ESP32-C3 I2C部分说明

国产的芯片终于遇到个中文资料了,呵呵~

ESP32-C3 只有一个 I2C接口,可做主机也可以做从机。

本文的测试以及说明是以 ESP23-C3 作为主机来说明

1.1 I2C初始化

根据官方文档,ESP32-C3 UART使用步骤如下:

  1. 设置参数,使用i2c_config_t结构体可以统一设置:

    例如示例中:

    示例中,最后使用了i2c_param_config配置好I2C的所有参数,除了自己定义的,其他的参数会被配置成 I2C 总线协议规范中定义的默认值。
    和 UART 一样,I2C的这些默认值 也可以使用一些函数对某些参数单独进行设置:
  2. 使用i2c_driver_install函数进行 I2C 设备的初始化,其中包括 端口好、通讯模式,发送接收缓存区, 中断标志:

    以示例中的主机初始化为例:

1.2 I2C读写

  1. 完成,上述步骤以后,下面就可以发起通讯,在官方文档中的说明有一张流程图:

    流程说明如下:

    通过示例说明一下上述流程:

    最后放一张官方介绍的 I2C 工作的整体流程图:

2、 I2C 示例测试 — SHT21驱动移植

通过示例工程i2c_self_test创建好工程,通过上面的基础介绍和分析,基本上知道了I2C通讯的步骤和方式了,因为示例代码是与 BH1750 传感器进行的 通讯,所以这里示例代码是无法测试的,直接修改 SHT21 的代码。

2.1 驱动移植修改

因为SHT21驱动函数以前在 STM32上用过,这里就相当于移植过来,先把sht21.csht21.h文件放进来,当然得注意包含关系,宏定义等一些东西:

既然增加了驱动,所以代码就放在驱这两个文件里面,对于sht21.h 文件,宏定义放在此文件中,函数在sht21.c文件中实现(下面会放源码),在此处声明 :

sht21.c 中的温湿度读取函数是如何实现的呢, 先来看一张 STH21 读取的时序图,是我在另一篇博文中写好的:

上图出自:nRF52832学习记录(十一、TWI总线的应用 SHT21程序移植)

这里我就直接上源码 :

#include "sht21.h"struct {sint16 value;uint16 raw;uint8  crc;
} aTemperature, aHumidity;esp_err_t i2c_master_init(void)
{int i2c_master_port = I2C_MASTER_NUM;i2c_config_t conf = {.mode = I2C_MODE_MASTER,.sda_io_num = I2C_MASTER_SDA_IO,.sda_pullup_en = GPIO_PULLUP_ENABLE,.scl_io_num = I2C_MASTER_SCL_IO,.scl_pullup_en = GPIO_PULLUP_ENABLE,.master.clk_speed = I2C_MASTER_FREQ_HZ,// .clk_flags = 0,          /*!< Optional, you can use I2C_SCLK_SRC_FLAG_* flags to choose i2c source clock here. */};esp_err_t err = i2c_param_config(i2c_master_port, &conf);if (err != ESP_OK) {return err;}return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}//    fT  = 175.72*u16T/65536.0 - 46.85;
//    fRH = 125.0*u16RH/65536.0 - 6.0;// -------------------------------------------------------------------
sint16 sht21_calcRH(uint16 u16RH)
{sint16 humidityRH;              // variable for resultu16RH &= ~0x0003;          // clear bits [1..0] (status bits)//-- calculate relative humidity [%RH] --humidityRH = (sint16)(-600 + (12500*(sint32)u16RH)/65536 ); // RH = -6 + 125 * SRH/2^16return humidityRH;                                          // Return RH*100
}// -------------------------------------------------------------------
sint16 sht21_calcTemperature(uint16 u16T)
{sint16 temperature;            // variable for resultu16T &= ~0x0003;           // clear bits [1..0] (status bits)//-- calculate temperature [癈] --temperature= (sint16)(-4685 + (17572*(sint32)u16T)/65536); //T = -46.85 + 175.72 * ST/2^16return temperature;                                        //return T*100
}// i2c_cmd_handle_t cmd = i2c_cmd_link_create();
// i2c_master_start(cmd);
// i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);
// i2c_master_write_byte(cmd, BH1750_CMD_START, ACK_CHECK_EN);
// i2c_master_stop(cmd);
// ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
// i2c_cmd_link_delete(cmd);
// if (ret != ESP_OK) {//     return ret;
// }
// vTaskDelay(30 / portTICK_RATE_MS);
// cmd = i2c_cmd_link_create();
// i2c_master_start(cmd);
// i2c_master_write_byte(cmd, BH1750_SENSOR_ADDR << 1 | READ_BIT, ACK_CHECK_EN);
// i2c_master_read_byte(cmd, data_h, ACK_VAL);
// i2c_master_read_byte(cmd, data_l, NACK_VAL);
// i2c_master_stop(cmd);
// ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
// i2c_cmd_link_delete(cmd);esp_err_t SHT2X_THMeasure(i2c_port_t i2c_num){// uint8 u8Ack;int ret;uint8 t_value[3];uint8 h_value[3];#if (SHT2X_RESOLUTION != 0x00)                                            // only needed if used resolution other than default// i2c_start();                                                        // send start sequence (S)// u8Ack = i2c_write((SHT2X_SLAVEADDRESS<<1)|I2C_WRITE);               // write to slave 0x40// u8Ack = (u8Ack<<1)|i2c_write(SHT2X_CMD_RD_REG);                     // request to read from user register  // i2c_start();                                                         // send start sequence (S)// u8Ack = (u8Ack<<1)|i2c_write((SHT2X_SLAVEADDRESS<<1)|I2C_READ);     // read from slave 0x40// u8UserReg = i2c_read(I2C_NACK);                                    // read user register       // i2c_start();                                                         // send start sequence (S)  // u8Ack = i2c_write((SHT2X_SLAVEADDRESS<<1)|I2C_WRITE);               // write to slave 0x40// u8Ack = (u8Ack<<1)|i2c_write(SHT2X_CMD_WR_REG);                     // request to write user register// u8Ack = (u8Ack<<1)|i2c_write(SHT2X_RESOLUTION | (u8UserReg & ~0x81)); // write new user register datai2c_cmd_handle_t cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, SHT2X_SLAVEADDRESS<<1 | WRITE_BIT, ACK_CHECK_EN);i2c_master_write_byte(cmd, SHT2X_CMD_WR_REG, ACK_CHECK_EN);i2c_master_stop(cmd);ret = i2c_master_cmd_begin(i2c_num, cmd, 500 / portTICK_RATE_MS);i2c_cmd_link_delete(cmd);if (ret != ESP_OK) {return ret;}
#endif//(SHT2X_RESOLUTION != 0x00)// --------------------// measure temperature// --------------------// i2c_start();     // send start sequence (S)// u8Ack = i2c_write((SHT2X_SLAVEADDRESS<<1)|I2C_WRITE);//----IIC???(8?)???7??IIC????0x80(???HT2X_SLAVEADDRESS=0x40)???DATA???(?R:1 ,?WRITE?0) //a write to slave 0x40 // u8Ack = (u8Ack<<1)|i2c_write(SHT2X_CMD_MEAS_T);      //----SHT2X_CMD_MEAS_T=0xF3(??????,???)//request to measure temperature       // i2c_stop();i2c_cmd_handle_t  cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, SHT2X_SLAVEADDRESS<<1 | WRITE_BIT, ACK_CHECK_EN);i2c_master_write_byte(cmd, SHT2X_CMD_MEAS_T, ACK_CHECK_EN);i2c_master_stop(cmd);ret = i2c_master_cmd_begin(i2c_num, cmd, 500 / portTICK_RATE_MS);i2c_cmd_link_delete(cmd);if (ret != ESP_OK) {return ret;}vTaskDelay(SHT2X_TEMP_MEAS_TIME / portTICK_RATE_MS);// shortTermSleep(SHT2X_TEMP_MEAS_TIME);  // HAL_Delay(SHT2X_TEMP_MEAS_TIME);// time_wait(SHT2X_TEMP_MEAS_TIME);// i2c_start();                 // send start sequence (SR)// u8Ack = i2c_write((SHT2X_SLAVEADDRESS<<1)|I2C_READ); //----IIC???(8?)???7??IIC????0x80(???HT2X_SLAVEADDRESS=0x40)???DATA???(?R:1 ,?WRITE?0)  // a read from slave 0x40cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, SHT2X_SLAVEADDRESS << 1 | READ_BIT, ACK_CHECK_EN);i2c_master_read_byte(cmd, &t_value[0], ACK_VAL);i2c_master_read_byte(cmd, &t_value[1], ACK_VAL);i2c_master_read_byte(cmd, &t_value[2], NACK_VAL);i2c_master_stop(cmd);ret = i2c_master_cmd_begin(i2c_num, cmd, 500 / portTICK_RATE_MS);i2c_cmd_link_delete(cmd);// if(u8Ack==I2C_ACK)  {//     aTemperature.raw = i2c_read(I2C_ACK)<<8;                        // read hi byte //     aTemperature.raw |= i2c_read(I2C_ACK);                          // read lo byte//     aTemperature.crc = i2c_read(I2C_NACK);                          // read check sum and finish transfere// }else {//     aTemperature.raw = 0;                       // }// i2c_stop();aTemperature.raw = t_value[0]<<8;aTemperature.raw |= t_value[1];aTemperature.crc = t_value[2]; // -------------------------
// Humidity Measure
// -------------------------// i2c_start();                                                      // send start sequence (S)// u8Ack = i2c_write((SHT2X_SLAVEADDRESS<<1)|I2C_WRITE);             // a write to slave 0x40              1000 0000// u8Ack = (u8Ack<<1)|i2c_write(SHT2X_CMD_MEAS_RH);                  // request to measure humidity F5  1110 0101// i2c_stop();cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, SHT2X_SLAVEADDRESS<<1 | WRITE_BIT, ACK_CHECK_EN);i2c_master_write_byte(cmd, SHT2X_CMD_MEAS_RH, ACK_CHECK_EN);i2c_master_stop(cmd);ret = i2c_master_cmd_begin(i2c_num, cmd, 500 / portTICK_RATE_MS);i2c_cmd_link_delete(cmd);if (ret != ESP_OK) {return ret;}// shortTermSleep(SHT2X_HUMI_MEAS_TIME);// HAL_Delay(SHT2X_HUMI_MEAS_TIME);vTaskDelay(SHT2X_HUMI_MEAS_TIME / portTICK_RATE_MS);// i2c_start();                                                      // send start sequence (SR)// u8Ack = i2c_write((SHT2X_SLAVEADDRESS<<1)|I2C_READ);              // read from slave 0x40                 1000 0001cmd = i2c_cmd_link_create();i2c_master_start(cmd);i2c_master_write_byte(cmd, SHT2X_SLAVEADDRESS << 1 | READ_BIT, ACK_CHECK_EN);i2c_master_read_byte(cmd, &h_value[0], ACK_VAL);i2c_master_read_byte(cmd, &h_value[1], ACK_VAL);i2c_master_read_byte(cmd, &h_value[2], NACK_VAL);i2c_master_stop(cmd);ret = i2c_master_cmd_begin(i2c_num, cmd, 500 / portTICK_RATE_MS);i2c_cmd_link_delete(cmd);// if(u8Ack==I2C_ACK)  {                                             // timeout//     aHumidity.raw = i2c_read(I2C_ACK)<<8;                           // read hi byte //     aHumidity.raw |= i2c_read(I2C_ACK);                             // read lo byte//     aHumidity.crc = i2c_read(I2C_NACK);                           // read check sum and finish transfere// }else{//     aHumidity.raw = 0;// }// i2c_stop();// PowerOff();aHumidity.raw = h_value[0] <<8;                           // read hi byte aHumidity.raw |= h_value[1];                             // read lo byteaHumidity.crc = h_value[2];                           // read check sum and finish transfere aTemperature.value = sht21_calcTemperature(aTemperature.raw);aHumidity.value = sht21_calcRH(aHumidity.raw);      // signed value, temperature = aTemperature.value * 0.01?if(aTemperature.crc!= sht21_CRC((uint8*)&aTemperature.raw, 2))  {}if(aHumidity.crc!= sht21_CRC((uint8*)&aHumidity.raw, 2))  {}if(aTemperature.value>5100) aTemperature.value=5100;              //prevent temperature over-/underflowelse if(aTemperature.value<0) aTemperature.value=0;if(aHumidity.value>10000) aTemperature.value=10000;              //prevent temperature over-/underflowelse if(aTemperature.value<0) aTemperature.value=0;return ret;
}uint16_t getTemperature() {return aTemperature.value;
}uint16_t getHumidity() {return aHumidity.value;
}//==============================================================================
uint8 sht21_CRC(uint8 value[], uint8 u8Bytes) {//  CRCconst uint16 POLYNOMIAL = 0x131;  //P(x)=x^8+x^5+x^4+1 = 100110001uint8 crc = 0;  uint8 byteCtr;uint8 bitCtr;//calculates 8-Bit checksum with given polynomialfor (byteCtr = 0; byteCtr < u8Bytes; ++byteCtr) { crc ^= (value[byteCtr]);for (bitCtr = 8; bitCtr > 0; --bitCtr){ if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;else crc = (crc << 1);}}return crc;
}  

2.2 测试

最后只需要在任务中调用SHT2X_THMeasure 函数即可:

可以看一下整体,i2c_example_main.c文件简单明了多了:

测试结果如下,正常:

ESP32-C3入门教程 基础篇(四、I2C总线 — 与SHT21温湿度传感器通讯)相关推荐

  1. ESP32-C3入门教程 基础篇⑪——Non-Volatile Storage (NVS) 非易失性存储参数的读写

    文章目录 一.前言 二.NVS介绍 三.操作流程 3.1 读操作流程 3.2 写操作流程 四.关键函数 五.随机整数 读写示例 六.对象/数组 读写示例 七.总结 八.参考 一.前言 本文基于VS C ...

  2. ESP32-C3入门教程 基础篇②——GPIO口输入,按键的长按和短按

    文章目录 一.前言 二.硬件准备 三.知识要点 3.1 GPIO使用 3.2 时钟节拍 四.参考例程 五.功能简述 六.源码实现 6.1 中断方式 6.2 定时扫描 七.源码详解 一.前言 本文基于V ...

  3. ESP32-C3入门教程 基础篇(八、NVS — 非易失性存储库的使用)

    前面的7节课把开发板上基本的外设都测试过一边,接下来马上就要进入wifi和蓝牙应用的测试了 在此之前,还需要把掉电数据保存的功能给实现,在STM32中,可以使用内部的flash或者有些自带的EEPRO ...

  4. ESP32-C3入门教程 基础篇(三、UART模块 — 与Enocean无线模块串口通信)

    测试第三课,ESP32-C3的串口通信测试 老样子,使用Enocean无线模块和ESP32-C3进行串口通信. 目录 前言 1.UART示例测试 1.1 UART 基础测试 1.2 与Enocean无 ...

  5. 泰凌微8258入门教程 基础篇④——sig_mesh_sdk架构介绍

    文章目录 一.前言 二.SDK文件架构 三.SDK Demo Project 四.vendor文件架构 4.1 common 4.2 Demo Project目录 五.产品类型定义 一.前言 本系列的 ...

  6. ESP32-C3入门教程 基础篇(六、TIMG 硬件定时器 与 软件定时器)

    到了测试第6课,还没有玩过ESP32-C3的基本定时器,虽然FreeRTOS,可以使用软件定时器 但是软件定时器毕竟也有不适用的时候,这个在我FreeRTOS博文中有单独说明. 所以硬件定时器也得熟悉 ...

  7. 泰凌微8258入门教程 基础篇⑤——发送数据流程

    文章目录 一.Sig Mesh协议 二.Sig SDK 流程图 三.mesh_tx_cmd 四.增加Log 五.调试 一.Sig Mesh协议 二.Sig SDK 流程图 Created with R ...

  8. 泰凌微8258入门教程 基础篇①——Bluetooth® SIG Mesh 快速上手

    文章目录 一.前言 1.1 Telink Bluetooth® Mesh开发工具 1.2 Bluetooth®SIG mesh演示 1.3 基于SDK的演示二进制文件 二.基于APP的节点控制 2.1 ...

  9. 泰凌微8258入门教程 基础篇⑬——群组(订阅)增删流程

    文章目录 一.演示 二.源码分析 三.流程图梳理 3.1 添加群组(订阅) 3.2 删除群组(订阅) 四.增删群组日志 4.1 添加群组(Living Room) 4.2 添加群组(Kitchen) ...

最新文章

  1. java.lang.UnsatisfiedLinkError
  2. webpack学习之路
  3. 交互学习 Vue.js
  4. linux网络寻址顺序,51CTO博客-专业IT技术博客创作平台-技术成就梦想
  5. JavaWeb学习之路——SSM框架之Mybatis(三)
  6. [翻译]:怎样从C/C++代码中对C#进行回调
  7. 10天确定Python,运行环境(超详细步骤)
  8. 论文笔记_S2D.19_2018-PR_基于膨胀卷积神经网络与软加权和推理的分层融合单目深度估计
  9. 计算机串口程序配置,串口设置软件 串口调试工具如何使用
  10. c语言指针选择题库及答案,C语言指针练习习题及答案.doc
  11. c51编译器+linux,C51 开源编译器SDCC学习笔记-安装
  12. AngularJs的UI组件ui-Bootstrap——Datepicker Popup
  13. 客户机键盘某些键失灵
  14. 程序员工作9年月薪从1.5K到24K,网友:不如刚毕业985
  15. Dubbo官方入门实例
  16. Python:学习成绩管理系统
  17. Cast from pointer to smaller type 'int' loses information”
  18. 深圳二手房房源市场研究(上)
  19. 以51单片机为基础的自动循迹小车
  20. 教练技术培训系列篇二——明辨

热门文章

  1. 基于51单片机的电压采集(ADC0804)
  2. NEC、NTT、富士通以及日立开发测试SDN技术
  3. python学习之二次方程求解
  4. Openface 入门
  5. 一级计算机考试电子邮件发送模拟题目,9月计算机一级MSOffice考前模拟试题及答案...
  6. ERDAS 2015 界面菜单目录介绍图
  7. OctaneRender 故障排除
  8. spring-security的基本概念和原理
  9. VL817以及迭代型号VL817S原理图规格书示例
  10. 朝花夕拾 - 基金定投回顾及 2022 定投计划