打印
[PSOC™]

【英飞凌PSOC 4000T DIY】驱动OLED显示屏

[复制链接]
108|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lulugl|  楼主 | 2025-4-13 18:34 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 lulugl 于 2025-4-14 09:17 编辑

#申请开发板# #申请原创# #有奖活动#  @21小跑堂
【前言】
前面我分享了如何搭建基础工程:
【英飞凌PSOC 4000T DIY】进入hellowold之旅   https://bbs.21ic.com/icview-3445992-1-1.html这一篇,我将介绍如何使用CY8CPROTO-040T-MS的串行外设中的I2C外设。我前面学习到了他的串行外设下面可以实现UART、I2C、SPI三个模式,由于这款开发板的IO资源是大部分分配给了电容传器的,所以在UART与I2C分配了同样的IO,所以在开发板上还设计了一个开关SW2进行IO连接的转换。

因此在使用I2C外设时,需要把这个SW2拨到I2C的一侧,这是需要大家注意的。
当然我们也可以使用GPIO来摸拟I2C实现,但是这样就使用不到了他的I2C的一些特有功能了。
【原理图】
如果要使用它他的外设,首先需要了解他的原理图,这样才能正确的把OLED与开发板连接起来。在用户手册中,对扩展接口J24原理图:

在接口中第2脚为GND,第5脚为VCC,经测试电压为3.3可以为OLED提供工作电压。
从原理图的上得到I2C的SDA与SCL分别这P2_3,P2_2:

也与他的数据手册中的pins的复用一致的:

经过上面的分析,那下面就着手如何对他的I2C进行驱动了。
【工程移植】
1、在官方的示例库中有两个工程,分别为I2C的Master和Slave,工程:

2、我们需要驱动的的OLED屏,因此只需要master发送数据即可,所以选用i2c master这个工程做为模版工程即可。
按照前面hello world的工程创建方法,我这里创建了IIC的模版工程,创建好工程如下:


3、拿到模块代码后,首先分析一下他的I2C的工程结构,在工程中有I2C的文件,分别为I2CMaster.c与I2CSlave.c,这两个分别处理作为主、从来处理数据的文件,我们只需要发送数据给OLED所以只需要关心I2CMaster这个文件即可。
4、在master.c中,他首先创建了cy_stc_scb_i2c_master_xfer_config_t 的结构体,并把从机地址给分配为了I2C_SLAVE_ADDR,这是一个宏,因此我们需要把这个宏替换为我们的OLED屏,我这里使用的芯片为ssd1306因此,需要把宏修改为0x3C

/* I2C slave address to communicate with */
#define I2C_SLAVE_ADDR      (0x3c)
5、接下来在I2CMaster.c中有WritePacketToEzI2C这个函数,函数的注释如下
/*******************************************************************************
* Function Name: WritePacketToEzI2C
****************************************************************************//**
*
* Summary:
*   Buffer is assigned with data to be sent to slave.
*   high level PDL library function is used to control I2C SCB to send data to
*   EzI2C slave. Errors are handled depend on the return value from the
*   appropriate function.
*
* Parameters:
*   writebuffer: Command packet buffer pointer
*   bufferSize: Size of the packet buffer
*
* Return:
*   Status after command is written to slave.
*   TRANSFER_ERROR is returned if any error occurs.
*   TRANSFER_CMPLT is returned if write is successful.
*
*******************************************************************************/
函数的说明非常明确,我们只需要把需要发送的writebuffer首地址,以及需要发送的地址传入就行了,返回为两个状态,即为TRANSFER_ERROR或者传感完成TRANSFER_CMPLT。
经过上面的从机地址的指定,以及I2C发送数据的功能函数后,我们就可以来实现我们OLED的代码了。
6、在工程的source文件夹下添加两个文件一个为ssd1306_driver.h以及ssd1306_driver.c,编写OLED的发送命令与发送数据的函数:
// 发送命令到 SSD1306
void ssd1306_send_command(uint8_t command) {
    uint8_t buffer[2] = {SSD1306_COMMAND_MODE, command};
    WritePacketToEzI2C(buffer, 2);
}

// 发送数据到 SSD1306
void ssd1306_send_data(uint8_t data) {
    uint8_t buffer[2] = {SSD1306_DATA_MODE, data};
    WritePacketToEzI2C(buffer, 2);
}
基实移植OLED就是修改以上的两个函数,即可完成。整体代码如下:
/*
* ssd1306_driver.c
*
*  Created on: 2025年4月13日
*      Author: liujianhua
*/

#include "cy_pdl.h"
#include "cybsp.h"
#include "I2CMaster.h"

#define SSD1306_I2C_ADDRESS 0x3C
#define SSD1306_WIDTH 128
#define SSD1306_HEIGHT 64

#define SSD1306_COMMAND_MODE 0x00
#define SSD1306_DATA_MODE 0x40

#define TRANSFER_ERROR 0


