u8g2 SSD1306(I2C) for Z-Stack

来源:互联网 发布:飞翔软件下载器 编辑:程序博客网 时间:2024/05/22 11:30

手中有块SSD1306 128x64的OLED显示屏幕,使用的是I2C模式驱动。现在想让其的能够在Z-Stack CC2530 驱动OLED显示。要让CC2530驱动OLED显示,需要实现:

  1. 实现CC2530 I2C驱动
  2. 移植U8G2显示库。

1. 实现CC2530 I2C驱动

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

2. 移植U8G2显示库

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函数

uint8_t u8x8_byte_UltraIto_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr){    uint8_t *data;  switch(msg)  {case U8X8_MSG_BYTE_SEND:            data = (uint8_t *)arg_ptr;            HalI2CSendByte(data, arg_int);//发送数据  break;case U8X8_MSG_BYTE_INIT:  HalI2CInit();//I2C初始化  break;case U8X8_MSG_BYTE_SET_DC:  break;case U8X8_MSG_BYTE_START_TRANSFER:            HalI2cStart(u8x8_GetI2CAddress(u8x8));//发送开始信号及发送设备地址  break;case U8X8_MSG_BYTE_END_TRANSFER:  HalI2CStop();//发送停止信号  break;default:  return 0;  }  return 1;}

其中I2C的控制逻辑都在都在CC2530 hal_i2c.c中实现的。


  • 在u8x8.h中声明该函数

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.cRevised:        $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