在玩MAX78000开发板时遇到个小问题,硬件I2C驱动多个设备时,出现了冲突,原因暂时未知。这就有了需要使用模拟I2C驱动OLED屏幕的需求。
硬件准备:MAX78000FTHR开发板,0.96寸SSD1315OLED屏幕。
U8g2 是专为嵌入式设备打造的单色图形库,用于驱动 OLED、LCD 等小尺寸显示屏。这个库让我最心动的是还支持中文显示。
第一步:下载U8g2库。官方代码库https://github.com/olikraus/u8g2,也可从gitee上下载整个项目包。
第二步:新建一个MAX78000项目,这里我使用官方例程GPIO做为基础模版建立了项目。在新项目GPIO下创建文件夹U8g2,然后将下载的u8g2下csrc里部分文件拷贝过来。
再在工程文件中增加一个oled文件夹,一会用来存放初始化oled的代码。
第三步:修改文件。
1、修改MakeFile文件。修改板子配置,将板卡信息改为BOARD ?= FTHR_RevA
添加文件路径,保证后续编译搜索路径。
2、修改U8g2下的u8g2_d_setup.c和u8g2_d_memory.c两个文件
留意这个函数void u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb),最后一个参数是一个回调函数,这个回调函数是我们需要自行实现的方法。
3、实现回调函数。这里参考着这个例程来写这个回调函数。这里我使用了P2_6,P2_7两个管脚做为模拟I2C的口。
#include "mxc_device.h" #include "mxc_delay.h" #include "gpio.h" #include "u8g2.h" #include "u8x8.h" #include "oled.h" #define MXC_GPIO_PORT_SDA MXC_GPIO2 #define MXC_GPIO_PIN_SDA MXC_GPIO_PIN_6 #define MXC_GPIO_PORT_SCL MXC_GPIO2 #define MXC_GPIO_PIN_SCL MXC_GPIO_PIN_7 void oled_init(void) { mxc_gpio_cfg_t gpio_out; /* Setup output pin. */ gpio_out.port = MXC_GPIO_PORT_SDA; gpio_out.mask = MXC_GPIO_PIN_SDA; gpio_out.pad = MXC_GPIO_PAD_NONE; gpio_out.func = MXC_GPIO_FUNC_OUT; MXC_GPIO_Config(&gpio_out); gpio_out.port = MXC_GPIO_PORT_SCL; gpio_out.mask = MXC_GPIO_PIN_SCL; gpio_out.pad = MXC_GPIO_PAD_NONE; gpio_out.func = MXC_GPIO_FUNC_OUT; MXC_GPIO_Config(&gpio_out); } uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch (msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: /* only support for software I2C*/ oled_init(); //初始化GPIO break; case U8X8_MSG_DELAY_NANO: /* not required for SW I2C */ break; case U8X8_MSG_DELAY_10MICRO: /* not used at the moment */ break; case U8X8_MSG_DELAY_100NANO: /* not used at the moment */ break; case U8X8_MSG_DELAY_MILLI: MXC_Delay(arg_int * 1000UL); //毫秒延时 break; case U8X8_MSG_DELAY_I2C: /* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */ MXC_Delay(arg_int <= 2 ? 5 : 1); //微秒延时 break; case U8X8_MSG_GPIO_I2C_CLOCK: if (arg_int == 0) { //MXC_GPIO_OutSet(MXC_GPIO_PORT_SCL, MXC_GPIO_PIN_SCL); // 高电平 MXC_GPIO_OutClr(MXC_GPIO_PORT_SCL, MXC_GPIO_PIN_SCL); // 低电平 } else { MXC_GPIO_OutSet(MXC_GPIO_PORT_SCL, MXC_GPIO_PIN_SCL); // 高电平 //MXC_GPIO_OutClr(MXC_GPIO_PORT_SCL, MXC_GPIO_PIN_SCL); // 低电平 } break; case U8X8_MSG_GPIO_I2C_DATA: if (arg_int == 0) { //MXC_GPIO_OutSet(MXC_GPIO_PORT_SDA, MXC_GPIO_PIN_SDA); // 高电平 MXC_GPIO_OutClr(MXC_GPIO_PORT_SDA, MXC_GPIO_PIN_SDA); // 低电平 } else { MXC_GPIO_OutSet(MXC_GPIO_PORT_SDA, MXC_GPIO_PIN_SDA); // 高电平 //MXC_GPIO_OutClr(MXC_GPIO_PORT_SDA, MXC_GPIO_PIN_SDA); // 低电平 } break; /* case U8X8_MSG_GPIO_MENU_SELECT: u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN)); break; case U8X8_MSG_GPIO_MENU_NEXT: u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN)); break; case U8X8_MSG_GPIO_MENU_PREV: u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN)); break; case U8X8_MSG_GPIO_MENU_HOME: u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN)); break; */ default: u8x8_SetGPIOResult(u8x8, 1); break; } return 1; }
4、写一个初始化函数。
void u8g2_Init(u8g2_t *u8g2) { u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay); u8g2_InitDisplay(u8g2); u8g2_SetPowerSave(u8g2, 0); u8g2_ClearBuffer(u8g2); }
在oled.h文件中做一下函数的声明。
第四步:u8g2的使用。修改main()方法,增加u8g2的定义和使用。
#include <stdio.h> #include <string.h> #include "mxc_device.h" #include "mxc_delay.h" #include "nvic_table.h" #include "pb.h" #include "board.h" #include "gpio.h" #include "u8g2.h" #include "oled.h" #define MXC_GPIO_PORT_OUT MXC_GPIO2 #define MXC_GPIO_PIN_OUT MXC_GPIO_PIN_0 /***** Globals *****/ /***** Functions *****/ u8g2_t u8g2; int main(void) { mxc_gpio_cfg_t gpio_out; u8g2_Init(&u8g2); /* Setup output pin. */ gpio_out.port = MXC_GPIO_PORT_OUT; gpio_out.mask = MXC_GPIO_PIN_OUT; gpio_out.pad = MXC_GPIO_PAD_NONE; gpio_out.func = MXC_GPIO_FUNC_OUT; MXC_GPIO_Config(&gpio_out); u8g2_SetFont(&u8g2, u8g2_font_smart_patrol_nbp_tr); u8g2_SetFontRefHeightText(&u8g2); u8g2_SetFontPosTop(&u8g2); u8g2_DrawStr(&u8g2, 0, 30, "u8g2 Soft I2C"); u8g2_SendBuffer(&u8g2); while (1) { MXC_GPIO_OutSet(gpio_out.port, gpio_out.mask); MXC_Delay(5000000); MXC_GPIO_OutClr(gpio_out.port, gpio_out.mask); MXC_Delay(5000000); } return 0; }
编译、烧录。
至此,移植完成。