本文将会分别介绍——使用软件I2C和硬件I2C在PSoC开发板上获取SHT30数字温湿度传感器的数据。本文实验使用的是4线的SHT30模组,通信接口为I2C,对外仅提供四根线,使用起来简单、便捷。本文使用的开发环境为RT-Thread Studio,设备上运行的是RT-Thread实时系统。本文主旨在于,介绍如何在PSoC开发板上使用软件I2C和硬件硬件I2C驱动外设。
如需离线阅读,可以下载本文的完整pdf版本:
*附件:【英飞凌PSoC 6 RTT开发板试用】通过I2C接口读取SHT30传感器的温湿度数据 28a12ba6538e461da5c07d6ff64279b1.pdf
一、环境准备
开始之前,需要准备实验所需的硬件和软件,接下来分别介绍。
1.1 硬件准备
本次实验需要用到的硬件有:
- RTT&英飞凌PSoC6评估板
- SHT30模组
- 杜邦线4根
- USB Type-C数据线
- 个人电脑,Windows 10系统
1.2 软件准备
本次实验需要使用的软件主要为:
- RT-Thread Studio
- MobaXterm(其他串口调试工具也可以)
假设你已经成功在电脑上安装了以上这些软件。
二、硬件原理分析
2.1 硬件连接
硬件连接分为两部分,一部分是PC和开发板,通过USB Type-C线连接;这个没啥难度,不做过多介绍;需要注意的是,开发板一端接DAP口;否则无法正常下载程序。
另外一部分是,开发板和OLED屏幕之间的连接,具体如下表所示:
SHT30模组 | 开发板引脚 |
---|---|
SCL | A0 |
SDA | A1 |
GND | GND |
VCC | 3V3 |
开发板和OLED屏幕之间的硬件连接,如下图所示:
2.2 开发板原理图
这里只能看到标号,看不到主控芯片的引脚名称。
所以,还需要继续搜索这两个引脚的标号,找到主控芯片对应的引脚标号:
对照前面的传感器与开发板的连接图,以及这两处原理图,可以知道——传感器模组I2C引脚和主控芯片直接的连接关系为:
- SCL:P10.0
- SDA:P10.1
2.3 芯片数据手册
《PSoC 6 MCU: CY8C62x8, CY8C62xA Datasheet》文档的 Pinouts 章节,Table 8. Multiple Alternate Functions 引脚功能服用表,可以查到P10.0和P10.1的功能有:
可以看到,有scb[1].i2c_scl和scb[1].i2c_sda功能。
也就是说,P10.0和P10.1可以设置为硬件I2C功能。
三、软件I2C获取SHT30数据
接下来,将使用RT-Thread Studio创建项目,并通过添加软件包和修改配置的方式,实现使用软件I2C获取SHT30的温湿度数据。
3.1 创建RT-Thread项目
在RT-Thread Studio中,打开“文件”→“新建”→”RT-Thread项目”菜单,如下图所示:
在弹出的创建项目界面中,Project name中填入psoc6_sht30,选中基于开发板的项目,如下图所示:
点击“完成”,稍等几秒钟,即可创建名为psoc6_sht30的项目。
3.2 添加ssd1306软件包
创建项目后,双击项目资源管理器视图中,项目下方的“RT-Thread Settings”,主编辑区如下图所示:
点击其中的“添加软件包”,弹出的软件包搜索界面,如下图所示:
按照图中标注的操作顺序,即可将ssd1306软件包添加到当前项目。
添加完成后,主编辑区如下图所示:
此时,按Ctrl+S快捷键,保存对项目配置的修改。如果网络通常,则会在控制台窗口中看到ssd1306软件包正常下载的日志:
这样,ssd1306软件包就成功添加到项目中了,位于packages子目录下:
3.3 配置软件I2C引脚
接下来,在RT-Thread Studio主编辑器,点击详细配置按钮,按钮位置如下图所示:
主编辑器将会显示详细配置:
切换到“硬件”标签页,找到“Enable Software I2C”选项,并打开该选项,如下图所示:
接着,打开“使能I2C1 BUS”,并将scl和sda中分别改为80和81,如下图所示:
最后,按Ctrl+S保存对所有配置项的修改。
3.4 编译和下载程序
首先,点击工具栏的锤子图标,或者按Ctrl+B快捷键,触发项目构建(全部编译):
项目构建完成后,可以在控制台窗口看到生成了elf文件,以及预计Flash和RAM占用情况:
接着,点击工具栏上的下载图标,或者Ctrl+Alt+D快捷键,触发下载程序二进制文件到开发板上,如下图:
下载过程中以及下载完成后,控制台窗都可以看到日志输出:
PS:开始下载之前,需要确认开发板以及和PC正确连接了(开发板要连在DAP口上,并能够正常识别)。
3.5 运行和测试程序
为了方便在串口中进行命令控制,运行之前,需要先打开MobaXterm(或者其他串口调试工具):
如上图所示,选中对应的COM号,串口参数设置为:
- 波特率 115200
- 数据位 8
- 停止位 1
- 校验 None
- 流控 None
之后,点OK确认连接。
连接成功后,按开发板的复位键,可以看到串口连接中输出:
可以看到i2c1成功注册的日志。
此时输入help命令并回车:
可以看到,有sht3x命令了。
输入sht3x命令并回车,将会输出用法提示:
可以看到,使用 sht3x probe 加上i2c设备名称,可以探测传感器;
我们先用list device看看有哪些设备:
可以看到i2c1设备了。
接下来,使用 sht3x probe i2c1 探测设备:
已经成功探测到了。
紧接着,使用sht3x read尝试读取传感器温湿度值:
成功读取到了温湿度数据!
接下来,我把手指放在传感器上,多读几次(上下键翻历史命令,再回车,可以避免重复复输入),应该可以看到温度和湿度都在不断升高:
说明传感器是正常工作的。
四、硬件I2C获取SHT30数据
前面通过查询原理图,我们知道开发板Arduino接口的A0/A1引脚可以设置为I2C1功能,接下来将在前面创建的项目的基础上,修改代码,实现通过硬件I2C1获取SHT30的温湿度数据。
4.1 增加硬件I2C1配置和代码
RT-Thread Studio默认创建的项目不支持硬件I2C1,不能实现硬件I2C1驱动SHT30。因此,需要先添加I2C4配置和代码,才能进行后续操作。
首先,修改 board/Kconfig 文件,在config BSP_USING_HW_I2C3之前添加如下代码行:
config BSP_USING_HW_I2C1
bool "Enable I2C1 Bus (User I2C)"
default n
if BSP_USING_HW_I2C1
comment "Notice: P10_0 -- > 80; P10_1 -- > 81"
config BSP_I2C1_SCL_PIN
int "i2c4 SCL pin number"
range 1 113
default 80
config BSP_I2C1_SDA_PIN
int "i2c4 SDA pin number"
range 1 113
default 81
endif
接着,修改 libraries/HAL_Drivers/SConscript 文件,找到 src += ['drv_i2c.c'] ,将其前面的条件修改为:
if GetDepend('BSP_USING_HW_I2C1') or GetDepend('BSP_USING_HW_I2C3') or GetDepend('BSP_USING_HW_I2C6'):
src += ['drv_i2c.c']
最后,修改 libraries/HAL_Drivers/drv_i2c.c 文件,具体修改内容为:
--- a/libraries/HAL_Drivers/drv_i2c.c
+++ b/libraries/HAL_Drivers/drv_i2c.c
@@ -11,9 +11,19 @@
#include "board.h"
#if defined(RT_USING_I2C)
-#if defined(BSP_USING_HW_I2C3) || defined(BSP_USING_HW_I2C6)
#include
+#include "drv_log.h"
+
+#ifndef I2C1_CONFIG
+#define I2C1_CONFIG \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+ { \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+ .name = "i2c1", \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+ .scl_pin = BSP_I2C1_SCL_PIN, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+ .sda_pin = BSP_I2C1_SDA_PIN, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+ }
+#endif
+
#ifndef I2C3_CONFIG
#define I2C3_CONFIG \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
@@ -22,7 +32,7 @@
.sda_pin = BSP_I2C3_SDA_PIN, \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
}
#endif /* I2C3_CONFIG */
-#endif
+
#ifndef I2C6_CONFIG
#define I2C6_CONFIG \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
{ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
@@ -34,6 +44,9 @@
enum
{
+#ifdef BSP_USING_HW_I2C1
+ I2C1_INDEX,
+#endif
#ifdef BSP_USING_HW_I2C3
I2C3_INDEX,
#endif
@@ -59,6 +72,10 @@ struct ifx_i2c
static struct ifx_i2c_config i2c_config[] =
{
+#ifdef BSP_USING_HW_I2C1
+ I2C1_CONFIG,
+#endif
+
#ifdef BSP_USING_HW_I2C3
I2C3_CONFIG,
#endif
@@ -145,8 +162,7 @@ void HAL_I2C_Init(struct ifx_i2c *obj)
int rt_hw_i2c_init(void)
{
- rt_err_t result;
- cyhal_i2c_t mI2C;
+ rt_err_t result = RT_EOK;
for (int i = 0; i < sizeof(i2c_config) / sizeof(i2c_config[0]); i++)
{
@@ -157,18 +173,18 @@ int rt_hw_i2c_init(void)
i2c_objs[i].mI2C_cfg.address = 0;
i2c_objs[i].mI2C_cfg.frequencyhal_hz = (400000UL);
- i2c_objs[i].mI2C = mI2C;
-
i2c_objs[i].i2c_bus.ops = &i2c_ops;
HAL_I2C_Init(&i2c_objs[i]);
result = rt_i2c_bus_device_register(&i2c_objs[i].i2c_bus, i2c_config[i].name);
RT_ASSERT(result == RT_EOK);
+
+ LOG_I("Hardware I2C device %s registered!", i2c_config[i].name);
}
return 0;
}
INIT_DEVICE_EXPORT(rt_hw_i2c_init);
-#endif /* defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) */
+#endif /* defined(RT_USING_I2C) */