SH1106OLED模块功能简单,价格便宜。I2C接口通信。
OpenHarmony系统自带I2C通信函数,只要调用就可以了。再使用I2C协议前,先打开 device/hisilicon/hispark_pegasus/sdk_liteos/build/config/usr_config.mk看看I2C设置是否是被注释掉,如果显示是 # CONFIG_I2C_SUPPORT is not set,就修改成CONFIG_I2C_SUPPORT=y。
在程序中设置端口,频率,并启动I2C初始化,如果不报错就初始化成功。
#define SDA_IO_NAME HI_IO_NAME_GPIO_13
#define SDA_IO_FUNC HI_IO_FUNC_GPIO_13_I2C0_SDA
#define SCL_IO_NAME HI_IO_NAME_GPIO_14
#define SCL_IO_FUNC HI_IO_FUNC_GPIO_14_I2C0_SCL
#define I2C_IDX HI_I2C_IDX_0
#define I2C_BAUDRATE 400000
// I2C初始
hi_void I2C_Init(hi_void)
{
hi_io_set_func(SDA_IO_NAME, SDA_IO_FUNC);
hi_io_set_func(SCL_IO_NAME, SCL_IO_FUNC);
if(hi_i2c_init(I2C_IDX, I2C_BAUDRATE) != 0)
{
printf(" [ I2C Init ] Failed! \n");
}
}
I2C写操作,harmony自带I2C操作函数,只要执行就可以,非常简单。
// 写入 1条 指令, addr = 地址, data = 数据
static hi_void SH1106_I2C_Write(hi_u8 addr, hi_u8 data)
{
hi_u8 data_send_buf[2] = {addr, data};
hi_i2c_data sh1106_i2c_data = {0};
sh1106_i2c_data.send_buf = data_send_buf;
sh1106_i2c_data.send_len = 2;
if(hi_i2c_write(SH1106_I2C_IDX, SH1106_ADDR, &sh1106_i2c_data) != 0)
{
printf(" [SH1106 I2C Write] Failed! \n");
}
}
SH1106的初始化,复制样例里的设置就行,一般实际使用中没什么需要再设置的了。
// SH1106 初始化
hi_void SH1106_Init(hi_void)
{
SH1106_I2C_Write(W_CMD, 0xAE);
SH1106_I2C_Write(W_CMD, 0x02);
SH1106_I2C_Write(W_CMD, 0x10);
SH1106_I2C_Write(W_CMD, 0x40);
SH1106_I2C_Write(W_CMD, 0xB0);
SH1106_I2C_Write(W_CMD, 0x81);
SH1106_I2C_Write(W_CMD, 0xCF);
SH1106_I2C_Write(W_CMD, 0xA1);
SH1106_I2C_Write(W_CMD, 0xC8);
SH1106_I2C_Write(W_CMD, 0xA6);
SH1106_I2C_Write(W_CMD, 0xA8);
SH1106_I2C_Write(W_CMD, 0x3F);
SH1106_I2C_Write(W_CMD, 0xAD);
SH1106_I2C_Write(W_CMD, 0x8B);
SH1106_I2C_Write(W_CMD, 0x33);
SH1106_I2C_Write(W_CMD, 0xC8);
SH1106_I2C_Write(W_CMD, 0xD3);
SH1106_I2C_Write(W_CMD, 0x00);
SH1106_I2C_Write(W_CMD, 0xD5);
SH1106_I2C_Write(W_CMD, 0x80);
SH1106_I2C_Write(W_CMD, 0xD9);
SH1106_I2C_Write(W_CMD, 0xF1);
SH1106_I2C_Write(W_CMD, 0xDA);
SH1106_I2C_Write(W_CMD, 0x12);
SH1106_I2C_Write(W_CMD, 0xDB);
SH1106_I2C_Write(W_CMD, 0x40);
SH1106_I2C_Write(W_CMD, 0xA4);
SH1106_I2C_Write(W_CMD, 0xAF);
hi_udelay(100000);
}
根据可能要使用的需求,做了几个功能函数。
// 清画布
hi_void Canvas_Clear(hi_void);
// 画线
hi_void Draw_Line(hi_s32 x1, hi_s32 y1, hi_s32 x2, hi_s32 y2);
// 画圆
hi_void Draw_Circle(hi_s32 cx, hi_s32 cy, hi_s32 cr);
// 画布 转入 缓存
hi_void Canv_Import_Buff(hi_void);
// 输入字符
hi_void Input_Char_6x12(hi_u8 cx, hi_u8 cy, hi_u8 ch);
// 输入字符串
hi_void Input_String_6x12(hi_u8 sx, hi_u8 sy, hi_u8 *str, hi_u8 len);
// 输入汉字
hi_void Input_CHINESE_12x12(hi_u8 cx, hi_u8 cy, hi_u8 *cn);
// 显示 1个 字符
hi_u8 Show_Char_4x8(hi_u8 x, hi_u8 y, hi_u8 c);
// 显示字符串
hi_u8 Show_String_4x8(hi_u8 sx, hi_u8 sy, hi_u8 *str, hi_u8 sl);
输出ASCII字符需要先做字库,用的工具是PCtoLCD2002,字体用Terminal。
PCtoLCD2002设置,主要根据你的sh1106的初始化设置是怎么做的,取模走向试几下就确认方向了。sh1106显示输出是按页输出,列地址自增。所以8个像素高度的字符在1个页里连续显示速度是最快的。首先做一个高效的6x8的字库,做成4x8也是可以的但是字太小了,挨在一起根本看不清楚,所以用6x8。
显示6x12像素字符是使用最舒服的效果:
12字符会有跨页显示的问题,先设置一个显示像素数组,然后把字符点阵数组铺进去,做好跨行处理就行了。
// 输入字符
hi_void Input_Char_6x12(hi_u8 cx, hi_u8 cy, hi_u8 ch)
{
hi_u8 n = ch - 32;
hi_u8 l1 = 0x00;
hi_u8 l2 = 0x00;
hi_u8 l3 = 0x00;
hi_u8 ny = cy / 8;
hi_u8 ly = cy % 8;
for(hi_u8 i=0; i<6; i++)
{
l1 = 0x00;
l2 = 0x00;
l3 = 0x00;
l1 |= char_6x12[n][i] << ly;
l2 |= char_6x12[n][i] >> (8-ly);
l2 |= char_6x12[n][i+6] << ly;
l3 |= char_6x12[n][i+6] >> (8-ly);
buffer[ny][cx+i] |= l1;
buffer[ny+1][cx+i] |= l2;
buffer[ny+2][cx+i] |= l3;
}
}
可以满足任意位置输入字符,但是要考虑不要越出边界。
编辑汉字字符点阵数组显示也就变的很简单。
画线基本是不会用到的功能,但是偶尔线条能更好反应数据信息。
Bresenham画法真是个天才的妙想,我复制了画线画圆法,基本就够一般使用了。
Bresenham画法代码实现非常简单,效率很高。
// 画线 线两端 A点 B点 坐标, 可以任意A点B点 x: 0-127 y: 0-63
hi_void Draw_Line(hi_s32 x1, hi_s32 y1, hi_s32 x2, hi_s32 y2)
{
hi_s32 w = abs(x2 - x1);
hi_s32 h = abs(y2 - y1);
hi_bool b = 0;
if(h > w)
{
b = 1;
Swap(&x1, &y1);
Swap(&x2, &y2);
Swap(&w, &h);
}
hi_s32 ix = 1;
if (x1 > x2)
{
ix = -1;
}
hi_s32 iy = 1;
if (y1 > y2)
{
iy = -1;
}
hi_s32 x = x1, y = y1;
hi_s32 d = h * 2 - w;
hi_s32 m = h * 2;
hi_s32 n = (h - w) * 2;
while (x != x2)
{
if (d < 0)
{
d += m;
} else {
d += n;
y += iy;
}
if (b)
{
canvas[x][y] = 1;
} else {
canvas[y][x] = 1;
}
x += ix;
}
}
结合红外遥控器做了一个例子。
例子源码
链接:https://pan.baidu.com/s/1tI3ua-zvx9tGCxfcWqyKSg?pwd=i27v
提取码:i27v