G
N
I
D
A
O
L

STM8驱动SPI接口OLED

由于中景园电子给出的例程不够全面,因此特地花时间重新整理了一下代码,并加上了其他的功能。本文记录了使用模拟四线 SPI 协议驱动 OLED 的代码。

使用软件:IAR FOR STM8

编程方式:固件库

硬件配套:STM8S105C6T6实验板

字模软件:PCtoLCD2002

图片转位图(bmp)格式软件:image2lcd

image

1 oled.h

#ifndef __OLED_SPI_H
#define __OLED_SPI_H

/*******************模拟四线 SPI 驱动 0.96寸OLED(128x64)**********************/

/* Includes ------------------------------------------------------------------*/

#include "stm8s.h"
#include "oled_font.h"

/* Enum ----------------------------------------------------------------------*/

enum page_num {PAGE0 = 0, PAGE1, PAGE2, PAGE3, PAGE4, PAGE5, PAGE6, PAGE7};
enum roll_frame {FRAME0 = 0, FRAME1, FRAME2, FRAME3, FRAME4, FRAME5, FRAME6, FRAME7};

/* Defines -------------------------------------------------------------------*/

#define OLED_CMD            0u          /* 命令模式 */
#define OLED_DATA           1u          /* 数据模式 */

#define OLED_CATHODE        0u          /* 阴码 */
#define OLED_ANODE          1u          /* 阳码 */

#define OLED_FONT_SIZE_12       12
#define OLED_FONT_SIZE_16       16

#define OLED_SCROLL_RIGHT      0u
#define OLED_SCROLL_LEFT       1u

#define OLED_SCK_PORT           (GPIOB) 
#define OLED_SCK_PIN            (GPIO_PIN_5) /* PB5 (OLED_D0)  */

#define OLED_SDA_PORT           (GPIOB) 
#define OLED_SDA_PIN            (GPIO_PIN_4) /* PB4 (OLED_D1)  */

#define OLED_RES_PORT           (GPIOD) 
#define OLED_RES_PIN            (GPIO_PIN_0) /* PD0 (OLED_RES) */

#define OLED_DC_PORT            (GPIOG) 
#define OLED_DC_PIN             (GPIO_PIN_1) /* PG1 (OLED_DC)  */

#define OLED_CS_PORT            (GPIOC) 
#define OLED_CS_PIN             (GPIO_PIN_6) /* PC6 (OLED_CS)  */

#define OLED_SCK_LOW()         GPIO_WriteLow (OLED_SCK_PORT, OLED_SCK_PIN)
#define OLED_SCK_HIGH()        GPIO_WriteHigh(OLED_SCK_PORT, OLED_SCK_PIN)

#define OLED_SDA_LOW()         GPIO_WriteLow (OLED_SDA_PORT, OLED_SDA_PIN)
#define OLED_SDA_HIGH()        GPIO_WriteHigh(OLED_SDA_PORT, OLED_SDA_PIN)

#define OLED_RES_LOW()         GPIO_WriteLow (OLED_RES_PORT, OLED_RES_PIN)
#define OLED_RES_HIGH()        GPIO_WriteHigh(OLED_RES_PORT, OLED_RES_PIN)

#define OLED_DC_CMD()          GPIO_WriteLow (OLED_DC_PORT, OLED_DC_PIN)
#define OLED_DC_DATA()         GPIO_WriteHigh(OLED_DC_PORT, OLED_DC_PIN)

#define OLED_CS_LOW()          GPIO_WriteLow (OLED_CS_PORT, OLED_CS_PIN)
#define OLED_CS_HIGH()         GPIO_WriteHigh(OLED_CS_PORT, OLED_CS_PIN)

/* Functions -----------------------------------------------------------------*/

static void OLED_DLY_ms (uint32_t ms);

static void OLED_SPI_WriteByte (uint8_t mode, uint8_t data);
void OLED_SPI_WriteCmd (uint8_t cmd);
void OLED_SPI_WriteData (uint8_t data);
static void OLED_SPI_GPIO_Init (void);
void OLED_SPI_Init (void);

void OLED_ON (void);
void OLED_OFF (void);

void OLED_Refresh_Gram (void);
void OLED_Clear (void);

static void OLED_DrawPoint (uint8_t x, uint8_t y, uint8_t mode);
static void OLED_Fill (uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode);

static void OLED_ShowChar (uint8_t x, uint8_t y, uint8_t ch, uint8_t size, uint8_t mode);
void OLED_ShowString (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size);

static void OLED_ShowChar_CH (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size, uint8_t mode);
void OLED_ShowChinese (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size, uint8_t num);

void OLED_ShowPic (uint8_t x, uint8_t y, const uint8_t *pic, uint8_t width, uint8_t height, uint8_t mode);

