引言
本文主要介绍如何在 OpenHarmony3.2的基础上开发IIC接口的OLED显示屏的不同显示效果。
目前网络上有关鸿蒙嵌入式方面的参考文章比较少,大多为HarmonyOS 1.0的版本,现在随着HarmonyOS的逐渐发展壮大,稳定版本的OpenHarmony已经到了OpenHarmony 3.2,很多以前的API已经不再适用,所以本文将详细介绍如何开发基于 OpenHarmony3.2的IIC接口的OLED显示。
软硬件准备
硬件
润和HiSpark 3861开发板
IIC接口的OLED显示屏
软件
VSCode
DevEco Device Tool
OpenHarmony-v3.2-Release版本源码
功能介绍
使用IIC接口的OLED显示屏显示字符串"HarmonyOS"
使用IIC接口的OLED显示屏显示不同字号的字符串"HarmonyOS"
使用IIC接口的OLED显示屏显示中文“鸿蒙嵌入式”
功能开发
创建工程并获取源码
在VSCode中通过DevEco Device Tool创建OpenHarmony工程,本项目选用目前最新的稳定版本OpenHarmony-v3.2-Release 。SOC选用Hi3861,开发板会自动选择hi3861,路径根据自己实际情况选择即可。
工程配置完成后,点击确定,DevEco Device Tool会自动启动OpenHarmony3.2源码的下载。
确定项目结构
在applications/sample/wifi-iot/app下创建文件夹OLED,在新建的文件夹下,放置我们的程序文件,主要为七个文件,分别是OLED.c、OLED.h、OLED_fonts.c、OLED_fonts.h、OLED_demo.c、OLED_conf.h和BUILD.gn。项目结构如下:
.
└── applications
└── sample
└── wifi-iot
└── app
└── OLED
│── OLED.c
│── OLED.h
│── OLED_fonts.c
│── OLED_fonts.h
│── OLED_demo.c
│── OLED_conf.h
└── BUILD.gn
实现流程
开启I2C功能
源码默认是关闭I2C功能的,需要我们在程序中手动打开,也就是设置CONFIG_I2C_SUPPORT=y。
修改文件:.device/soc/hisilicon/hi3861v100/sdk_liteos/build/config/usr_config.mk文件。在这个配置文件中打开I2C驱动宏。
取消注释
CONFIG_I2C_SUPPORT=y。
选择IIC 引脚
开发板上OLED显示屏使用的引脚为HI_IO_NAME_GPIO_13 、 HI_IO_NAME_GPIO_14,所以我们需要选择IIC的复用引脚。
在.device/soc/hisilicon/hi3861v100/sdk_liteos/app/wifiiot_app/init/app_io_init.c中,替换两行代码。
将
hi_io_set_func(HI_IO_NAME_GPIO_0, HI_IO_FUNC_GPIO_0_I2C1_SDA);
hi_io_set_func(HI_IO_NAME_GPIO_1, HI_IO_FUNC_GPIO_1_I2C1_SCL);
替换为
hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA);
hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL);
这样我们以后编程都可以直接使用HarmonyOS提供的抽象层函数了,不必每次都要定义IIC的IO复用引脚。
重要程序介绍
发送数据到OLED,驱动OLED其实就是通过IIC的发送,写入对应指令,来达到控制OLED显示的作用。
实际发送IIC的函数
static uint32_t
OLED
_SendData(uint8_t* data, size_t size)
{
int id =
OLED
_I2C_IDX;
return IoTI2cWrite(id,
OLED
_I2C_ADDR, data, size);
}
发送单个字节
static uint32_t
OLED
_WiteByte(uint8_t regAddr, uint8_t byte)
{
uint8_t buffer[] = {regAddr, byte};
return
OLED
_SendData(buffer, sizeof(buffer));
}
发送指令
void
OLED
_WriteCommand(uint8_t byte) {
OLED
_WiteByte(
OLED
_CTRL_CMD, byte);
}
发送不定长数据
void
OLED
_WriteData(uint8_t* buffer, size_t buff_size) {
uint8_t data[
OLED
_WIDTH * 2] = {0};
for (size_t i = 0; i < buff_size; i++) {
data[i*2] =
OLED
_CTRL_DATA |
OLED
_MASK_CONT;
data[i*2+1] = buffer;
}
data[(buff_size - 1) * 2] =
OLED
_CTRL_DATA;
OLED
_SendData(data, sizeof(data));
}
设定当前位置,我们为了设定显示位置,所以需要设置指针的位置。
void
OLED
_SetCursor(uint8_t x, uint8_t y) {
OLED
.CurrentX = x;
OLED
.CurrentY = y;
}
显示字符串
char
OLED
_DrawString(char* str, FontDef Font,
OLED
_COLOR color) {
while (*str) {
if (
OLED
_DrawChar(*str, Font, color) != *str) {
return *str;
}
str++;
}
return *str;
}
在屏幕缓冲区中绘制一个像素
;(也就是绘制一个像素点)
void
OLED
_DrawPixel(uint8_t x, uint8_t y,
OLED
_COLOR color) {
if(x >=
OLED
_WIDTH || y >=
OLED
_HEIGHT) {
return;
}
if(
OLED
.Inverted) {
color = (
OLED
_COLOR)!color;
}
if(color == White) {
OLED
_Buffer[x + (y / 8) *
OLED
_WIDTH] |= 1 << (y % 8);
} else {
OLED
_Buffer[x + (y / 8) *
OLED
_WIDTH] &= ~(1 << (y % 8));
}
}
绘制区域
void
OLED
_DrawRegion(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* data, uint32_t size, uint32_t stride)
{
if (x + w >
OLED
_WIDTH || y + h >
OLED
_HEIGHT || w * h == 0) {
printf("%dx%d @ %d,%d out of range or invalid!\r\n", w, h, x, y);
return;
}
w = (w <=
OLED
_WIDTH ? w :
OLED
_WIDTH);
h = (h <=
OLED
_HEIGHT ? h :
OLED
_HEIGHT);
stride = (stride == 0 ? w : stride);
uint8_t rows = size * 8 / stride;
for (uint8_t i = 0; i < rows; i++) {
uint32_t base = i * stride / 8;
for (uint8_t j = 0; j < w; j++) {
uint32_t idx = base + (j / 8);
uint8_t byte = idx < size ? data[idx] : 0;
uint8_t bit = byte & (0x80 >> (j % 8));
OLED
_DrawPixel(x + j, y + i, bit ? White : Black);
}
}
}
显示中文
首先我们需要对文字取模,有很多取模工具,这里就不做介绍。这里着重介绍软件实现显示中文的效果。character数组存放汉字取模后的16进制数,这里选用字大小为16*16的,所以W和H都赋值为16,二维数组大小设定为32;
void
Oled
Chinese(void)
{
const uint32_t W = 16, H = 16;
uint8_t character[][32] = {
{
0x40,0x20,0x30,0x48,0x10,0xFC,0x02,0x88,0x9F,0xA8,0x64,0x88,0x24,0xA8,0x04,0x90,
0x14,0x84,0x14,0xFE,0xE7,0x04,0x3C,0x24,0x29,0xF4,0x20,0x04,0x20,0x14,0x20,0x08,
},{
0x04,0x48,0x7F,0xFC,0x04,0x40,0x7F,0xFE,0x40,0x02,0x8F,0xE4,0x00,0x00,0x7F,0xFC,
0x06,0x10,0x3B,0x30,0x05,0xC0,0x1A,0xA0,0x64,0x90,0x18,0x8E,0x62,0x84,0x01,0x00,
},{
0x01,0x00,0x21,0x08,0x21,0x08,0x3F,0xF8,0x22,0x28,0x22,0x20,0xFF,0x7C,0x22,0x44,
0x22,0xA8,0x22,0x20,0x3E,0x20,0x22,0x20,0x22,0x50,0x22,0x48,0x3E,0x8E,0x21,0x04,
},{
0x04,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x80,0x02,0x80,0x02,0x80,
0x04,0x40,0x04,0x40,0x08,0x20,0x08,0x20,0x10,0x10,0x20,0x10,0x40,0x0E,0x80,0x04,
},
{
0x00,0x80,0x00,0xA0,0x00,0x90,0x00,0x84,0xFF,0xFE,0x00,0x80,0x00,0x80,0x3E,0x80,
0x08,0x80,0x08,0x40,0x08,0x40,0x09,0x20,0x0E,0x22,0x70,0x12,0x20,0x0A,0x00,0x04
}
};
OLED
_Fill(Black);
for (size_t i = 0; i < sizeof(character)/sizeof(character[0]); i++) {
OLED
_DrawRegion(i * W, 0, W, H, character, sizeof(character[0]), W);
}
OLED
_UpdateScreen();
sleep(1);
}
业务函数;这里主要是创建一个OLED显示的demo线程,线程的入口函数为OLEDTaskEntry。
void
OLED
Demo(void)
{
osThreadAttr_t attr;
attr.name = "
OLED
Task";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 10240;
attr.priority = osPriorityBelowNormal7;
if (osThreadNew(
OLED
Task
Entry
, NULL, &attr) == NULL) {
printf("[
OLED
Demo] Falied to create
OLED
Task!\n");
}
}
APP_FEATURE_INIT(
OLED
Demo);
11. OLEDDemo线程入口函数,这里我们首先初始化IIC,初始化OLED,然后令屏幕全黑,方便我们进行后续显示。在while循环中,我们首先显示字号为7x10的字符串HarmonyOS,然后延时一会,显示字号为11x18的字符串HarmonyOS,最后显示中文“鸿蒙嵌入式”。
void OLEDTaskEntry(void* arg)
{
(void) arg;
IoTI2cInit(0, OLED_I2C_BAUDRATE);//初始化IIC
usleep(20*1000);
OLED
_Init();//初始化OLED
while (1) {
OLED
_Fill(Black);//屏幕全黑
OLED
_SetCursor(0, 0);//指针设置在(0,0)
OLED
_DrawString("HarmonyOS", Font_7x10, White);
OLED
_UpdateScreen();
usleep(1000000);
OLED
_Fill(Black);//屏幕全黑
OLED
_SetCursor(0, 0);//指针设置在(0,0)
OLED
_DrawString("HarmonyOS", Font_11x18, White);
OLED
_UpdateScreen();
usleep(1000000);
OLED
_Fill(Black);//屏幕全黑
OLED
_SetCursor(0, 0);//指针设置在(0,0)
OledChinese();
OLED
_UpdateScreen();
usleep(1000000);
}
}
实现效果
显示字号为7x10的字符串HarmonyOS
显示字号为11x18的字符串HarmonyOS
显示汉字“鸿蒙嵌入式”。
总结
本文主要介绍如何通过在 OpenHarmony3.2的基础上开发IIC接口的OLED显示屏的不同显示效果。读者可以参考本文来开发自己的鸿蒙应用,显示符合自身需求的内容。
作者: 跋扈洋, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-3925799.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
文章评论(0条评论)
登录后参与讨论