OLED驱动 0.96寸 SPI(STM32)

一、前期准备
单片机:STM32F103ZET6
开发环境:MDK5.14
库函数:标准库V3.5
0.96 OLED模块:淘宝有售
这里写图片描述
二、实验效果
这里写图片描述
这里写图片描述
这里写图片描述
三、驱动原理
此OLED模块采用SPI通信,也可转成IIC通信,不过要焊接背面的电阻,不建议改IIC,要改请参考具体数据手册。驱动芯片SSD1306,具体命令字详解请见网友SSD1306详解
需要完整工程或者有问题的请加QQ:1002521871,验证:呵呵。
四、驱动代码
oled.h

#ifndef __OLED_H__
#define __OLED_H__
#include "stm32f10x.h"
#include "stdlib.h"
#include "oledfont.h"    
#include "delay.h"
#include "bmp.h"
#include "gpio.h"

#define     OLED            0
#define     SIZE            16
#define     XLevelL         0x00
#define     XLevelH         0x10
#define     Max_Column      128
#define     Max_Row         64
#define     Brightness      0xff
#define     X_WIDTH         128
#define     Y_WIDTH         64

//IO Definitions
#define     CS          PDout(3)
#define     RST         PDout(4)
#define     DC          PDout(5)
#define     CLK         PDout(6)
#define     DIN         PDout(7)

#define     OLED_CS_Clr()       CS = 0  //CS
#define     OLED_CS_Set()       CS = 1

#define     OLED_RST_Clr()      RST = 0 //RES
#define     OLED_RST_Set()      RST = 1

#define     OLED_DC_Clr()       DC = 0 //DC
#define     OLED_DC_Set()       DC = 1

#define     OLED_SCLK_Clr()     CLK = 0//CLK--D0
#define     OLED_SCLK_Set()     CLK = 1

#define     OLED_SDIN_Clr()     DIN = 0 //DIN--D1
#define     OLED_SDIN_Set()     DIN = 1

typedef enum
{
    OLED_CMD,
    OLED_DATA
}OLED_WR_MODE;

typedef enum 
{
    Display_ON,
    Display_OFF,
    Display_Clear,
    Display_Test
}DIS_MODE;

//OLED控制用函数
extern void OLED_WR_Byte(uint8_t dat,OLED_WR_MODE cmd);     
extern void OLED_Display_Status(DIS_MODE mode);                                         
extern void OLEDConfiguration(void);
extern void OLED_DrawPoint(uint8_t x, uint8_t y, uint8_t t);
extern void OLED_Fill(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t dot);
extern void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr);
extern void OLED_ShowNum(uint8_t x, uint8_t y, u32 num, uint8_t len, uint8_t size);
extern void OLED_ShowString(uint8_t x,uint8_t y, uint8_t *p);    
extern void OLED_Set_Pos(uint8_t x, uint8_t y);
extern void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no);
extern void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1, uint8_t BMP[]);
#endif

oled.c

#include "oled.h"

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127    
//[1]0 1 2 3 ... 127    
//[2]0 1 2 3 ... 127    
//[3]0 1 2 3 ... 127    
//[4]0 1 2 3 ... 127    
//[5]0 1 2 3 ... 127    
//[6]0 1 2 3 ... 127    
//[7]0 1 2 3 ... 127               

//#if OLED_MODE == 1
////向SSD1106写入一个字节。
////dat:要写入的数据/命令
////cmd:数据/命令标志 0,表示命令;1,表示数据;
//void OLED_WR_Byte(uint8_t dat,OLED_WR_MODE cmd)
//{
//  //DATAOUT(dat); 
//  switch(cmd)
//  {
//      case OLED_CMD:
//          OLED_DC_Clr();
//          break;
//      case OLED_DATA:
//          OLED_DC_Set();
//          break;
//  }    
//             
//  OLED_CS_Clr();
//  OLED_WR_Clr();   
//  OLED_WR_Set();
//  OLED_CS_Set();    
//  OLED_DC_Set();   
//}                 
//#else
//向SSD1106写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(uint8_t dat,OLED_WR_MODE cmd)
{   
    uint8_t i;
    switch(cmd)
    {
        case OLED_CMD:
            OLED_DC_Clr();
            break;
        case OLED_DATA:
            OLED_DC_Set();
            break;
    }                     
    OLED_CS_Clr();
    for(i = 0; i < 8; i ++)
    {             
        OLED_SCLK_Clr();
        if(dat & 0x80)
           OLED_SDIN_Set();
        else 
           OLED_SDIN_Clr();
        OLED_SCLK_Set();
        dat<<=1;   
    }                         
    OLED_CS_Set();
    OLED_DC_Set();        
} 
//#endif

void OLED_Set_Pos(uint8_t x, uint8_t y) 
{ 
    OLED_WR_Byte(0xB0 + y, OLED_CMD);
    OLED_WR_Byte(((x & 0xF0) >> 4) | 0x10, OLED_CMD);
    OLED_WR_Byte((x & 0x0F) | 0x01, OLED_CMD); 
}   

