Neza-D1开发板学习之I2C-OLED篇
Neza-D1开发板扩展IO上引出了I2C2,从原理图上看,已经接了PCF8574@38了,总线速度400K,我们的OLED也是接在这上边的,由于这屏幕比较小,显示不了多少东西,就不用FB方式了,直接在应用层操作OLED,所以设备树也不需要配置
在应用层操作就跟单片机操作是一样的了,这里为了方便操作屏幕,我分辨率移植u8g2这个库,我手里的哦了的是1.3”的,驱动IC是SHT1106,用1306也可以,只能显示不满屏,可能是基地址定义的不一样
我们不需要从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); }
移植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;
}这就移植完了,下边编译一下传到开发板里,可以看到显示成功
最后附上完整工程