手中有块SSD1306 128x64的OLED显示屏幕,使用的是I2C模式驱动。现在想让其的能够在Z-Stack CC2530 驱动OLED显示。要让CC2530驱动OLED显示,需要实现:
实现CC2530 I2C驱动移植U8G2显示库。CC2530芯片上面并没有I2C控制器,所以只能使用IO口模拟的方式模拟I2C的控制时序。并且Ti提供RemoTI协议栈中已经实现好了I2C控制逻辑(hal_i2c.h,hal_i2c.c),或者自己实现I2C控制逻辑。自己实现I2C控制时序时,需要参考SSD1306数据手册[8.1.5 MCU I2C Interface 及14AC CHARACTERISTICS 中的I2C interface Timing characteristics],注意I2C上各种时序的要求。
I2C文件下载地址:http://download.csdn.net/detail/oxp7085915/9895098
u8g2是一个开源的嵌入式显示库,其功能非常强大,最小只占128Byte内存,可以显示文字,图片,几何图形等。并且支持非常多的显示屏。SSD1306就是其支持的一款OLED显示屏幕。
开源地址 https://github.com/olikraus/u8g2
WIKI https://github.com/olikraus/u8g2/wiki
u8g2将已C-library的方式提供给Z-Stack调用。将代码下载到本地,主要修改的目录位于csrc目录下。
移植u8g2需要实现需要实现两个步骤:
1、实现u8x8_Setup中byte_cb回调函数,该函数主要用于调用I2C驱动接口对SSD1306进行初始化和读写数据
在u8x8_byte.c中增加u8x8_byte_UltraIto_sw_i2c函数其中I2C的控制逻辑都在都在CC2530 hal_i2c.c中实现的。
uint8_t u8x8_byte_UltraIto_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
2、实现u8x8_Setup中gpio_and_delay_cb回调函数,控制GPIO的逻辑和延时
由于I2C中已经拥有了GPIO的控制及延时逻辑,所以在gpio_and_delay_cb,值用定义一个空函数结构就可以了。 创建u8x8cb.c/u8x8cb.h文件,并在.c文件中实现gpio_and_delay_cb函数,在.h中声明gpio_and_delay_cb函数。
#include "chip.h" #include "delay.h" #include "u8x8.h" uint8_t u8x8_gpio_and_delay_Ultriot(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*/ 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: //delay_micro_seconds(arg_int*1000UL); break; case U8X8_MSG_DELAY_I2C: /* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */ // delay_micro_seconds(arg_int<=2?5:1); break; case U8X8_MSG_GPIO_I2C_CLOCK: break; case U8X8_MSG_GPIO_I2C_DATA: 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; }3、测试
打开自己的Z-Stack工程,生成的u8g2库加入到工程文件中,同时将u8g2.h、u8x8.h、u8x8cb.h、u8x8cb.c、库文件放到一个文件中,并配置IAR环境变量,让IAR能够找到库和u8g2头文件的路径地址。将hal_i2c.c/hal_i2c.h添加到Z-stack工程。在Components\hal\target中创建hal_oled.c/hal_oled.h
hal_oled.c:
/************************************************************************************************** Filename: hal_oled.c Revised: $Date: 2012-09-30 16:36:36 -0700 (Sun, 30 Sep 2012) $ Revision: $Revision: 31658 $ Description: This file contains the interface to the HAL oled Service. **************************************************************************************************/ /************************************************************************************************** * INCLUDES **************************************************************************************************/ #include "hal_types.h" #include "hal_oled.h" #include "OSAL.h" #include "OnBoard.h" #include "hal_assert.h" #include "hal_i2c.h" #include "u8x8.h" #include "u8g2.h" #include "u8x8cb.h" #if defined (ZTOOL_P1) || defined (ZTOOL_P2) #include "DebugTrace.h" #endif #if (HAL_OLED == TRUE) u8g2_t u8g2; #endif /************************************************************************************************** * CONSTANTS **************************************************************************************************/ /************************************************************************************************** * MACROS **************************************************************************************************/ /************************************************************************************************** * LOCAL VARIABLES **************************************************************************************************/ /************************************************************************************************** * FUNCTIONS - API **************************************************************************************************/ void HalOledInit(void) { #if (HAL_OLED == TRUE) u8g2_Setup_ssd1306_i2c_128x64_noname_1(&u8g2, U8G2_R0, u8x8_byte_UltraIto_sw_i2c, u8x8_gpio_and_delay_Ultriot); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); u8g2_SetFont(&u8g2, u8g2_font_6x12_tr); u8g2_FirstPage(&u8g2); do { u8g2_DrawStr(&u8g2, 0,15,"UltraIot"); u8g2_SendBuffer(&u8g2); } while( u8g2_NextPage(&u8g2) ); #endif } /************************************************************************************************** **************************************************************************************************/ 在hal_board_cfg.h中定义HAL_OLED宏 #ifndef HAL_OLED #define HAL_OLED TRUE #endif 在HalDriverInit()中初始化OLED #if (defined HAL_OLED) && (HAL_OLED==TRUE) HalOledInit(); #endif