void OLED_Display_Status(DIS_MODE mode)
{
    uint8_t i,n;        
    switch(mode)
    {
        case Display_ON://开启OLED显示 
            OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令
            OLED_WR_Byte(0X14, OLED_CMD);  //DCDC ON
            OLED_WR_Byte(0XAF, OLED_CMD);  //DISPLAY ON
            break;
        case Display_OFF://关闭OLED显示  
            OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令
            OLED_WR_Byte(0X10, OLED_CMD);  //DCDC OFF
            OLED_WR_Byte(0XAE, OLED_CMD);  //DISPLAY OFF
            break;
        case Display_Clear://清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!    
            for(i = 0; i < 8; i ++)  
            {  
                OLED_WR_Byte(0xB0 + i, OLED_CMD);    //设置页地址(0~7)
                OLED_WR_Byte(0x00, OLED_CMD);      //设置显示位置—列低地址
                OLED_WR_Byte(0x10, OLED_CMD);      //设置显示位置—列高地址   
                for(n = 0; n < Max_Column; n ++)
                {
                    OLED_WR_Byte(0, OLED_DATA); 
                }
            } //更新显示
            break;
        case Display_Test:
            for(i = 0; i < 8; i ++)  
            {  
                OLED_WR_Byte(0xb0 + i, OLED_CMD);    //设置页地址(0~7)
                OLED_WR_Byte(0x00, OLED_CMD);      //设置显示位置—列低地址
                OLED_WR_Byte(0x10, OLED_CMD);      //设置显示位置—列高地址   
                for(n = 0; n < Max_Column; n ++)
                {
                    OLED_WR_Byte(1, OLED_DATA);
                    DelayMs(5);
                }
            } //更新显示
            break;
    }

}

//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示                 
//size:选择字体 16/12 
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr)
{       
    uint8_t c = 0, i = 0;   
    c = chr - ' ';//得到偏移后的值         
    if(x > Max_Column - 1)
    {
        x = 0;
        y += 2;
    }
    if(SIZE == 16)
    {
        OLED_Set_Pos(x, y); 
        for(i = 0; i < 8; i ++)
        {
            OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);
        }
        OLED_Set_Pos(x, y + 1);
        for(i = 0; i < 8; i ++)
        {
            OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
        }
    }
    else 
    {   
        OLED_Set_Pos(x, y + 1);
        for(i = 0; i < 6; i ++)
        {
            OLED_WR_Byte(F6x8[c][i],OLED_DATA);
        }
    }
}

void OLED_ShowChar1(uint8_t x, uint8_t y, uint8_t chr)
{       
    uint8_t c = 0, i = 0;   
        c = chr - ' ';//得到偏移后的值         
        if(x > Max_Column - 1)
        {
            x = 0;
            y += 2;
        }
        if(SIZE == 16)
        {
            OLED_Set_Pos(x, y); 
            for(i = 0; i < 6; i ++)
            {
                OLED_WR_Byte(F6x8[c][i], OLED_DATA);
            }
            OLED_Set_Pos(x, y + 1);
            for(i = 0; i < 6; i ++)
            {
                OLED_WR_Byte(F6x8[c][i + 6], OLED_DATA);
            }
        }
        else 
        {   
            OLED_Set_Pos(x, y + 1);
            for(i = 0; i < 6; i ++)
            {
                OLED_WR_Byte(F6x8[c][i],OLED_DATA);
            }
        }
}
//m^n函数
u32 oled_pow(uint8_t m,uint8_t n)
{
    u32 result = 1;  
    while(n --)
    {
        result *= m;
    }    
    return result;
}   

//显示2个数字
//x,y :起点坐标  
//len :数字的位数
//size:字体大小
//mode:模式   0,填充模式;1,叠加模式
//num:数值(0~4294967295);              
void OLED_ShowNum(uint8_t x, uint8_t y, u32 num, uint8_t len, uint8_t size)
{           
    uint8_t t,temp;
    uint8_t enshow = 0;                        
    for(t = 0; t < len; t ++)
    {
        temp = (num / oled_pow(10, len - t - 1)) % 10;
        if(enshow == 0 && t < (len - 1))
        {
            if(temp == 0)
            {
                OLED_ShowChar(x + (size / 2) * t, y, ' ');
                continue;
            }else enshow = 1; 
        }
        OLED_ShowChar(x + (size / 2) * t, y, temp + '0'); 
    }
} 

//显示一个字符号串
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr)
{
    uint8_t j = 0;
    while (chr[j] != '\0')
    {       
        OLED_ShowChar(x, y, chr[j]);
        x += 8;
        if(x > 120)
        {
            x = 0; 
            y += 2;
        }
        j++;
    }
}


