Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
I2C_IIC
英飞凌Infineon
原创征文
【英飞凌PSoC 6 RTT开发板试用】使用软件和硬件I2C点亮OLED屏,帧率从2FPS提升到51FPS
发布于 2023-07-21 08:00:35 浏览:822
订阅该版
[tocm]
by xusiwei1236
本文将会分别介绍——使用软件I2C和硬件I2C在PSoC开发板上点亮OLED屏,并进行屏幕刷新率对比测试,最后还会在硬件I2C的基础上继续优化屏幕刷新率。本文实验使用的OLED屏尺寸为0.96寸,分辨率为128x64,驱动芯片为SSD1306。本文使用的开发环境为RT-Thread Studio,设备上运行的是RT-Thread实时系统。本文主旨在于,介绍如何在PSoC开发板上使用软件I2C和硬件硬件I2C驱动外设,以及对于屏幕刷新率优化的一些思路。 ## 一、准备工作 开始之前,需要准备实验所需的硬件和软件,接下来分别介绍。 ### 1.1 硬件准备 本次实验需要用到的硬件有: - **RTT&英飞凌PSoC6评估板** - **0.96寸OLED屏(驱动芯片SSD1306)** - 杜邦线4根 - USB Type-C数据线 - 个人电脑(Windows 10) ### 1.2 软件准备 本次实验需要使用的软件主要为: - RT-Thread Studio - MobaXterm(其他串口调试工具也可以) 假设你已经成功在电脑上安装了以上这些软件。 ### 1.3 硬件连接 硬件连接分为两部分,一部分是PC和开发板,通过USB Type-C线连接;这个没啥难度,不做过多介绍;需要注意的是,开发板一端接DAP口;否则无法正常下载程序。 另外一部分是,开发板和OLED屏幕之间的连接,具体如下表所示: | OLED屏引脚 | 开发板引脚 | | --- | --- | | SDA | SDA | | SCL | SCL | | GND | GND | | VCC | 3V3 | 开发板和OLED屏幕之间的硬件连接,如下图所示:  ## 二、原理分析 这么连接之后,如果主控芯片使用软件I2C驱动OLED屏,那么什么限制,对应管脚只需要使用GPIO模拟I2C时序即可。如果想要让主控芯片使用硬件I2C驱动OLED屏,则需要检查一下主控芯片对应引脚可以设置为硬件I2C功能,接下来即为检查的过程。 ### 2.1 开发板原理图 首先,检查开发板原理图的Arduino接口部分:  这里只能看到标号,看不到主控芯片的引脚名称。 所以,还需要继续搜索这两个引脚的标号,找到主控芯片对应的引脚标号:  对照这两处可以知道——Arduino接口I2C引脚和主控芯片直接的连接关系为: - SCL:P8.0 - SDA:P8.1 ### 2.2 芯片数据手册 《PSoC 6 MCU: CY8C62x8, CY8C62xA Datasheet》文档的 Pinouts 章节,**Table 8. Multiple Alternate Functions** 引脚功能服用表,可以查到P8.0和P8.1的功能有:  可以看到,有scb[4].i2c_scl和scb[4].i2c_sda功能。 也就是说,P8.0和P8.1可以设置为硬件I2C功能。 ## 三、软件I2C驱动OLED 接下来,将使用RT-Thread Studio创建项目,并通过添加软件包和修改配置的方式,实现使用软件I2C驱动OLED屏幕。 ### 3.1 创建RT-Thread项目 在RT-Thread Studio中,打开“文件”→“新建”→”RT-Thread项目”菜单,如下图所示:  在弹出的创建项目界面中,Project name中填入psoc6_oled,选中基于开发板的项目,如下图所示:  点击“完成”,即可创建名为psoc6_oled的项目。 ### 3.2 添加ssd1306软件包 创建项目后,双击项目资源管理器视图中,项目下方的“RT-Thread Settings”,主编辑区如下图所示:  点击其中的“添加软件包”,弹出的软件包搜索界面,如下图所示:  按照图中标注的操作顺序,即可将ssd1306软件包添加到当前项目。 添加完成后,主编辑区如下图所示:  此时,按Ctrl+S快捷键,保存对项目配置的修改。如果网络通常,则会在控制台窗口中看到ssd1306软件包正常下载的日志:  这样,ssd1306软件包就成功添加到项目中了,位于packages子目录下:  ### 3.3 配置软件I2C和ssd1306软件包 接下来,在RT-Thread Studio主编辑器,点击详细配置按钮,按钮位置如下图所示:  主编辑器将会显示详细配置:  切换到“硬件”标签页,找到“Enable Software I2C”选项,并打开该选项,如下图所示:  接着,打开“使能I2C1 BUS”,并将scl和sda中分别改为64和65,如下图所示:  然后,在搜索框输入ssd1306,弹出悬浮菜单后,单击该悬浮菜单,如下图所示:  勾选“Enable debug log output”和“Enable ssd1306 sample”,如下图所示:  最后,按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确认连接。 连接成功后,按开发板的复位键,可以看到串口连接中输出:  此时输入help命令并回车:  可以看到,有ssd1306_TestAll命令。 输入ssd1306_TestAll命令并回车,如无意外,将会看到OLED屏幕上已经有画面显示了:  但是此时的帧率较低,测试显示仅有2帧每秒:  ## 四、硬件I2C驱动OLED 方便起见,接下来将不再创建新项目,而是在刚刚创建的RT-Thread Studio项目上进行修改,通过修改配置的方式,实现使用硬件I2C驱动OLED屏幕。 ### 4.1 增加I2C4配置和代码 RT-Thread Studio默认创建的项目不支持I2C4,不能实现硬件I2C驱动OLED。因此,需要先添加I2C4配置和代码,才能进行后续操作。 首先,修改 board/Kconfig 文件,在config BSP_USING_HW_I2C6之前添加如下代码行: ``` config BSP_USING_HW_I2C4 bool "Enable I2C4 Bus (Arduino I2C)" default n if BSP_USING_HW_I2C4 comment "Notice: P8_0 --> 64; P8_1 --> 65" config BSP_I2C4_SCL_PIN int "i2c4 SCL pin number" range 1 113 default 64 config BSP_I2C4_SDA_PIN int "i2c4 SDA pin number" range 1 113 default 65 endif ``` 接着,修改 libraries/HAL_Drivers/SConscript 文件,找到 src += ['drv_i2c.c'] 前一行,添加一个条件: ``` if GetDepend('BSP_USING_HW_I2C3') or GetDepend('BSP_USING_HW_I2C4') or GetDepend('BSP_USING_HW_I2C6'): ``` 最后,修改 libraries/HAL_Drivers/drv_i2c.c 文件,具体修改内容为: ```diff --- a/libraries/HAL_Drivers/drv_i2c.c +++ b/libraries/HAL_Drivers/drv_i2c.c @@ -11,7 +11,7 @@ #include "board.h" #if defined(RT_USING_I2C) -#if defined(BSP_USING_HW_I2C3) || defined(BSP_USING_HW_I2C6) +#if defined(BSP_USING_HW_I2C3) || defined(BSP_USING_HW_I2C4) || defined(BSP_USING_HW_I2C6) #include
#ifndef I2C3_CONFIG @@ -22,7 +22,16 @@ .sda_pin = BSP_I2C3_SDA_PIN, \ } #endif /* I2C3_CONFIG */ -#endif + +#ifndef I2C4_CONFIG +#define I2C4_CONFIG \ + { \ + .name = "i2c4", \ + .scl_pin = BSP_I2C4_SCL_PIN, \ + .sda_pin = BSP_I2C4_SDA_PIN, \ + } +#endif /* I2C4_CONFIG */ + #ifndef I2C6_CONFIG #define I2C6_CONFIG \ { \ @@ -32,11 +41,16 @@ } #endif /* I2C6_CONFIG */ +#endif /* defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) */ + enum { #ifdef BSP_USING_HW_I2C3 I2C3_INDEX, #endif +#ifdef BSP_USING_HW_I2C4 + I2C4_INDEX, +#endif #ifdef BSP_USING_HW_I2C6 I2C6_INDEX, #endif @@ -63,6 +77,10 @@ static struct ifx_i2c_config i2c_config[] = I2C3_CONFIG, #endif +#ifdef BSP_USING_HW_I2C4 + I2C4_CONFIG, +#endif + #ifdef BSP_USING_HW_I2C6 I2C6_CONFIG, #endif @@ -145,8 +163,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,8 +174,6 @@ 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]); @@ -171,4 +186,4 @@ int rt_hw_i2c_init(void) } INIT_DEVICE_EXPORT(rt_hw_i2c_init); -#endif /* defined(BSP_USING_I2C1) || defined(BSP_USING_I2C2) */ +#endif /* RT_USING_I2C */ ``` ### 4.1 修改I2C和ssd1306软件包配置 首先,打开RT-Thread Settings的详细配置,切换到硬件标签页,关闭“Enable Software I2C Bus”配置项,如下图所示:  接着,打开“Enable Hardware I2C Bus”配置项,再打开其中的“Enable I2C4 Bus (Arduino I2C)”配置项,如下图所示:  最后,再次搜索ssd1306,点击悬浮菜单,跳回到ssd1306配置,修改I2C bus name为 i2c4 ,如下图所示:  完成修改后,按Ctrl+S保存配置。 ### 4.2 编译、下载、运行 重新Ctrl+B编译,Ctrl+Alt+D下载,按RESET键复位之后,重新运行 ssd1306_TestAll 命令,可以看到,OLED屏幕成功显示画面了。 并且,这一次测得的帧率为7fps,如下图所示:  这次显示画面快了很多,之前只有2fps,现在已经7fps了;但还是不够高,还可以继续优化。 接下来继续优化,提高帧率,提高帧率的思路: - 提高I2C时钟信号频率 - 减少一帧画面发送数据量 ### 4.3 提高I2C时钟信号频率 接下来,分别从这两方面尝试提升帧率。 首先是提升I2C频率,默认的速度写在drv_i2c.c代码里面: ```c i2c_objs[i].mI2C_cfg.frequencyhal_hz = (400000UL); // 400K ``` 查阅芯片手册,可以知道CY8C624ABZI芯片I2C最高支持1Mbps:  将drv_i2c.c里面的默认I2C频率改为1M之后,测试显示的帧率为12fps:  ### 4.5 减少一帧画面发送数据量 查看ssd1306.c文件,发现可以优化的代码: ```c // Send data void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) { #if PKG_USING_SSD1306_HW_I2C HAL_I2C_Mem_Write(&SSD1306_I2C_PORT, SSD1306_I2C_ADDR, 0x40, 1, buffer, buff_size, HAL_MAX_DELAY); #else for (int i = 0; i < buff_size; i++) { uint8_t buf[2] = {SSD1306_CTRL_DATA, buffer[i]}; rt_i2c_master_send(i2c_bus, SSD1306_I2C_ADDR, RT_I2C_WR, buf, 2); } #endif } ``` 这段代码中,PKG_USING_SSD1306_HW_I2C 宏内部的分支是STM32的代码,不用关系,主要看下面的分支; 下面的分支,使用了一个for循环,调用rt_i2c_master_send接口,每次却只发送两个字节,存在重复的大量的SSD1306_CTRL_DATA字节。 查询SSD1306数据手册,可以知道,它是支持在一个数据标记字节之后,连续发送数据的: 相应的可以优化为: ```c // Send data void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) { uint32_t len = buff_size + 1; uint8_t* data = rt_malloc(len); // 申请一个更大的缓冲 RT_ASSERT(data); // 准备数据 data[0] = SSD1306_CTRL_DATA; rt_memcpy(&data[1], buffer, buff_size); // 发送 rt_i2c_master_send(i2c_bus, SSD1306_I2C_ADDR, RT_I2C_WR, data, len); rt_free(data); // 释放 } ``` 这段代码修改之后,再次运行,测得帧率为45fps:  更进一步检查,发现还有优化空间: ```c void ssd1306_UpdateScreen(void) { // Write data to each page of RAM. Number of pages // depends on the screen height: // // * 32px == 4 pages // * 64px == 8 pages // * 128px == 16 pages for(uint8_t i = 0; i < SSD1306_HEIGHT/8; i++) { ssd1306_WriteCommand(0xB0 + i); // Set the current RAM page address. ssd1306_WriteCommand(0x00); ssd1306_WriteCommand(0x10); ssd1306_WriteData(&SSD1306_Buffer[SSD1306_WIDTH*i],SSD1306_WIDTH); } } ``` 这个函数里面,从注释可以知道,对于128x64分辨率的屏,会分为8页进行发送;每个页面发送开始的时候,会调用三次ssd1306_WriteCommand函数。 实际上可以不需要重复调用ssd1306_WriteCommand函数: ```c void ssd1306_UpdateScreen(void) { uint8_t cmd[] = { 0X21, // 设置列起始和结束地址 0X00, // 列起始地址 0 0X7F, // 列终止地址 127 0X22, // 设置页起始和结束地址 0X00, // 页起始地址 0 0X07, // 页终止地址 7 }; uint32_t count = 0; uint8_t data[2 * sizeof(cmd) + 1 + SSD1306_BUFFER_SIZE ] = {}; // copy cmd for (uint32_t i = 0; i < sizeof(cmd)/sizeof(cmd[0]); i++) { data[count++] = SSD1306_CTRL_CMD | SSD1306_MASK_CONT; data[count++] = cmd[i]; } // copy frame data data[count++] = SSD1306_CTRL_DATA; memcpy(&data[count], SSD1306_Buffer, sizeof(SSD1306_Buffer)); count += sizeof(SSD1306_Buffer); // send to i2c bus rt_i2c_master_send(i2c_bus, SSD1306_I2C_ADDR, RT_I2C_WR, data, count); } ```  非常快了,已经是最初2fps的25倍。 最终达到的帧率并没有达到OLED屏幕的物理极限,可能还存在一些优化空间,感兴趣的读者还可以在此基础上继续探索。 文章就到这里,感谢阅读,下次再会~ ## 五、参考链接 1. RTT PSoC开发板原理图:[IFX-PSoC6-RT-Thread-sch.pdf (gitee.com)](https://gitee.com/RT-Thread-Studio-Mirror/sdk-bsp-cy8c624-infineon-evaluationkit/raw/main/documents/IFX-PSoC6-RT-Thread-sch.pdf) 2. CY8C624A 芯片数据手册:[Infineon-PSOC_6_MCU_CY8C62X8_CY8C62XA-DataSheet-v18_00-EN.pdf](https://www.infineon.com/dgdl/Infineon-PSOC_6_MCU_CY8C62X8_CY8C62XA-DataSheet-v18_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0ee7d03a70b1) 3. CY8C624A 架构参考手册: [Infineon-PSoC_6_MCU_CY8C6xx8_CY8C6xxA_Architecture_Technical_Reference_Manual_(TRM)-AdditionalTechnicalInformation-v08_00-EN.pdf](https://www.infineon.com/dgdl/Infineon-PSoC_6_MCU_CY8C6xx8_CY8C6xxA_Architecture_Technical_Reference_Manual_(TRM)-AdditionalTechnicalInformation-v08_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0f94fd420282&utm_source=cypress&utm_medium=referral&utm_campaign=202110_globe_en_all_integration-files) 4. CY8C624A 寄存器参考手册: [Infineon-PSoC_6_MCU_CY8C62x8_CY8C62xA_Registers_Technical_Reference_Manual-AdditionalTechnicalInformation-v06_00-EN.pdf](https://www.infineon.com/dgdl/Infineon-PSoC_6_MCU_CY8C62x8_CY8C62xA_Registers_Technical_Reference_Manual-AdditionalTechnicalInformation-v06_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0f94f764027c&utm_source=cypress&utm_medium=referral&utm_campaign=202110_globe_en_all_integration-files) 5. Cypress HAL接口参考: [Redirecting to Infineon GitHub (cypresssemiconductorco.github.io)](https://cypresssemiconductorco.github.io/psoc6hal/html/modules.html)
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
xusiwei1236
https://blog.csdn.net/xusiwei1236
文章
11
回答
41
被采纳
6
关注TA
发私信
相关文章
1
NXP的I2C应该比ST的好用吧
2
Use of I2C device driver
3
关于I2C 驱动问题请教
4
我如何知道这个iic的io配置和我电路设计的是一致的?
5
I2C模拟读操作失败,不知道问什么进不去读函数
6
RTT的I2C有官方文档资料没有
7
求 STM32F103 IIC 自定义IO初始化 代码
8
报一个LPC4008代码中I2C的bug
9
RTOS IIC总线使用
10
关于在RTT中使用STM32 I2C的疑问
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
I2C_IIC
UART
ESP8266
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
编译报错
中断
Debug
rt_mq_消息队列_msg_queue
keil_MDK
ulog
SFUD
msh
C++_cpp
MicroPython
本月问答贡献
RTT_逍遥
10
个答案
3
次被采纳
xiaorui
3
个答案
2
次被采纳
winfeng
2
个答案
2
次被采纳
三世执戟
8
个答案
1
次被采纳
KunYi
8
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
lizimu
2
篇文章
9
次点赞
swet123
1
篇文章
4
次点赞
Days
1
篇文章
4
次点赞
YZRD
1
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部