void OLED_VerHorScroll (enum page_num start_page, enum page_num end_page, enum roll_frame frame, uint8_t scroll_offset, uint8_t dir);
void OLED_HorScroll (enum page_num start_page, enum page_num end_page, enum roll_frame frame, uint8_t dir);

#endif /* __OLED_SPI_H */

2 oled.c

根据不同函数的功能,分为以下几类:

2.1 与初始化相关的函数

#include "oled_spi.h"

uint8_t OLED_GRAM[128][8];

/*************************************************************************
                        OLED 专用软件延时函数
--------------------------------------------------------------------------
ms:软件延时长度
*************************************************************************/
static void OLED_DLY_ms (uint32_t ms)
{                         
  uint32_t a;
  
  while (ms)
  {    
    a = 200;
    while (a--);
    ms--;
  }
}

/*************************************************************************
                        往 OLED 中写入一字节数据
--------------------------------------------------------------------------
mode:传输模式  data:一字节数据
*************************************************************************/
static void OLED_SPI_WriteByte (uint8_t mode, uint8_t data)
{
  BitStatus bit;
  uint8_t i;
  
  if (mode == OLED_CMD)
  {
    OLED_DC_CMD();
  }
  else
  {
    OLED_DC_DATA();
  }
  
  OLED_SCK_LOW();
  
  for (i = 0; i < 8; i++)
  {
    OLED_SCK_LOW();
    bit = (BitStatus)(data & 0x80);
    
    if (bit == RESET)
    {
      OLED_SDA_LOW();
    }
    else
    {
      OLED_SDA_HIGH();
    }
    
    OLED_SCK_HIGH();
    data <<= 1;
  }
  
  OLED_SCK_HIGH();
  OLED_DC_DATA();
}

/*************************************************************************
                           往 OLED 写入命令字 
--------------------------------------------------------------------------
cmd:命令字
*************************************************************************/
void OLED_SPI_WriteCmd (uint8_t cmd)
{
  OLED_SPI_WriteByte(OLED_CMD, cmd);
}

/*************************************************************************
                          往 OLED 写入数据字  
--------------------------------------------------------------------------
data:数据字
*************************************************************************/
void OLED_SPI_WriteData (uint8_t data)
{
  OLED_SPI_WriteByte(OLED_DATA, data);
}

