.ACE彭洪权 · 2022年01月10日

【XR806开发板试用】XR806移植U8G2到128*64单色屏基于硬件IIC

XR806移植U8G2到128*64单色屏基于硬件IIC

一、准备工作

  1. 能正常编译通过的环境
  2. https://github.com/olikraus/u8g2 下载u8g2源码
  3. 下载单色屏的示例代码,淘宝商家那里找

二、移植开始

  1. 参考 https://blog.csdn.net/qq_43862401/article/details/121809470
  2. 在hello_demo一顿瞎比操作,oled目录是调试屏幕时候使用的淘宝代码,u8g2_lib是u8g2图形库代码,工程目录如下: title=
  3. ohosdemo/BUILD.gn 内容如下:

    group("ohosdemo") {
     deps = [
         "hello_demo:app_hello",
         #"iot_peripheral:app_peripheral",
         #"wlan_demo:app_WlanTest",
     ]
    }
    
  4. 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",
     ]
    }
    
  5. 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);
    
  6. 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字节是写命令,后面的是写数据

  7. 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你们是怎么添加的,我是一个一个添加上去的,还怕添加漏了,人都干废了,如果几百个源文件,需要怎么操作呢?

  8. 最终的移植结果就是上面的代码,主要是参考别的大佬移植到STM32的文章,然后自己一步一步经过艰苦的调试,终于成功了

三、效果展示

没有视频,毕竟没做效果,只是移植图形库
效果1.jpg

四、最后说个事

为什么这个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)
推荐阅读
关注数
13820
内容数
140
全志XR806开发板相关的知识介绍以及应用专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息