STM8驱动0.96寸OLED(12864液晶屏)

Posted Mount256

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM8驱动0.96寸OLED(12864液晶屏)相关的知识,希望对你有一定的参考价值。

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

文章目录


使用软件:IAR FOR STM8

编程方式:固件库

硬件配套:STM8S105C6T6实验板

字模软件:PCtoLCD2002

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

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 刷新显示
--------------------------------------------------------------------------
无参数
*************************************************************************/
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);
      

以上是关于STM8驱动0.96寸OLED(12864液晶屏)的主要内容,如果未能解决你的问题,请参考以下文章

Arduino ESP32 0.96OLED I2C屏幕驱动显示

51单片机IIC 12864 OLED屏幕滚动显示仿真

和12岁小同志搞创客开发:如何驱动 12864 OLED液晶显示屏?

和12岁小同志搞创客开发:如何驱动 12864 OLED液晶显示屏?

和12岁小同志搞创客开发:如何驱动 12864 OLED液晶显示屏?

STM32Cubemx——硬件SPI驱动七针0.96寸OLED