TuyaOS T2-U开发板驱动ssd1306并成功移植u8g2
SSD1306介绍
SSD1306 是一款带控制器的 OLED 点阵图形显示系统的单片 CMOS OLED/PLED 驱动器。它由 128 个 列输出 (SEG)和 64 个行输出(COM)组成,该芯片专为共阴极 OLED 面板设计。
SSD1306内置对比度控制器、显示RAM(GDDRAM)和振荡器,以此减少了外部元件的数量和功耗。该芯片有256级亮度控制。数据或命令由通用微控制器通过硬件选择的6800/8000系通用并行接口、I2C接口或 SPI发送。该芯片适用于许多小型便携式应用,如手机副显示屏、MP3播放器和计算器等。
特性:
- 分辨率: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上拉电阻。
U8g2
U8g2 是一个用于嵌入式设备的简易图形库,可以在多种 OLED 和 LCD 屏幕上,支持包括 SSD1306 等多种类型的底层驱动,并可以很方便地移植到 Arduino 、树莓派和 ARM 上。
U8g2 库的 GitHub 地址为:https://github.com/olikraus/u8g2 ,可以从中获取到源码与文档帮助。
移植
U8g2 移植比较简单,U8g2 自带了软件 I2C 通讯,适配层完成:
- gpio 初始化及 I2C对应的 SCL 和 SDA 操作
- 延时控制
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));
}
示例工程
将 tuyaos_demo_oled_u8g2.zip
解压后放在 tuyaos开发框架对应apps目录下,即可开始编译。
运行前修改 SSD1306 对应 I2C 接口对应的GPIO。
Code: Select all
#define SSD1306_SCL_PIN TUYA_GPIO_NUM_20
#define SSD1306_SDA_PIN TUYA_GPIO_NUM_22