×
单片机 > 单片机程序设计 > 详情

OLED驱动 0.96寸 硬件SPI驱动(STM32)

发布时间:2020-06-08 发布时间:
|

一、前期准备

单片机:STM32F103ZET6

开发环境:MDK5.14

库函数:标准库V3.5

0.96 OLED模块:淘宝有售

二、实验效果




三、驱动原理

此OLED模块采用SPI通信,也可转成IIC通信,不过要焊接背面的电阻,不建议改IIC,要改请参考具体数据手册。驱动芯片SSD1306,具体命令字详解请见网友SSD1306详解。

需要完整工程或者有问题的请加QQ:1002521871,验证:呵呵。

软件模拟SPI驱动

四、驱动代码

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 RST PBout(10) //RES

#define DC PBout(11) //DC


#define SPI2_NSS_PIN GPIO_Pin_12 //CS

#define SPI2_SCLK_PIN GPIO_Pin_13 //D0

#define SPI2_MISO_PIN GPIO_Pin_14

#define SPI2_MOSI_PIN GPIO_Pin_15 //D1


#define SPI2_NSS PBout(12)


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    


uint8_t SPI2_SendByte(uint8_t byte)

{

while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);  // 等待发送区空

SPI_I2S_SendData(SPI2, byte);     // 发送一个字节  

while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); // 等待接收完一个字节

return SPI_I2S_ReceiveData(SPI2);     // 返回收到的数据 

}



//向SSD1106写入一个字节。

//dat:要写入的数据/命令

//cmd:数据/命令标志 0,表示命令;1,表示数据;

void OLED_WR_Byte(uint8_t dat,OLED_WR_MODE cmd)

{

//uint8_t i;

switch(cmd)

{

case OLED_CMD:

DC = 0;

break;

case OLED_DATA:

DC = 1;

break;

}        

SPI2_NSS = 0;

// for(i = 0; i < 8; i ++)

// {   

// OLED_SCLK_Clr();

// if(dat & 0x80)

//    OLED_SDIN_Set();

// else 

//    OLED_SDIN_Clr();

// OLED_SCLK_Set();

// dat<<=1;   

// }

SPI2_SendByte(dat);

SPI2_NSS = 1;

DC = 1;      

//#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] != '')

{

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)

{  

SPI_InitTypeDef  MySPI;

GPIO_InitTypeDef MyGPIO;


RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_AFIO , ENABLE);


// GPIO配置,设置为PB输出

MyGPIO.GPIO_Pin = SPI2_NSS_PIN;

MyGPIO.GPIO_Speed = GPIO_Speed_50MHz;

MyGPIO.GPIO_Mode = GPIO_Mode_Out_PP;

GPIO_Init(GPIOB, &MyGPIO);

SPI2_NSS = 1;

MyGPIO.GPIO_Pin = SPI2_SCLK_PIN | SPI2_MISO_PIN | SPI2_MOSI_PIN;

MyGPIO.GPIO_Speed = GPIO_Speed_50MHz;

MyGPIO.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOB, &MyGPIO);


// SPI配置

MySPI.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

MySPI.SPI_Mode = SPI_Mode_Master;

MySPI.SPI_DataSize = SPI_DataSize_8b;

MySPI.SPI_CPOL = SPI_CPOL_Low;

MySPI.SPI_CPHA = SPI_CPHA_1Edge;

MySPI.SPI_NSS = SPI_NSS_Soft;

MySPI.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

MySPI.SPI_FirstBit = SPI_FirstBit_MSB;

MySPI.SPI_CRCPolynomial = 7;


SPI_Init(SPI2, &MySPI);

SPI_Cmd(SPI2, ENABLE);


 

MyGPIO.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;

  MyGPIO.GPIO_Mode = GPIO_Mode_Out_PP;  

MyGPIO.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOB, &MyGPIO);   /

DC = 1;



RST = 1;

DelayMs(100);

RST = 0;

DelayMs(100);

RST = 1; 

  

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, OLE


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向