SSD1306双内存驱动

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/jickjiang/article/details/81384768

问题原由

基于目前在网上找的SSD1306的驱动程序普遍采用一个二维数组作为显示缓存,画点函数作为显示的底层,这样会照成当整个页面在刷新的时候的操作有:
1、单点刷玩整个页面
2、使用显示缓存刷完整个页面
这样会让整个页面刷新缓慢,对人机交互有影响

问题解法

我目前使用的是OLED12832这款型号的屏幕,程序显示主缓存为OLED_Gram[4][128],对比缓存为OLED_GramBk[4][128],每个缓存一共四行,每行128字节映射128*8个像素点。

流程

画点函数只改变OLEDGram[4][128]的数据,然后后台程序每100ms对比两个显示缓存OLED_Gram[4][128]和OLED_GramBk[4][128],如果有一行数据不一样(x)就刷新改行数据,并将该行数据拷贝到OLED_GramBk[x][128],然后发送改行的坐标给SSD1306后发送整行OLED_GramBk[x][128]的缓存数据。

程序

bsp_ssd1306.h


/**
*****************************************************************************
* @文  件: bsp_ssd1306.h
* @作  者: 00Jackey
* @版  本: V1.0.0
* @日  期: 17-July-2018
* @描  述: ssd1306驱动接口文件
******************************************************************************
* @修改记录:
*   2018/07/17:初始版本
*    
*
******************************************************************************
**/

#ifndef _BSP_SSD1306_H_
#define _BSP_SSD1306_H_

#ifdef __cplusplus
 extern "C" {
#endif

//C库
#include <stdint.h>
#include <stdbool.h>

//定义枚举
typedef enum{
    OLED_CMD = 0,
    OLED_DATA
}OLED_BYTE_TYPE;


//接口函数
void Ssd1306_drawPixel(uint8_t x,uint8_t y,uint8_t show);
void Ssd1306_displaySet(uint8_t state);
void Ssd1306_lightSet(uint8_t value);
void Ssd1306_clear(uint8_t state);

void Ssd1306_refresh(void);
void Ssd1306_init(void);

#ifdef __cplusplus
}
#endif

#endif

bsp_ssd1306.c


/**
*****************************************************************************
* @文  件: bsp_ssd1306.c 
* @作  者: 00Jackey
* @版  本: V1.0.0
* @日  期: 17-July-2018
* @描  述: ssd1306驱动主程序
******************************************************************************
* @修改记录:
*   2018/07/17:初始版本
*    
*
******************************************************************************
**/

//接口头文件
#include "bsp_ssd1306.h"

//硬件头文件
#include "hardware.h"

//宏定义
#define SSID1306_WRITE(x)       Ssd1306_sendData(x) 

#define CMD_CHOOSE()            GPIO_ResetBits(GPIOC,GPIO_Pin_7)
#define DATA_CHOOSE()           GPIO_SetBits(GPIOC,GPIO_Pin_7)

#define SPI_SCK_LOW()           GPIO_ResetBits(GPIOC,GPIO_Pin_4)
#define SPI_SCK_HIGH()          GPIO_SetBits(GPIOC,GPIO_Pin_4)

#define SPI_MOSI_LOW()          GPIO_ResetBits(GPIOC,GPIO_Pin_5)
#define SPI_MOSI_HIGH()         GPIO_SetBits(GPIOC,GPIO_Pin_5)

#define SSD1306_RESET_LOW()     GPIO_ResetBits(GPIOC,GPIO_Pin_6)
#define SSD1306_RESET_HIGH()    GPIO_SetBits(GPIOC,GPIO_Pin_6)

//静态函数
static void Ssd1306_sendData(uint8_t byte);
static void Ssd1306_writeByte(uint8_t content, OLED_BYTE_TYPE type);

//静态变量
static uint8_t OLED_Gram[4][128];
static uint8_t OLED_GramBk[4][128];