// 发送命令到 SSD1306
void ssd1306_send_command(uint8_t command) {
    uint8_t buffer[2] = {SSD1306_COMMAND_MODE, command};
    WritePacketToEzI2C(buffer, 2);
}

// 发送数据到 SSD1306
void ssd1306_send_data(uint8_t data) {
    uint8_t buffer[2] = {SSD1306_DATA_MODE, data};
    WritePacketToEzI2C(buffer, 2);
}

// 初始化 SSD1306
void ssd1306_init() {
    // 复位 OLED

    Cy_SysLib_Delay(1); // 短暂延时

    // 发送初始化命令
    ssd1306_send_command(0xAE); // 关闭显示
    ssd1306_send_command(0xD5); // 设置显示时钟分频比/振荡器频率
    ssd1306_send_command(0x80);
    ssd1306_send_command(0xA8); // 设置多路复用率
    ssd1306_send_command(0x3F);
    ssd1306_send_command(0xD3); // 设置显示偏移
    ssd1306_send_command(0x00);
    ssd1306_send_command(0x40); // 设置显示开始行
    ssd1306_send_command(0x8D); // 电荷泵设置
    ssd1306_send_command(0x14);
    ssd1306_send_command(0x20); // 设置内存寻址模式
    ssd1306_send_command(0x00);
    ssd1306_send_command(0xA1); // 设置段重映射
    ssd1306_send_command(0xC8); // 设置 COM 输出扫描方向
    ssd1306_send_command(0xDA); // 设置 COM 引脚硬件配置
    ssd1306_send_command(0x12);
    ssd1306_send_command(0x81); // 设置对比度控制
    ssd1306_send_command(0xCF);
    ssd1306_send_command(0xD9); // 设置预充电周期
    ssd1306_send_command(0xF1);
    ssd1306_send_command(0xDB); // 设置 VCOMH 取消选择级别
    ssd1306_send_command(0x40);
    ssd1306_send_command(0xA4); // 全局显示开启
    ssd1306_send_command(0xA6); // 设置正常显示
    ssd1306_send_command(0xAF); // 开启显示
}

// 清屏
void ssd1306_clear_screen(uint8_t mode) {
    for (uint8_t page = 0; page < 8; page++) {
        ssd1306_send_command(0xB0 | page); // 设置页地址
        ssd1306_send_command(0x00); // 设置列低地址
        ssd1306_send_command(0x10); // 设置列高地址
        for (uint8_t col = 0; col < SSD1306_WIDTH; col++) {
            ssd1306_send_data(mode);
        }
    }
}
程序中,我添加了一个用于清展的函数,传于Mode来实现对整个屏的刷新。
7、在ssd1306_driver.h中把供用户使用的两个函数定义好即可:
/*
* ssd1306_driver.h
*
*  Created on: 2025年4月13日
*      Author: liujianhua
*/

#ifndef SOURCE_SSD1306_DRIVER_H_
#define SOURCE_SSD1306_DRIVER_H_

void ssd1306_init();
void ssd1306_clear_screen(uint8_t mode);



#endif /* SOURCE_SSD1306_DRIVER_H_ */
8、接下来在Main主函数中添加测试代码,在工程中模版中已有i2c_marster_init了,所以我们只需要添加oled的测试函数即可,整体代码如下:

/* Header file includes */
#include "cy_pdl.h"
#include "cybsp.h"
#include "I2CMaster.h"
#include "I2CSlave.h"
#include "ssd1306_driver.h"

/*******************************************************************************
* Macros
*******************************************************************************/
/* LED Status */
#define OFF                     CYBSP_LED_STATE_OFF
#define ON                      CYBSP_LED_STATE_ON

/* Delay duration */
#define CMD_TO_CMD_DELAY        (1000UL)

int main(void)
{
    cy_rslt_t result;

    /* Initialize the device and board peripherals */
    result = cybsp_init() ;
    if (result != CY_RSLT_SUCCESS)
    {
        CY_ASSERT(0);
    }

    status = initMaster();
    if(status != I2C_SUCCESS)
    {
        handle_error();
    }

    /* Enable interrupts */
    __enable_irq();
    ssd1306_init();  //初始化oled

    for(;;)
    {

            ssd1306_clear_screen(0);  //全屏黑
            Cy_SysLib_Delay(CMD_TO_CMD_DELAY);
            ssd1306_clear_screen(0xFF);  //全屏白
            Cy_SysLib_Delay(CMD_TO_CMD_DELAY);
            Cy_GPIO_Inv(CYBSP_USER_LED1_PORT, CYBSP_USER_LED1_PIN);
    }
}

/* [] END OF FILE */
【测试效果】
编译后下载到开发板,按上面的原理图将OLED与开发板连接起来。然后我们就看OLED屏交规刷新了:

【总结】
ModusToolbox提供好了非常好的外设模版,我们在使用他的外设时,非常方便的就能实现即定功能。当然这只是一个初步的测试,还没有将有可能错误发生的进行处理。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

168

主题

779

帖子

10

粉丝