1. Neza-D1开发板扩展IO上引出了I2C2,从原理图上看,已经接了PCF8574@38了,总线速度400K,我们的OLED也是接在这上边的,由于这屏幕比较小,显示不了多少东西,就不用FB方式了,直接在应用层操作OLED,所以设备树也不需要配置

  2. 在应用层操作就跟单片机操作是一样的了,这里为了方便操作屏幕,我分辨率移植u8g2这个库,我手里的哦了的是1.3”的,驱动IC是SHT1106,用1306也可以,只能显示不满屏,可能是基地址定义的不一样

  3. 我们不需要从OLED读取数据,所以只需要实现I2C写函数就可以,注意OLED模块上标的地址是0x78,这个是8位地址,这里使用的是7位地址,右移一位所以是0x3C

     unsigned char i2c_init()
     {
         const char *i2c_dev = "/dev/i2c-2";
         fd = open(i2c_dev, O_RDWR);
         if (fd < 0)
         {
             printf("not have /dev/i2c-2 t\r\n");
             fflush(stdout);
             return -1;
         }
         return 0;
     }
     // I2C Addr 7bit
     unsigned char base_i2c_write(unsigned char device_addr, unsigned char *buff, int num)
     {
    
         struct i2c_rdwr_ioctl_data data;
         struct i2c_msg msgs_str[1];
         data.msgs = msgs_str;
         data.nmsgs = 1;
         data.msgs[0].len = num;
         data.msgs[0].addr = device_addr;
         data.msgs[0].flags = 0;
         data.msgs[0].buf = buff;
         ioctl(fd, I2C_RDWR, (unsigned long)&data);
     }
    
  4. 移植u8g2 非常简单,只需修改这下边这个函数里初始化位置和写数据位置就行,另外一个是延时,可以不用修改
    uint8_t u8x8_byte_hw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void arg_ptr)
    {
    /
    u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
    static uint8_t buffer[128];
    static uint8_t buf_idx;
    uint8_t data;

    switch (msg)
    {
    case U8X8_MSG_BYTE_INIT:
    {
    /
    add your custom code to init i2c subsystem */
    i2c_init; // I2C初始化
    }
    break;

    case U8X8_MSG_BYTE_START_TRANSFER:
    {
    buf_idx = 0;
    }
    break;

    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_END_TRANSFER:
    {
    //i2c写函数
    if (base_i2c_write(OLED_ADDRESS, buffer, buf_idx) != 0)
    return 0;
    }
    break;

    case U8X8_MSG_BYTE_SET_DC:
    break;

    default:
    return 0;
    }

    return 1;
    }

    uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void arg_ptr)
    {
    switch (msg)
    {
    case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
    break;
    case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
    break;
    case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
    break;
    case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
    break; // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
    case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
    break; // arg_int=1: Input dir with pullup high for I2C clock pin
    case U8X8_MSG_GPIO_I2C_DATA: // arg_int=0: Output low at I2C data pin
    break; // arg_int=1: Input dir with pullup high for I2C data pin
    case U8X8_MSG_GPIO_MENU_SELECT:
    u8x8_SetGPIOResult(u8x8, /
    get menu select pin state / 0);
    break;
    case U8X8_MSG_GPIO_MENU_NEXT:
    u8x8_SetGPIOResult(u8x8, /
    get menu next pin state / 0);
    break;
    case U8X8_MSG_GPIO_MENU_PREV:
    u8x8_SetGPIOResult(u8x8, /
    get menu prev pin state / 0);
    break;
    case U8X8_MSG_GPIO_MENU_HOME:
    u8x8_SetGPIOResult(u8x8, /
    get menu home pin state */ 0);
    break;
    default:
    u8x8_SetGPIOResult(u8x8, 1); // default return value
    break;
    }
    return 1;
    }

  5. 这就移植完了,下边编译一下传到开发板里,可以看到显示成功

  6. 最后附上完整工程