/*************************************************************************
                          初始化 OLED 引脚  
--------------------------------------------------------------------------
无参数
*************************************************************************/
static void OLED_SPI_GPIO_Init (void)
{
  GPIO_Init(OLED_SCK_PORT, OLED_SCK_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
  GPIO_Init(OLED_SDA_PORT, OLED_SDA_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
  GPIO_Init(OLED_RES_PORT, OLED_RES_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
  GPIO_Init(OLED_DC_PORT,  OLED_DC_PIN,  GPIO_MODE_OUT_PP_HIGH_FAST);
  GPIO_Init(OLED_CS_PORT,  OLED_CS_PIN,  GPIO_MODE_OUT_PP_HIGH_FAST);
}

/*************************************************************************
                            初始化 OLED 
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_SPI_Init (void)
{
  OLED_SPI_GPIO_Init();
  OLED_CS_LOW();
  
  OLED_SCK_HIGH();
  OLED_RES_LOW();
  OLED_DLY_ms (100);
  OLED_RES_HIGH();
  
  OLED_SPI_WriteCmd(0xAE);         // Display Off (0x00)
  OLED_SPI_WriteCmd(0xD5);
  OLED_SPI_WriteCmd(0x80);         // Set Clock as 100 Frames/Sec
  OLED_SPI_WriteCmd(0xA8);
  OLED_SPI_WriteCmd(0x3F);         // 1/64 Duty (0x0F~0x3F)
  OLED_SPI_WriteCmd(0xD3);
  OLED_SPI_WriteCmd(0x00);         // Shift Mapping RAM Counter (0x00~0x3F)
  OLED_SPI_WriteCmd(0x40 | 0x00);  // Set Mapping RAM Display Start Line (0x00~0x3F)
  OLED_SPI_WriteCmd(0x8D);
  OLED_SPI_WriteCmd(0x10 | 0x04);  // Enable Embedded DC/DC Converter (0x00/0x04)
  OLED_SPI_WriteCmd(0x20);
  OLED_SPI_WriteCmd(0x02);         // Set Page Addressing Mode (0x00/0x01/0x02)
  OLED_SPI_WriteCmd(0xA0 | 0x01);  // Set SEG/Column Mapping    
  OLED_SPI_WriteCmd(0xC0);         // Set COM/x Scan Direction   
  OLED_SPI_WriteCmd(0xDA);
  OLED_SPI_WriteCmd(0x02 | 0x10);  // Set Sequential Configuration (0x00/0x10)
  OLED_SPI_WriteCmd(0x81);
  OLED_SPI_WriteCmd(0xCF);         // Set SEG Output Current
  OLED_SPI_WriteCmd(0xD9);
  OLED_SPI_WriteCmd(0xF1);         // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  OLED_SPI_WriteCmd(0xDB);
  OLED_SPI_WriteCmd(0x40);         // Set VCOM Deselect Level
  OLED_SPI_WriteCmd(0xA4 | 0x00);  // Disable Entire Display On (0x00/0x01)
  OLED_SPI_WriteCmd(0xA6 | 0x00);  // Disable Inverse Display On (0x00/0x01)
  OLED_SPI_WriteCmd(0xAE | 0x01);  // Display On (0x01)
  
  OLED_Clear();         // 清屏
}

初始化 OLED 只需调用:

OLED_SPI_Init();

2.2 唤醒和休眠

/*************************************************************************
                               唤醒 OLED
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_ON (void)
{
  OLED_SPI_WriteCmd(0X8D);  // 设置电荷泵
  OLED_SPI_WriteCmd(0X14);  // 开启电荷泵
  OLED_SPI_WriteCmd(0XAF);  // OLED唤醒
}

/*************************************************************************
                              休眠 OLED
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_OFF (void)
{
  OLED_SPI_WriteCmd(0X8D);  // 设置电荷泵
  OLED_SPI_WriteCmd(0X10);  // 关闭电荷泵
  OLED_SPI_WriteCmd(0XAE);  // OLED休眠
}

2.3 与显示相关的函数

指定位置刷新显示的功能实现有待进一步研究。

注意:不要频繁调用清屏函数 OLED_Clear(),这会导致屏幕刷新过慢或出现重影现象。

/*************************************************************************
                            OLED 刷新显示
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_Refresh_Gram (void)
{   
  uint8_t i, j;
  
  for(i = 0; i < 8; i++)  
  {  
    OLED_SPI_WriteCmd(0xB0 + i);        // 设置页地址(0~7)
    OLED_SPI_WriteCmd(0x00);            // 设置显示位置—列低地址
    OLED_SPI_WriteCmd(0x10);            // 设置显示位置—列高地址 
    
    for(j = 0; j < 128; j++)
    {
      OLED_SPI_WriteData(OLED_GRAM[j][i]);
    }
  }
  
}

/*************************************************************************
                              OLED 清屏
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_Clear (void)
{
  uint8_t i, j;  
    
  for(i = 0; i < 8; i++)
  {
    for(j = 0; j < 128; j++)
    {
      OLED_GRAM[j][i] = 0X00; 
    }
  }
  
  OLED_Refresh_Gram();  // 更新显示
}

/*************************************************************************
                               OLED 画点 
--------------------------------------------------------------------------
x,y:坐标  mode:阳码/阴码填充
*************************************************************************/
static void OLED_DrawPoint (uint8_t x, uint8_t y, uint8_t mode)
{    
  uint8_t pos, bx;
  uint8_t temp = 0;
  
  if (x > 127|| y > 63)         // 超出范围
  {
    return;       
  }
  
  pos = 7 - y / 8;
  bx  = y % 8;
  temp= 1 << (7 - bx);
  
  if (mode == OLED_ANODE)
  {
    OLED_GRAM[x][pos] |= temp;
  }
  else 
  {
    OLED_GRAM[x][pos] &= ~temp;
  }
}

/*************************************************************************
                            OLED 方块填充
--------------------------------------------------------------------------
x1,y1:左上角坐标  x2,y2:右下角坐标  mode:阳码/阴码填充
*************************************************************************/
static void OLED_Fill (uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode)  
{      
  uint8_t x, y;  
  
  for (x = x1; x <= x2; x++)
  {
     for (y = y1; y <= y2; y++)
     {
        OLED_DrawPoint (x, y, mode);
     }
  }   
  
  OLED_Refresh_Gram();          // 更新显示
}

需要刷新屏幕时,调用:

OLED_Refresh_Gram ();

需要清屏时,调用:

OLED_Clear ();

2.4 显示 ASCII 字符串

/*************************************************************************
                            OLED 打印一个字符
--------------------------------------------------------------------------
x,y:坐标  ch:字符  size:字符大小  mode:阳码/阴码
*************************************************************************/
static void OLED_ShowChar (uint8_t x, uint8_t y, uint8_t ch, uint8_t size, uint8_t mode)
{
  uint8_t temp;
  uint8_t i, j;
  uint8_t y0;
  uint8_t csize;
  
  y0 = y;
  ch = ch - ' ';
  csize = (size / 8 + ((size % 8) ? 1 : 0) ) * (size / 2);      //得到字体一个字符对应点阵集所占的字节数
  
  for(i = 0; i < csize; i++)
  {
    switch (size)
    {
    case OLED_FONT_SIZE_12:
      temp = ascii_1206[ch][i];
      break;
    case OLED_FONT_SIZE_16:
      temp = ascii_1608[ch][i];
      break;
    default:
      return;
    }
    
    for(j = 0; j < 8; j++)
    {
      if (temp & 0x80)
      {
        OLED_DrawPoint (x, y, mode);
      }
      else 
      {
        OLED_DrawPoint (x, y, !mode);
      }
      
      temp <<= 1;
      y++;
      
      if ((y - y0) == size)
      {
        y = y0;
        x++;
        break;   // 退出循环
      }
      
    } 
  }
}

/*************************************************************************
                           OLED 打印一个字符串 
--------------------------------------------------------------------------
x,y:坐标  str:字符串  size:字符大小
*************************************************************************/
void OLED_ShowString (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size)
{       
  while( (*str <= '~') && (*str >= ' ') )           //判断是不是非法字符!
  {       
    if ( x > (128 - (size / 2)) )
    {
      x = 0;
      y += size;
    }
    
    if ( y > (64 - size) )
    {
      x = 0;
      y = 0;
      OLED_Clear();
    }
    
    OLED_ShowChar (x, y, *str, size, OLED_ANODE);  
    
    x += size / 2;
    str++;
  }  
}   

使用示例:

OLED_ShowString (0, 0, "Welcome To", OLED_FONT_SIZE_16);

2.5 显示中文字符串

注意:传入的参数必须是一个数组的地址,而不是一个中文字符串。这个数组必须存储中文的点阵数据。

/*************************************************************************
                            OLED 打印一个中文字
--------------------------------------------------------------------------
x,y:坐标  *str:中文数组首地址  size:字符大小  mode:阳码/阴码
*************************************************************************/
static void OLED_ShowChar_CH (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size, uint8_t mode)
{
  uint8_t temp;
  uint8_t i, j;
  uint8_t y0;
  uint8_t csize;
  
  y0 = y;
  csize = (size / 8 + ((size % 8) ? 1 : 0) ) * (size / 2);      //得到字体一个字符对应点阵集所占的字节数
  
  for(i = 0; i < csize; i++)
  {
    temp = *(str + i);
    
    for(j = 0; j < 8; j++)
    {
      if (temp & 0x80)
      {
        OLED_DrawPoint (x, y, mode);
      }
      else 
      {
        OLED_DrawPoint (x, y, !mode);
      }
      
      temp <<= 1;
      y++;
      
      if ((y - y0) == size)
      {
        y = y0;
        x++;
        break;   // 退出循环
      }
      
    } 
  }
}

/*************************************************************************
                            OLED 打印一行中文字
--------------------------------------------------------------------------
x,y:坐标  *str:中文数组首地址  size:字符大小  num:多少字  mode:阳码/阴码
*************************************************************************/
void OLED_ShowChinese (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size, uint8_t num)
{
  uint16_t i;
  
  for (i = 0; i < num * 2; i++)
  {       
    if ( x > (128 - (size / 2)) )
    {
      x = 0;
      y += size;
    }
    
    if ( y > (64 - size) )
    {
      x = 0;
      y = 0;
      OLED_Clear();
    }
    
    OLED_ShowChar_CH (x, y, str, size, OLED_ANODE);  
    
    x += size / 2;
    str += size;
  }  
}

使用示例:

OLED_ShowChinese (20, 20, &chinese1_1616[0][0], OLED_FONT_SIZE_16, 4);

2.6 显示图片

注意:传入的参数必须是一个数组的地址。这个数组必须存储 BMP 图片的点阵数据。

/*************************************************************************
                            OLED 打印 BMP 图片
--------------------------------------------------------------------------
x,y:左上角坐标  *bmp:BMP数组首地址  width,height:图片尺寸大小  
*************************************************************************/
void OLED_ShowPic (uint8_t x, uint8_t y, const uint8_t *pic, uint8_t width, uint8_t height, uint8_t mode)
{
  uint16_t i, j, size;
  uint8_t y0;
  uint8_t temp;
  
  if ((x + width > 128) || (y + height > 64))  
    return;    

  size = (uint16_t)( height / 8 + ((height % 8)? 1 : 0) ) * width;
  y0 = y;
  
  for (i = 0; i < size; i++)
  {
    temp = *(pic + i);
    
    for (j = 0; j < 8; j++)
    {
      if (temp & 0x80)
      {
        OLED_DrawPoint (x, y, mode);
      }
      else 
      {
        OLED_DrawPoint (x, y, !mode);
      }
      
      temp <<= 1;
      y++;
      
      if (y - y0 == height)
      {
        y = y0;
        x++;
        break;
      }
      
    }
  }
}

使用示例:

OLED_ShowPic (0, 0, &bmp1[0][0], 114, 64, OLED_CATHODE);

2.7 垂直及水平滚动

注意:

  • 这些函数需要在OLED_Refresh_Gram()后调用,且不能放在 while 循环体内。
  • 由于硬件设计原因,OLED 不能直接做到完全垂直滚动,只能做到垂直+水平滚动的效果。完全垂直滚动的实现有待本人进一步研究。
/*************************************************************************
                            OLED 垂直+水平滚动显示
--------------------------------------------------------------------------
start_page,end_page:起始/终止页地址  frame:滚动步长时间间隔,帧为单位
scroll_offset:垂直滚动偏移(0-63)  dir:滚动方向
--------------------------------------------------------------------------
注意:该函数需要在 OLED_Refresh_Gram 后调用
*************************************************************************/
void OLED_VerHorScroll (enum page_num start_page, enum page_num end_page, enum roll_frame frame, uint8_t scroll_offset, uint8_t dir)
{
  OLED_SPI_WriteCmd (0x2E);             //关闭滚动
  OLED_SPI_WriteCmd (0x29 + dir);       //水平垂直和水平滚动左右 29/2a
  OLED_SPI_WriteCmd (0x00);             //虚拟字节
  OLED_SPI_WriteCmd (start_page);       //起始页  
  OLED_SPI_WriteCmd (frame);            //滚动时间间隔
  OLED_SPI_WriteCmd (end_page);         //终止页
  OLED_SPI_WriteCmd (scroll_offset);    //垂直滚动偏移量
  OLED_SPI_WriteCmd (0x2F);
}

/*************************************************************************
                            OLED 水平滚动显示
--------------------------------------------------------------------------
start_page,end_page:起始/终止页地址  frame:滚动步长时间间隔,帧为单位
dir:滚动方向
--------------------------------------------------------------------------
注意:该函数需要在 OLED_Refresh_Gram 后调用
*************************************************************************/
void OLED_HorScroll (enum page_num start_page, enum page_num end_page, enum roll_frame frame, uint8_t dir)
{
  OLED_SPI_WriteCmd (0x2E);             //关闭滚动
  OLED_SPI_WriteCmd (0x26 + dir);       //水平向左或者右滚动 26/27
  OLED_SPI_WriteCmd (0x00);             //虚拟字节
  OLED_SPI_WriteCmd (start_page);       //起始页
  OLED_SPI_WriteCmd (frame);            //滚动时间间隔
  OLED_SPI_WriteCmd (end_page);         //终止页
  OLED_SPI_WriteCmd (0x00);             //虚拟字节(必须加上)
  OLED_SPI_WriteCmd (0xFF);             //虚拟字节(必须加上)
  OLED_SPI_WriteCmd (0x2F);             //开启滚动
}

使用示例(要放在 while 外面):

// 实现图片的垂直+水平滚动
  OLED_ShowPic (0, 0, &bmp1[0][0], 114, 64, OLED_CATHODE);
  OLED_Refresh_Gram ();
  OLED_VerHorScroll (PAGE2, PAGE7, FRAME7, 0, OLED_SCROLL_LEFT);

3 字模和图片的相关文件

3.1 oled_font.h

#ifndef __OLED_FONT_H
#define __OLED_FONT_H

#include "stm8s.h"

extern const uint8_t ascii_1206[][12];
extern const uint8_t ascii_1608[][16];

extern const uint8_t chinese1_1616[][16];
extern const uint8_t chinese2_1616[][16];

extern const uint8_t bmp1[][16];
extern const uint8_t bmp2[][16];
extern const uint8_t bmp3[][16];

#endif /* __OLED_FONT_H */

3.2 oled_font.c

存储 ASCII 字符,仅展示一部分代码(12x6 的 ASCII 字符):

#include "oled_font.h"

/*********点阵格式:阴码  取模方式:逐列式  取模走向:顺向(高位在前)*********/

const uint8_t ascii_1206[95][12]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x3F,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x40,0x00,0x00,0x00},/*""",2*/
{0x09,0x00,0x0B,0xC0,0x3D,0x00,0x0B,0xC0,0x3D,0x00,0x09,0x00},/*"#",3*/
{0x18,0xC0,0x24,0x40,0x7F,0xE0,0x22,0x40,0x31,0x80,0x00,0x00},/*"$",4*/
{0x18,0x00,0x24,0xC0,0x1B,0x00,0x0D,0x80,0x32,0x40,0x01,0x80},/*"%",5*/
{0x03,0x80,0x1C,0x40,0x27,0x40,0x1C,0x80,0x07,0x40,0x00,0x40},/*"&",6*/
{0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x40,0x20},/*"(",8*/
{0x00,0x00,0x40,0x20,0x20,0x40,0x1F,0x80,0x00,0x00,0x00,0x00},/*")",9*/
{0x09,0x00,0x06,0x00,0x1F,0x80,0x06,0x00,0x09,0x00,0x00,0x00},/*"*",10*/
{0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x00,0x00},/*"+",11*/
{0x00,0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x20,0x01,0xC0,0x06,0x00,0x38,0x00,0x40,0x00,0x00,0x00},/*"/",15*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"0",16*/
{0x00,0x00,0x10,0x40,0x3F,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"1",17*/
{0x18,0xC0,0x21,0x40,0x22,0x40,0x24,0x40,0x18,0x40,0x00,0x00},/*"2",18*/
{0x10,0x80,0x20,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"3",19*/
{0x02,0x00,0x0D,0x00,0x11,0x00,0x3F,0xC0,0x01,0x40,0x00,0x00},/*"4",20*/
{0x3C,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x23,0x80,0x00,0x00},/*"5",21*/
{0x1F,0x80,0x24,0x40,0x24,0x40,0x34,0x40,0x03,0x80,0x00,0x00},/*"6",22*/
{0x30,0x00,0x20,0x00,0x27,0xC0,0x38,0x00,0x20,0x00,0x00,0x00},/*"7",23*/
{0x1B,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"8",24*/
{0x1C,0x00,0x22,0xC0,0x22,0x40,0x22,0x40,0x1F,0x80,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x08,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40},/*"<",28*/
{0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x40,0x40,0x20,0x80,0x11,0x00,0x0A,0x00,0x04,0x00},/*">",30*/
{0x18,0x00,0x20,0x00,0x23,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"?",31*/
{0x1F,0x80,0x20,0x40,0x27,0x40,0x29,0x40,0x1F,0x40,0x00,0x00},/*"@",32*/
{0x00,0x40,0x07,0xC0,0x39,0x00,0x0F,0x00,0x01,0xC0,0x00,0x40},/*"A",33*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"B",34*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x30,0x80,0x00,0x00},/*"C",35*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"D",36*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x40,0x30,0xC0,0x00,0x00},/*"E",37*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x00,0x30,0x00,0x00,0x00},/*"F",38*/
{0x0F,0x00,0x10,0x80,0x20,0x40,0x22,0x40,0x33,0x80,0x02,0x00},/*"G",39*/
{0x20,0x40,0x3F,0xC0,0x04,0x00,0x04,0x00,0x3F,0xC0,0x20,0x40},/*"H",40*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x00,0x00},/*"I",41*/
{0x00,0x60,0x20,0x20,0x20,0x20,0x3F,0xC0,0x20,0x00,0x20,0x00},/*"J",42*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x0B,0x00,0x30,0xC0,0x20,0x40},/*"K",43*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x00,0x40,0x00,0x40,0x00,0xC0},/*"L",44*/
{0x3F,0xC0,0x3C,0x00,0x03,0xC0,0x3C,0x00,0x3F,0xC0,0x00,0x00},/*"M",45*/
{0x20,0x40,0x3F,0xC0,0x0C,0x40,0x23,0x00,0x3F,0xC0,0x20,0x00},/*"N",46*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"O",47*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"P",48*/
{0x1F,0x80,0x21,0x40,0x21,0x40,0x20,0xE0,0x1F,0xA0,0x00,0x00},/*"Q",49*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x26,0x00,0x19,0xC0,0x00,0x40},/*"R",50*/
{0x18,0xC0,0x24,0x40,0x24,0x40,0x22,0x40,0x31,0x80,0x00,0x00},/*"S",51*/
{0x30,0x00,0x20,0x40,0x3F,0xC0,0x20,0x40,0x30,0x00,0x00,0x00},/*"T",52*/
{0x20,0x00,0x3F,0x80,0x00,0x40,0x00,0x40,0x3F,0x80,0x20,0x00},/*"U",53*/
{0x20,0x00,0x3E,0x00,0x01,0xC0,0x07,0x00,0x38,0x00,0x20,0x00},/*"V",54*/
{0x38,0x00,0x07,0xC0,0x3C,0x00,0x07,0xC0,0x38,0x00,0x00,0x00},/*"W",55*/
{0x20,0x40,0x39,0xC0,0x06,0x00,0x39,0xC0,0x20,0x40,0x00,0x00},/*"X",56*/
{0x20,0x00,0x38,0x40,0x07,0xC0,0x38,0x40,0x20,0x00,0x00,0x00},/*"Y",57*/
{0x30,0x40,0x21,0xC0,0x26,0x40,0x38,0x40,0x20,0xC0,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x7F,0xE0,0x40,0x20,0x40,0x20,0x00,0x00},/*"[",59*/
{0x00,0x00,0x70,0x00,0x0C,0x00,0x03,0x80,0x00,0x40,0x00,0x00},/*"\",60*/
{0x00,0x00,0x40,0x20,0x40,0x20,0x7F,0xE0,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x20,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10},/*"_",63*/
{0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x02,0x80,0x05,0x40,0x05,0x40,0x03,0xC0,0x00,0x40},/*"a",65*/
{0x20,0x00,0x3F,0xC0,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"b",66*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x06,0x40,0x00,0x00},/*"c",67*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x24,0x40,0x3F,0xC0,0x00,0x40},/*"d",68*/
{0x00,0x00,0x03,0x80,0x05,0x40,0x05,0x40,0x03,0x40,0x00,0x00},/*"e",69*/
{0x00,0x00,0x04,0x40,0x1F,0xC0,0x24,0x40,0x24,0x40,0x20,0x00},/*"f",70*/
{0x00,0x00,0x02,0xE0,0x05,0x50,0x05,0x50,0x06,0x50,0x04,0x20},/*"g",71*/
{0x20,0x40,0x3F,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"h",72*/
{0x00,0x00,0x04,0x40,0x27,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x10,0x00,0x10,0x04,0x10,0x27,0xE0,0x00,0x00,0x00,0x00},/*"j",74*/
{0x20,0x40,0x3F,0xC0,0x01,0x40,0x07,0x00,0x04,0xC0,0x04,0x40},/*"k",75*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x00,0x40,0x00,0x40,0x00,0x00},/*"l",76*/
{0x07,0xC0,0x04,0x00,0x07,0xC0,0x04,0x00,0x03,0xC0,0x00,0x00},/*"m",77*/
{0x04,0x40,0x07,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"n",78*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"o",79*/
{0x04,0x10,0x07,0xF0,0x04,0x50,0x04,0x40,0x03,0x80,0x00,0x00},/*"p",80*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x50,0x07,0xF0,0x00,0x10},/*"q",81*/
{0x04,0x40,0x07,0xC0,0x02,0x40,0x04,0x00,0x04,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x06,0x40,0x05,0x40,0x05,0x40,0x04,0xC0,0x00,0x00},/*"s",83*/
{0x00,0x00,0x04,0x00,0x1F,0x80,0x04,0x40,0x00,0x40,0x00,0x00},/*"t",84*/
{0x04,0x00,0x07,0x80,0x00,0x40,0x04,0x40,0x07,0xC0,0x00,0x40},/*"u",85*/
{0x04,0x00,0x07,0x00,0x04,0xC0,0x01,0x80,0x06,0x00,0x04,0x00},/*"v",86*/
{0x06,0x00,0x01,0xC0,0x07,0x00,0x01,0xC0,0x06,0x00,0x00,0x00},/*"w",87*/
{0x04,0x40,0x06,0xC0,0x01,0x00,0x06,0xC0,0x04,0x40,0x00,0x00},/*"x",88*/
{0x04,0x10,0x07,0x10,0x04,0xE0,0x01,0x80,0x06,0x00,0x04,0x00},/*"y",89*/
{0x00,0x00,0x04,0x40,0x05,0xC0,0x06,0x40,0x04,0x40,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x04,0x00,0x7B,0xE0,0x40,0x20,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x20,0x7B,0xE0,0x04,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x40,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x40,0x00},/*"~",94*/
}; 

3.3 oled_font_ch.c

存储中文字符,仅展示 12x12 的中文字符“当前温度 ”:

#include "oled_font.h"

/*********点阵格式:阴码  取模方式:逐列式  取模走向:顺向(高位在前)*********/

// chinese1 = "当前温度"
const uint8_t chinese1_1616[4*2][16] = {
{0x00,0x00,0x02,0x02,0x42,0x22,0x22,0x22,0x1A,0x22,0x02,0x22,0x02,0x22,0xFE,0x22},
{0x02,0x22,0x02,0x22,0x0A,0x22,0x12,0x22,0x63,0xFF,0x00,0x00,0x00,0x00,0x00,0x00},/*"当",0*/

{0x10,0x00,0x10,0x00,0x17,0xFF,0x94,0x90,0x74,0x92,0x14,0x91,0x17,0xFE,0x10,0x00},
{0x10,0x00,0x13,0xF0,0x30,0x02,0xD0,0x01,0x17,0xFE,0x10,0x00,0x10,0x00,0x00,0x00},/*"前",1*/

{0x08,0x20,0x06,0x20,0x40,0x7E,0x31,0x80,0x00,0x02,0x00,0x7E,0x7F,0x42,0x49,0x42},
{0x49,0x7E,0x49,0x42,0x49,0x7E,0x49,0x42,0x7F,0x42,0x00,0x7E,0x00,0x02,0x00,0x00},/*"温",2*/

{0x00,0x02,0x00,0x0C,0x3F,0xF1,0x24,0x01,0x24,0x21,0x24,0x32,0x3F,0xAA,0xA4,0xA4},
{0x64,0xA4,0x24,0xA4,0x3F,0xAA,0x24,0x32,0x24,0x01,0x24,0x01,0x20,0x01,0x00,0x00},/*"度",3*/
};

3.4 oled_bmp.c

该文件用于存储图片数据。需要在软件 image2LCD 中将图片转换为 bmp 格式,再用软件 PCtoLCD2002 将其转换为字模数据。

#include "oled_font.h"

// 64x64
const uint8_t bmp2[][16] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x30,0x40,0x00,0x00,0x00,0x00,0x00},
{0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00},
{0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x07,0xC0,0x00,0x00,0x00},
{0x1E,0x00,0x00,0x07,0x90,0x00,0x00,0x00,0x3E,0x00,0x00,0x07,0xF4,0x00,0x00,0x00},
{0x7E,0x00,0x00,0x07,0x98,0x00,0x00,0x00,0x7E,0x00,0x00,0x07,0xE4,0x00,0x00,0x03},
{0xFE,0x00,0x00,0x07,0xFC,0x00,0x00,0x0F,0xFE,0x00,0x00,0x07,0x7E,0x00,0x00,0x1F},
{0xFE,0x00,0x00,0x0F,0x8B,0x00,0x00,0x3F,0xFE,0x00,0x00,0x03,0x02,0x80,0x07,0xFF},
{0xFE,0x00,0x00,0x1C,0x11,0x00,0x1F,0xFF,0xFE,0x00,0x00,0x30,0x00,0x20,0x3F,0xFF},
{0xFE,0x00,0x00,0x04,0x00,0x40,0x7F,0xFF,0xFE,0x00,0x00,0x10,0x00,0x00,0x7F,0xFF},
{0xFE,0x00,0x00,0xC0,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x01,0xE0,0x00,0x00,0xFF,0xFF},
{0xFF,0x00,0x03,0x80,0x00,0x00,0xC7,0xFF,0xFF,0x00,0x06,0x80,0x00,0x00,0x00,0x3F},
{0xFF,0xC0,0x07,0xF0,0x00,0x00,0x80,0x3F,0xFF,0xF0,0x0D,0xF0,0x00,0x00,0x00,0x1F},
{0xFF,0xFC,0x1F,0xE0,0x00,0x01,0x00,0x1F,0xFF,0xFF,0xC1,0xC8,0x01,0x00,0x00,0x3F},
{0xFF,0xFF,0xFF,0x80,0x02,0x00,0x00,0x3F,0xFF,0xFF,0xF8,0x00,0x0C,0xE4,0x00,0x3F},
{0xFF,0xFF,0xFB,0xFC,0x71,0x88,0x00,0x7F,0xFF,0xFF,0xE0,0x7F,0x83,0x00,0x00,0xFF},
{0xFF,0xFF,0xF0,0xFE,0x04,0x00,0x00,0xFF,0xFF,0xFF,0xFB,0x80,0x00,0x00,0x01,0xFF},
{0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x03,0x8F},
{0xFF,0xFF,0xFC,0x08,0x00,0x00,0x07,0x87,0x7F,0xFE,0xFC,0x03,0xA0,0x00,0x1F,0x8F},
{0x1F,0xFE,0xFE,0x0C,0x40,0x00,0x5F,0xDF,0x0F,0xFF,0xFF,0xF8,0x40,0x00,0x7F,0xFF},
{0x1F,0xFC,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0x1F,0x3E,0xFF,0x40,0x00,0x01,0xFF,0xFF},
{0x1F,0x82,0x63,0x00,0x00,0x03,0xFF,0xFF,0x0F,0x80,0x00,0x00,0x00,0x03,0xFF,0xFF},
{0x03,0x80,0x00,0x00,0x00,0x07,0xFF,0xFF,0x03,0xC0,0x00,0x00,0x00,0x0F,0xFF,0xFF},
{0x01,0xE0,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x01,0xB0,0x00,0x00,0x00,0x1F,0xFF,0xFF},
{0x01,0x8C,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x01,0x80,0x00,0x00,0x00,0x0F,0xFF,0xFF},
{0x00,0x80,0x00,0x00,0x00,0x07,0xFF,0xFC,0x01,0xC0,0x00,0x00,0x00,0x07,0xFF,0xF8},
{0x00,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x58,0x00,0x00,0x00,0x01,0xCF,0xF0},
{0x00,0x20,0x00,0x00,0x00,0x00,0xF7,0xE0,0x00,0x00,0x80,0x00,0x00,0x00,0x3F,0xF0},
{0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF},
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},/*"E:\STM8_Project\555.bmp",0*/
};
---EOF---
posted @ 2022-02-27 14:45  漫舞八月(Mount256)  阅读(596)  评论(0编辑  收藏  举报