/*
******************************************************************************
*   函 数 名: Ssd1306_gpioInit
*   功能说明: Ssd1306初始化GPIO
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_gpioInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure ;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;

    //配置模拟SPI的 SCK
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_Init(GPIOC, &GPIO_InitStructure );

    //配置模拟SPI的 MOSI
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_Init(GPIOC, &GPIO_InitStructure );

    //配置 SSD1306 RESET
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOC, &GPIO_InitStructure );

    //配置 SSD1306 D/C
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_Init(GPIOC, &GPIO_InitStructure ); 

    GPIO_SetBits(GPIOC,GPIO_Pin_7);
    GPIO_SetBits(GPIOC,GPIO_Pin_6);

}

/*
******************************************************************************
*   函 数 名: Ssd1306_init
*   功能说明: Ssd1306初始化
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_init(void)
{
    Ssd1306_gpioInit();               //初始化GPIO口

    SSD1306_RESET_LOW();              //复位SSD1306   
    Delay_mSec(100);
    SSD1306_RESET_HIGH();

    Ssd1306_writeByte(0xAE,OLED_CMD); //关闭显示 -

    Ssd1306_writeByte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数. -
    Ssd1306_writeByte(0xB0,OLED_CMD); //设置扫描方向 -

    Ssd1306_writeByte(0x81,OLED_CMD); //对比度设置 -
    Ssd1306_writeByte(0x7F,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮) -

    Ssd1306_writeByte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127; -
    Ssd1306_writeByte(0xA6,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数

    Ssd1306_writeByte(0xA8,OLED_CMD); //设置驱动路数 -
    Ssd1306_writeByte(0X1F,OLED_CMD); //默认0X3F(1/64) -1f 

    Ssd1306_writeByte(0xC8,OLED_CMD); //COM重映射

    Ssd1306_writeByte(0xD3,OLED_CMD); //设置显示偏移  -
    Ssd1306_writeByte(0X00,OLED_CMD); //默认为0 -

    Ssd1306_writeByte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率 -
    Ssd1306_writeByte(0xF0,OLED_CMD); //[3:0],分频因子;[7:4],震荡频率 -

    Ssd1306_writeByte(0xD9,OLED_CMD); //设置预充电周期 -
    Ssd1306_writeByte(0x22,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2; -

    Ssd1306_writeByte(0xDA,OLED_CMD); //设置COM硬件引脚配置 -
    Ssd1306_writeByte(0x02,OLED_CMD); //[5:4]配置 -    

    Ssd1306_writeByte(0xDB,OLED_CMD); //设置VCOMH 电压倍率 -
    Ssd1306_writeByte(0x49,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc; -

    Ssd1306_writeByte(0x8D,OLED_CMD); //电荷泵设置 -
    Ssd1306_writeByte(0x14,OLED_CMD); //bit2,开启/关闭 -

    Ssd1306_writeByte(0x20,OLED_CMD); //设置内存地址模式
    Ssd1306_writeByte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;

    Ssd1306_writeByte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
    Ssd1306_writeByte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示  

    Ssd1306_writeByte(0xAF,OLED_CMD); //开启显示   

    Ssd1306_clear(0);                 //清屏开显示

}

/*
******************************************************************************
*   函 数 名: Ssd1306_dcSet
*   功能说明: Ssd1306写数据
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_dcSet(OLED_BYTE_TYPE type)
{
    if(type == OLED_CMD){
        CMD_CHOOSE();
    }else if(type == OLED_DATA){
        DATA_CHOOSE();
    }
}

/*
******************************************************************************
*   函 数 名: Ssd1306_writeByte
*   功能说明: Ssd1306写数据
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_writeByte(uint8_t content, OLED_BYTE_TYPE type)
{
    Ssd1306_dcSet(type);
    SSID1306_WRITE(content);
}

/*
******************************************************************************
*   函 数 名: Ssd1306_sendData
*   功能说明: Ssd1306发送数据
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_sendData(uint8_t byte)
{
    for(uint8_t cnt=0; cnt<8; cnt++){
        SPI_SCK_LOW();

        if(byte & 0x80)
            SPI_MOSI_HIGH();
        else
            SPI_MOSI_LOW();
        byte <<= 1;

        SPI_SCK_HIGH();   
    }
}

/*
******************************************************************************
*   函 数 名: Ssd1306_setPos
*   功能说明: Ssd1306设置写的起始点
*   形    参: x:x坐标 y:y坐标
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_setPos(uint8_t x, uint8_t y)
{
    Ssd1306_writeByte(0xb0 + (y / 8), OLED_CMD);
    Ssd1306_writeByte(((x & 0xf0) >> 4) | 0x10, OLED_CMD);
    Ssd1306_writeByte((x & 0x0f), OLED_CMD); 
}

/*
******************************************************************************
*   函 数 名: Ssd1306_drawPixel
*   功能说明: Ssd1306画点
*   形    参: x:x坐标 y:y坐标 show:0:不亮, 1:电路
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_drawPixel(uint8_t x,uint8_t y,uint8_t show)
{
    uint8_t pos = 0;
    uint8_t bx = 0;
    uint8_t temp = 0;

    pos = y / 8;
    bx = y % 8;
    temp = 1 << bx;

    if (show){
        OLED_Gram[pos][x] |= temp;
    }else{
        OLED_Gram[pos][x] &= ~temp;
    }
}

/*
******************************************************************************
*   函 数 名: Ssd1306_displaySet
*   功能说明: Ssd1306开关显示
*   形    参: show:0:不显示,1:显示
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_displaySet(uint8_t state)
{
    if(state){
        Ssd1306_writeByte(0xAF,OLED_CMD);
    }else{
        Ssd1306_writeByte(0xAE,OLED_CMD);
    }
}

/*
******************************************************************************
*   函 数 名: Ssd1306_lightSet
*   功能说明: Ssd1306亮度调整
*   形    参: bk_light :0~255 亮度等级
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_lightSet(uint8_t bk_light)
{
    Ssd1306_writeByte(0x81 ,OLED_CMD);
    Ssd1306_writeByte(bk_light, OLED_CMD);
}

/*
******************************************************************************
*   函 数 名: Ssd1306_refreshGram
*   功能说明: 页面刷新开关
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_refreshGram(void)
{
    for (uint8_t i = 0;i < 4;i++){  
        //设置页地址(0~7)
        Ssd1306_writeByte(0xb0 + i,OLED_CMD);
        //设置显示位置—列低地址
        Ssd1306_writeByte(0x02,OLED_CMD);
        //设置显示位置—列高地址   
        Ssd1306_writeByte(0x10,OLED_CMD);

        //更新数据
        for (uint8_t n = 0; n < 128; n++){
            Ssd1306_writeByte(OLED_Gram[i][n],OLED_DATA); 
        }
    }
}


/*
******************************************************************************
*   函 数 名: Ssd1306_clear
*   功能说明: 页面刷新开关
*   形    参: show :0:点暗 1:点亮
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_clear(uint8_t show)
{
    for (uint8_t i = 0;i < 4;i++){
        for(uint8_t n = 0; n < 128; n++){
            OLED_Gram[i][n] = show; 
        }
    }
}

/*
******************************************************************************
*   函 数 名: Ssd1306_refreshPage
*   功能说明: 后台刷新页面,试一下使用后台刷新页面
*   形    参: 无
*   返 回 值: 无
******************************************************************************
*/
void Ssd1306_refresh(void)
{
    for(uint8_t i = 0; i < 4; i ++){
        if(0 == memcmp(OLED_GramBk[i],OLED_Gram[i],128))
            continue;
        else{
            Ssd1306_writeByte(0xb0 + i,OLED_CMD);
            Ssd1306_writeByte(0x02,OLED_CMD);
            Ssd1306_writeByte(0x10,OLED_CMD);
            for(uint8_t n = 0; n < 128; n++){
                Ssd1306_writeByte(OLED_Gram[i][n],OLED_DATA); 
            }
            memcpy(OLED_GramBk[i],OLED_Gram[i],128);
        }
    }
}


猜你喜欢

转载自blog.csdn.net/jickjiang/article/details/81384768