//显示汉字
void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no)
{                   
    uint8_t t, adder = 0;
    OLED_Set_Pos(x, y); 
    for(t = 0; t < 16; t ++)
    {
        OLED_WR_Byte(Hzk[2 * no][t], OLED_DATA);
        adder += 1;
    }   
    OLED_Set_Pos(x, y + 1); 
    for(t = 0; t < 16; t ++)
    {   
        OLED_WR_Byte(Hzk[2 * no + 1][t], OLED_DATA);
        adder += 1;
    }                   
}

/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP(uint8_t x0, uint8_t y0,uint8_t x1, uint8_t y1, uint8_t BMP[])
{   
    uint8_t j = 0;
    uint8_t x, y;

    if(y1 % 8 == 0)
    {
        y = y1 / 8;
    }             
    else 
    {
        y = y1 / 8 + 1;
    }

    for(y = y0; y < y1; y ++)
    {
        OLED_Set_Pos(x0, y);
        for(x = x0; x < x1; x ++)
        {      
            OLED_WR_Byte(BMP[j ++], OLED_DATA);         
        }
    }
} 

//初始化SSD1306                        
void OLEDConfiguration(void)
{        
    GPIO_InitTypeDef  GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOG, ENABLE);    //使能PC,D,G端口时钟
    GPIO_InitStructure.GPIO_Pin     = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_3 | GPIO_Pin_8;   //PD3,PD6推挽输出  
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_Out_PP;          //推挽输出
    GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;//速度50MHz
    GPIO_Init(GPIOD, &GPIO_InitStructure);    //初始化GPIOD3,6
    GPIO_SetBits(GPIOD, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_3 | GPIO_Pin_8);   //PD3,PD6 输出高

 #if OLED_MODE == 1

    GPIO_InitStructure.GPIO_Pin = 0xFF; //PC0~7 OUT推挽输出
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC, 0xFF); //PC0~7输出高

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;               //PG13,14,15 OUT推挽输出
    GPIO_Init(GPIOG, &GPIO_InitStructure);
    GPIO_SetBits(GPIOG, GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);                        //PG13,14,15 OUT  输出高
 #else
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;               //PC0,1 OUT推挽输出
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    GPIO_SetBits(GPIOC, GPIO_Pin_0 | GPIO_Pin_1);                        //PC0,1 OUT  输出高

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;               //PG15 OUT推挽输出   RST
    GPIO_Init(GPIOG, &GPIO_InitStructure);
    GPIO_SetBits(GPIOG, GPIO_Pin_15);                        //PG15 OUT  输出高
 #endif
    OLED_RST_Set();
    DelayMs(100);
    OLED_RST_Clr();
    DelayMs(100);
    OLED_RST_Set(); 

    OLED_WR_Byte(0xAE, OLED_CMD);//--turn off oled panel
    OLED_WR_Byte(0x00, OLED_CMD);//---set low column address
    OLED_WR_Byte(0x10, OLED_CMD);//---set high column address
    OLED_WR_Byte(0x40, OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
    OLED_WR_Byte(0x81, OLED_CMD);//--set contrast control register
    OLED_WR_Byte(0xCF, OLED_CMD); // Set SEG Output Current Brightness
    OLED_WR_Byte(0xA1, OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
    OLED_WR_Byte(0xC8, OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
    OLED_WR_Byte(0xA6, OLED_CMD);//--set normal display
    OLED_WR_Byte(0xA8, OLED_CMD);//--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3f, OLED_CMD);//--1/64 duty
    OLED_WR_Byte(0xD3, OLED_CMD);//-set display offset  Shift Mapping RAM Counter (0x00~0x3F)
    OLED_WR_Byte(0x00, OLED_CMD);//-not offset
    OLED_WR_Byte(0xd5, OLED_CMD);//--set display clock divide ratio/oscillator frequency
    OLED_WR_Byte(0x80, OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
    OLED_WR_Byte(0xD9, OLED_CMD);//--set pre-charge period
    OLED_WR_Byte(0xF1, OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
    OLED_WR_Byte(0xDA, OLED_CMD);//--set com pins hardware configuration
    OLED_WR_Byte(0x12, OLED_CMD);
    OLED_WR_Byte(0xDB, OLED_CMD);//--set vcomh
    OLED_WR_Byte(0x40, OLED_CMD);//Set VCOM Deselect Level
    OLED_WR_Byte(0x20, OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
    OLED_WR_Byte(0x02, OLED_CMD);//
    OLED_WR_Byte(0x8D, OLED_CMD);//--set Charge Pump enable/disable
    OLED_WR_Byte(0x14, OLED_CMD);//--set(0x10) disable
    OLED_WR_Byte(0xA4, OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
    OLED_WR_Byte(0xA6, OLED_CMD);// Disable Inverse Display On (0xa6/a7) 
    OLED_WR_Byte(0xAF, OLED_CMD);//--turn on oled panel

    OLED_WR_Byte(0xAF, OLED_CMD); /*display ON*/ 
    OLED_Display_Status(Display_Clear);
    OLED_Set_Pos(0, 0);     
}  

由于作者能力有限,有不妥之处欢迎指正,邮箱[email protected]

猜你喜欢

转载自blog.csdn.net/huazhen1234/article/details/80313930