Page 1 of 1

TuyaOS T2-U开发板驱动ssd1306并成功移植u8g2

Posted: 2024年 Apr 17日 14:26
by chenyisong

SSD1306介绍

SSD1306 是一款带控制器的 OLED 点阵图形显示系统的单片 CMOS OLED/PLED 驱动器。它由 128 个 列输出 (SEG)和 64 个行输出(COM)组成,该芯片专为共阴极 OLED 面板设计。

SSD1306内置对比度控制器、显示RAM(GDDRAM)和振荡器,以此减少了外部元件的数量和功耗。该芯片有256级亮度控制。数据或命令由通用微控制器通过硬件选择的6800/8000系通用并行接口、I2C接口或 SPI发送。该芯片适用于许多小型便携式应用,如手机副显示屏、MP3播放器和计算器等。

ssd1306.png

特性:

  • 分辨率:128 x 64 点阵
  • 电源:对于集成逻辑电路,VDD=1.65V3.3V;对于面板驱动,VCC=7V15V
  • 点阵驱动:
    • OLED 驱动输出电压,最大15V;
    • SEG 最大源电流:100uA;
    • COM 最大汇电流:15mA;
    • 256 阶对比度亮度电流控制
  • 内置 128 x 64 位 SRAM 显示缓冲区
  • 引脚可选择的 MCU 接口:8位6800/8080串并接口、 3/4线串行外围接口、I2C 接口
  • 水平和垂直方向的屏幕保持连续滚动功能
  • RAM写同步信号
  • 可编程帧速率和复用率
  • 行重映射和列重映射
  • 片内内置振荡器
  • COG和COF的芯片封装
  • 工作温度范围广:-40°C至85°C

SSD1306 通讯接口可通过外部电阻连接选择。本次项目使用 I2C 通讯,所以需焊接 R1/R4/R6/R7/R8 电阻,其中 R6/R7 为 I2C上拉电阻。

ssd1306-2.png

U8g2

U8g2 是一个用于嵌入式设备的简易图形库,可以在多种 OLED 和 LCD 屏幕上,支持包括 SSD1306 等多种类型的底层驱动,并可以很方便地移植到 Arduino 、树莓派和 ARM 上。

U8g2 库的 GitHub 地址为:https://github.com/olikraus/u8g2 ,可以从中获取到源码与文档帮助。

移植

U8g2 移植比较简单,U8g2 自带了软件 I2C 通讯,适配层完成:

  1. gpio 初始化及 I2C对应的 SCL 和 SDA 操作
  2. 延时控制

Code: Select all

#include "u8g2.h"

/***********************************************************
***********************typedef define***********************
***********************************************************/
#define TASK_IIC_PRIORITY           THREAD_PRIO_1
#define TASK_IIC_SIZE               2048

#define SSD1306_SCL_PIN             TUYA_GPIO_NUM_20
#define SSD1306_SDA_PIN             TUYA_GPIO_NUM_22

/***********************************************************
********************function declaration********************
***********************************************************/


/***********************************************************
***********************variable define**********************
***********************************************************/
STATIC THREAD_HANDLE sg_u8g2_handle;
STATIC THREAD_HANDLE ty_app_thread = NULL;
STATIC THREAD_CFG_T sg_task = {
    .priority = TASK_IIC_PRIORITY,
    .stackDepth = TASK_IIC_SIZE,
    .thrdname = "u8g2"
};

STATIC u8g2_t u8g2;

/***********************************************************
***********************function define**********************
***********************************************************/

