XR806移植U8G2到128*64单色屏基于硬件IIC
一、准备工作
- 能正常编译通过的环境
- https://github.com/olikraus/u8g2 下载u8g2源码
- 下载单色屏的示例代码,淘宝商家那里找
二、移植开始
- 参考 https://blog.csdn.net/qq_43862401/article/details/121809470
- 在hello_demo一顿瞎比操作,oled目录是调试屏幕时候使用的淘宝代码,u8g2_lib是u8g2图形库代码,工程目录如下:
ohosdemo/BUILD.gn 内容如下:
group("ohosdemo") { deps = [ "hello_demo:app_hello", #"iot_peripheral:app_peripheral", #"wlan_demo:app_WlanTest", ] }
hello_demo/BUILD.gn 内容如下:
import("//device/xradio/xr806/liteos_m/config.gni") static_library("app_hello") { configs = [] sources = [ "src/main.c", "src/test_i2c.c", ] cflags = board_cflags include_dirs = board_include_dirs include_dirs += [ "//kernel/liteos_m/kernel/arch/include", "include", "src/oled", "src/u8g2_lib", "//base/iot_hardware/peripheral/interfaces/kits", ] deps = [ "src:bsp_display", ] }
main.c 内容如下:
#include <stdio.h> #include "ohos_init.h" #include "kernel/os/os.h" #include "test_i2c.h" static OS_Thread_t g_main_thread; static void MainThread(void *arg) { IotI2CTest(); while (1) { printf("hello world!\n"); LOS_Msleep(1000); } } void HelloTestMain(void) { printf("Wifi Test Start\n"); if (OS_ThreadCreate(&g_main_thread, "MainThread", MainThread, NULL, OS_THREAD_PRIO_APP, 50 * 1024) != OS_OK) { printf("[ERR] Create MainThread Failed\n"); } } SYS_RUN(HelloTestMain);
test_i2c.c 内容如下:
#include <stdio.h> #include <string.h> #include "kernel/os/os.h" #include "iot_i2c.h" #include "oled.h" #include "u8g2.h" uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); uint8_t u8g2_gpio_and_delay_stm32(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr); void delay_ms(uint32_t ms); void IotI2CTest(void) { OLED_Init(); OLED_Clear(); OLED_ShowCHinese(0,0,0); OLED_ShowCHinese(18,0,1); OLED_ShowCHinese(36,0,2); OLED_ShowCHinese(54,0,3); OLED_ShowCHinese(72,0,4); OLED_ShowCHinese(90,0,5); OLED_ShowCHinese(108,0,6); u8g2_t u8g2; u8g2_Setup_sh1106_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_hw_i2c, u8g2_gpio_and_delay_stm32); //u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); u8g2_ClearDisplay(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_wqy16_t_chinese1); u8g2_DrawCircle(&u8g2, 55, 30, 5, U8G2_DRAW_ALL); u8g2_DrawCircle(&u8g2, 65, 30, 5, U8G2_DRAW_ALL); u8g2_DrawCircle(&u8g2, 75, 30, 5, U8G2_DRAW_ALL); u8g2_DrawUTF8(&u8g2, 20, 50, "你好, XR806!"); u8g2_SendBuffer(&u8g2); } uint8_t u8g2_gpio_and_delay_stm32(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr) { switch(msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: break; case U8X8_MSG_DELAY_MILLI: delay_ms(arg_int); break; default: return 0; } return 1; } uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { static uint8_t buffer[131]; /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */ static uint8_t buf_idx; uint8_t *data; switch(msg) { case U8X8_MSG_BYTE_SEND: data = (uint8_t *)arg_ptr; while( arg_int > 0 ) { buffer[buf_idx++] = *data; data++; arg_int--; } break; case U8X8_MSG_BYTE_INIT: /* add your custom code to init i2c subsystem */ break; case U8X8_MSG_BYTE_START_TRANSFER: buf_idx = 0; break; case U8X8_MSG_BYTE_END_TRANSFER: if (buf_idx != 132) { for (uint8_t i = 0; i < buf_idx; i++) { OLED_WR_Byte(buffer[i], OLED_CMD); } } else { for (uint8_t i = 1; i < 4; i++) { OLED_WR_Byte(buffer[i], OLED_CMD); } for (uint8_t i = 4; i < buf_idx; i++) { OLED_WR_Byte(buffer[i], OLED_DATA); } } break; default: return 0; } return 1; } void delay_ms(uint32_t ms) { uint16_t i, j; for (i = 0; i < ms; i++) { for (j = 0; j < 10; j++) { __asm("nop"); } } }
这里要说几个事:
1、没有使用u8g2_InitDisplay(&u8g2);初始化寄存器,好像值不对
2、移植U8X8_MSG_BYTE_END_TRANSFER分支的时候,发现不能区分是数据还是命令,我不知道其他大佬是怎么实现的,或者u8g2库有实现,但是我自己没找到使用方法,我的取巧:不是132长度的数据一律是写命令,132长度的1 2 3字节是写命令,后面的是写数据src/BUILD.gn 内容如下
static_library("bsp_display") { sources = [ "oled/oled.c", "u8g2_lib/mui.c", "u8g2_lib/mui_u8g2.c", "u8g2_lib/u8g2_bitmap.c", "u8g2_lib/u8g2_box.c", "u8g2_lib/u8g2_buffer.c", "u8g2_lib/u8g2_button.c", "u8g2_lib/u8g2_circle.c", "u8g2_lib/u8g2_cleardisplay.c", "u8g2_lib/u8g2_d_memory.c", "u8g2_lib/u8g2_d_setup.c", "u8g2_lib/u8g2_font.c", "u8g2_lib/u8g2_fonts.c", "u8g2_lib/u8g2_hvline.c", "u8g2_lib/u8g2_input_value.c", "u8g2_lib/u8g2_intersection.c", "u8g2_lib/u8g2_kerning.c", "u8g2_lib/u8g2_line.c", "u8g2_lib/u8g2_ll_hvline.c", "u8g2_lib/u8g2_message.c", "u8g2_lib/u8g2_polygon.c", "u8g2_lib/u8g2_selection_list.c", "u8g2_lib/u8g2_setup.c", "u8g2_lib/u8log.c", "u8g2_lib/u8log_u8g2.c", "u8g2_lib/u8log_u8x8.c", "u8g2_lib/u8x8_8x8.c", "u8g2_lib/u8x8_byte.c", "u8g2_lib/u8x8_cad.c", "u8g2_lib/u8x8_capture.c", "u8g2_lib/u8x8_d_a2printer.c", "u8g2_lib/u8x8_d_ssd1306_128x64_noname.c", "u8g2_lib/u8x8_debounce.c", "u8g2_lib/u8x8_display.c", "u8g2_lib/u8x8_fonts.c", "u8g2_lib/u8x8_gpio.c", "u8g2_lib/u8x8_input_value.c", "u8g2_lib/u8x8_message.c", "u8g2_lib/u8x8_selection_list.c", "u8g2_lib/u8x8_setup.c", "u8g2_lib/u8x8_string.c", "u8g2_lib/u8x8_u16toa.c", "u8g2_lib/u8x8_u8toa.c", ] include_dirs = [ "//utils/native/lite/include", "//kernel/liteos_m/components/bounds_checking_function/include", "//kernel/liteos_m/kernel/include", "//kernel/liteos_m/utils", "//kernel/liteos_m/kal/cmsis", "//base/iot_hardware/peripheral/interfaces/kits", ] }
大佬们,这里问一句,这么多.c你们是怎么添加的,我是一个一个添加上去的,还怕添加漏了,人都干废了,如果几百个源文件,需要怎么操作呢?
- 最终的移植结果就是上面的代码,主要是参考别的大佬移植到STM32的文章,然后自己一步一步经过艰苦的调试,终于成功了
三、效果展示
没有视频,毕竟没做效果,只是移植图形库
四、最后说个事
为什么这个markdown会自动给我把'_'前面加一个'\',知道的大佬说说。PS:每次编辑都有新的事故,头秃。
....................................................................................................................................
补充:IIC忘记贴了
写命令 写数据
unsigned int i2c_id = 0;
unsigned char i2c_device_add = I2C_DEVICE_ADDR;
void Write_IIC_Command(unsigned char IIC_Command)
{
uint8_t buff[3] = {0x00};
buff[1] = IIC_Command;
// IIC_Start();
// Write_IIC_Byte(0x78); //Slave address,SA0=0
// Write_IIC_Byte(0x00); //write command
// Write_IIC_Byte(IIC_Command);
// IIC_Stop();
IoTI2cWrite(i2c_id, i2c_device_add, buff, 2);
}
void Write_IIC_Data(unsigned char IIC_Data)
{
uint8_t buff[3] = {0x40};
buff[1] = IIC_Data;
// IIC_Start();
// Write_IIC_Byte(0x78); //D/C#=0; R/W#=0
// Write_IIC_Byte(0x40); //write data
// Write_IIC_Byte(IIC_Data);
// IIC_Stop();
IoTI2cWrite(i2c_id, i2c_device_add, buff, 2);
}
初始化
IoTI2cInit(i2c_id, I2C_SPEED);
宏定义
#define I2C_SPEED (400000)
#define I2C_DEVICE_ADDR (0x3C)