在玩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;
}编译、烧录。

至此,移植完成。
27