STATIC uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    // TAL_PR_DEBUG("msg: %d arg_int: %d", msg, arg_int);
    TUYA_GPIO_BASE_CFG_T scl_pin_cfg = {
            .mode = TUYA_GPIO_PUSH_PULL,
            .direct = TUYA_GPIO_OUTPUT,
            .level = TUYA_GPIO_LEVEL_LOW
        };
        TUYA_GPIO_BASE_CFG_T sda_pin_cfg = {
            .mode = TUYA_GPIO_PUSH_PULL,
            .direct = TUYA_GPIO_OUTPUT,
            .level = TUYA_GPIO_LEVEL_LOW
        };
            
    switch(msg)
    {
        case U8X8_MSG_GPIO_AND_DELAY_INIT:
            /* only support for software I2C*/ 
            tkl_gpio_init(SSD1306_SCL_PIN, &scl_pin_cfg);
            tkl_gpio_init(SSD1306_SDA_PIN, &sda_pin_cfg);
            break;

        case U8X8_MSG_DELAY_NANO:
            /* not required for SW I2C */
            break;

        case U8X8_MSG_DELAY_10MICRO:
            /* not used at the moment */
            break;

        case U8X8_MSG_DELAY_100NANO:
            /* not used at the moment */
            break;

        case U8X8_MSG_DELAY_MILLI:
            // delay_micro_seconds(arg_int*1000UL);
            break;

        case U8X8_MSG_DELAY_I2C:
            // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
            // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
            for (uint16_t n = 0; n < (arg_int<=2?160:40); n++)
            {
                __asm__ volatile("nop");
            }            
            break;
    
        case U8X8_MSG_GPIO_I2C_CLOCK:
            // arg_int=0: Output low at I2C clock pin
            // arg_int=1: Input dir with pullup high for I2C clock pin
            if ( arg_int == 0 )
            {
                tkl_gpio_write(SSD1306_SCL_PIN, TUYA_GPIO_LEVEL_LOW);
            }
            else
            {
                tkl_gpio_write(SSD1306_SCL_PIN, TUYA_GPIO_LEVEL_HIGH);
            }
            break;

        case U8X8_MSG_GPIO_I2C_DATA:
            // arg_int=0: Output low at I2C data pin
            // arg_int=1: Input dir with pullup high for I2C data pin
            if ( arg_int == 0 )
            {
                tkl_gpio_write(SSD1306_SDA_PIN, TUYA_GPIO_LEVEL_LOW);
            }
            else
            {
                tkl_gpio_write(SSD1306_SDA_PIN, TUYA_GPIO_LEVEL_HIGH);
            }
            break;

        default:
            break;
    }

    return 1;
}

STATIC VOID draw(u8g2_t *u8g2)
{
    u8g2_SetFontMode(u8g2, 1);	// Transparent
    u8g2_SetFontDirection(u8g2, 0);
    u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
    u8g2_DrawStr(u8g2, 0, 30, "U");
    
    u8g2_SetFontDirection(u8g2, 1);
    u8g2_SetFont(u8g2, u8g2_font_inb30_mn);
    u8g2_DrawStr(u8g2, 21,8,"8");
        
    u8g2_SetFontDirection(u8g2, 0);
    u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
    u8g2_DrawStr(u8g2, 51,30,"g");
    u8g2_DrawStr(u8g2, 67,30,"\xb2");
    
    u8g2_DrawHLine(u8g2, 2, 35, 47);
    u8g2_DrawHLine(u8g2, 3, 36, 47);
    u8g2_DrawVLine(u8g2, 45, 32, 12);
    u8g2_DrawVLine(u8g2, 46, 33, 12);
  
    u8g2_SetFont(u8g2, u8g2_font_4x6_tr);
    u8g2_DrawStr(u8g2, 1,54,"github.com/olikraus/u8g2");
}

/**
* @brief u8g2_task
*
* @return none
*/
VOID u8g2_task(VOID* param)
{
    u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay);   // init u8g2 structure
    u8g2_InitDisplay(&u8g2);            // send init sequence to the display, display is in sleep mode after this,
    u8g2_SetPowerSave(&u8g2, 0);        // wake up display 

    while(1)
    {
        u8g2_FirstPage(&u8g2);
        do
        {
            draw(&u8g2);
        } while (u8g2_NextPage(&u8g2));

        tal_system_sleep(5000);
     }
}

/**
* @brief u8g2_demo
*
* @return none
*/
VOID u8g2_demo(VOID)
{
    OPERATE_RET rt = OPRT_OK;

    TUYA_CALL_ERR_LOG(tal_thread_create_and_start(&sg_u8g2_handle, NULL, NULL, u8g2_task, NULL, &sg_task));
}
U8g2.jpg

示例工程

将 tuyaos_demo_oled_u8g2.zip

tuyaos_demo_oled_u8g2.zip
(9.59 MiB) Downloaded 131 times

解压后放在 tuyaos开发框架对应apps目录下,即可开始编译。
运行前修改 SSD1306 对应 I2C 接口对应的GPIO。

Code: Select all

#define SSD1306_SCL_PIN             TUYA_GPIO_NUM_20
#define SSD1306_SDA_PIN             TUYA_GPIO_NUM_22

Re: TuyaOS T2-U开发板驱动ssd1306并成功移植u8g2

Posted: 2024年 Oct 25日 11:18
by xiebulai

你好,我这个线都接对的,然后代码中引脚也改了,为啥显示屏都不亮,我也是用的4线的OLED