365bet最稳定网址-365bet官网注册开户-77365bet体育在线投注

实用指南:OLED显示屏详解(IIC协议0.96寸 STM32)

实用指南:OLED显示屏详解(IIC协议0.96寸 STM32)

目录 一、介绍

二、模块原理

1.原理图

2.工作原理:SSD1306显存与命令

三、程序设计

main.c文件

oled.h文件

oled.c文件

四、实验效果

五、资料获取

项目分享

一、介绍 OLED是有机发光二极管,又称为有机电激光显示(Organic Electroluminescence Display, OLED)。OLED由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术

以下是OLED显示屏的参数:

尺寸

0.96寸

模块电压

DC:3~5V

分辨率

128×64

驱动

SSD1306

管脚数

4针

接口

IIC

工作温度

-20℃~70℃

哔哩哔哩视频链接:

https://www.bilibili.com/video/BV17Z421K7vV/?share_source=copy_web&vd_source=097fdeaf6b6ecfed8a9ff7119c32faf2

(资料分享见文末)

二、模块原理1.原理图

以下为OLED显示屏的引脚描述

引脚名称

描述

VCC

供给电压3~5V

SCL

I2C总线时钟线

SDA

I2C总线数据线

GND

电源地

2.工作原理:SSD1306显存与命令

SSD1306的显存总共为128*64bit大小,其将这些显存分为了8页。每页包含了128个字节,总共8页,这样刚好是128*64的点阵大小。

命令0X81:设置对比度。包含两个字节,第一个0X81为命令,随后发送的一个字节为要设置的对比度的值。这个值设置得越大屏幕就越亮。命令0XAE/0XAF:0XAE为关闭显示命令;0XAF为开启显示命令。命令0XB0~B7:用于设置页地址,其低三位的值对应着GRAM的页地址。命令0X00~0X0F:用于设置显示时的起始列地址低四位。命令0X10~0X1F:用于设置显示时的起始列地址高四位。三、程序设计使用STM32F103C8T6将中英文字符、数字和图片显示在OLED显示屏上

main.c文件

#include "stm32f10x.h"

#include "led.h"

#include "usart.h"

#include "delay.h"

#include "dht11.h"

#include "oled.h"

#include "bmp.h"

/*****************辰哥单片机设计******************

STM32

* 项目 : OLED显示屏实验

* 版本 : V1.0

* 日期 : 2024.8.7

* MCU : STM32F103C8T6

* 接口 : 参看oled.h

* BILIBILI : 辰哥单片机设计

* CSDN : 辰哥单片机设计

* 作者 : 辰哥

**********************BEGIN***********************/

int main(void)

{

SystemInit();//配置系统时钟为72M

delay_init(72);

LED_Init();

LED_On();

USART1_Config();//串口初始化

OLED_Init();

printf("Start \n");

delay_ms(1000);

//OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode)

//x,y:起点坐标 num:汉字对应的序号 mode:0,反色显示;1,正常显示

OLED_ShowChinese(0,32,0,16,1); //你

OLED_ShowChinese(32,32,1,16,1);//好

OLED_ShowChinese(64,32,2,16,1);//世

OLED_ShowChinese(96,32,3,16,1);//界

//OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode);

//x,y:起点坐标 size1:字体大小 *chr:字符串起始地址 mode:0,反色显示;1,正常显示

//OLED_ShowString(0,16,"HELLO WORLD!",16,1);

//OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode);

//x,y :起点坐标 num :要显示的数字 len :数字的位数 size:字体大小 mode:0,反色显示;1,正常显示

//OLED_ShowNum(0,32,666,3,24,1);

//OLED_Clear();

//OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode)

//x,y:起点坐标 sizex,sizey,图片长宽 BMP[]:要写入的图片数组 mode:0,反色显示;1,正常显示

// OLED_ShowPicture(0,0,128,64,BMP4,0);

while (1)

{

LED_Toggle();

delay_ms(500);

}

}

oled.h文件

#ifndef __OLED_H

#define __OLED_H

#include "sys.h"

#include "stdlib.h"

/*****************辰哥单片机设计******************

STM32

* 文件 : OLED显示屏h文件

* 版本 : V1.0

* 日期 : 2024.8.7

* MCU : STM32F103C8T6

* 接口 : 见代码

* BILIBILI : 辰哥单片机设计

* CSDN : 辰哥单片机设计

* 作者 : 辰哥

**********************BEGIN***********************/

//----------------OLED端口定义-----------------

/***************根据自己需求更改****************/

#define OLED_SCL_PROT GPIOB

#define OLED_SCL_PIN GPIO_Pin_11

#define OLED_SCL_GPIO_CLK RCC_APB2Periph_GPIOB

#define OLED_SDA_PROT GPIOB

#define OLED_SDA_PIN GPIO_Pin_10

#define OLED_SDA_GPIO_CLK RCC_APB2Periph_GPIOB

/*********************END**********************/

#define OLED_SCL_Clr() GPIO_ResetBits(OLED_SCL_PROT,OLED_SCL_PIN)//SCL

#define OLED_SCL_Set() GPIO_SetBits(OLED_SCL_PROT,OLED_SCL_PIN)

#define OLED_SDA_Clr() GPIO_ResetBits(OLED_SDA_PROT,OLED_SDA_PIN)//DIN

#define OLED_SDA_Set() GPIO_SetBits(OLED_SDA_PROT,OLED_SDA_PIN)

#define OLED_CMD 0 //写命令

#define OLED_DATA 1 //写数据

void OLED_ClearPoint(u8 x,u8 y);

void OLED_ColorTurn(u8 i);

void OLED_DisplayTurn(u8 i);

void OLED_I2C_Start(void);

void OLED_I2C_Stop(void);

void OLED_I2C_WaitAck(void);

void OLED_Send_Byte(u8 dat);

void OLED_WR_Byte(u8 dat,u8 mode);

void OLED_DisPlay_On(void);

void OLED_DisPlay_Off(void);

void OLED_Refresh(void);

void OLED_Clear(void);

void OLED_DrawPoint(u8 x,u8 y,u8 t);

void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode);

void OLED_DrawCircle(u8 x,u8 y,u8 r);

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode);

void OLED_ShowChar6x8(u8 x,u8 y,u8 chr,u8 mode);

void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode);

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode);

void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode);

void OLED_ScrollDisplay(u8 num,u8 space,u8 mode);

void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode);

void OLED_Init(void);

#endif

oled.c文件

#include "oled.h"

#include "stdlib.h"

#include "oledfont.h"

#include "delay.h"

/*****************辰哥单片机设计******************

STM32

* 文件 : OLED显示屏c文件

* 版本 : V1.0

* 日期 : 2024.8.7

* MCU : STM32F103C8T6

* 接口 : 见代码

* BILIBILI : 辰哥单片机设计

* CSDN : 辰哥单片机设计

* 作者 : 辰哥

**********************BEGIN***********************/

u8 OLED_GRAM[144][8];

//反显函数

void OLED_ColorTurn(u8 i)

{

if(i==0)

{

OLED_WR_Byte(0xA6,OLED_CMD);//正常显示

}

if(i==1)

{

OLED_WR_Byte(0xA7,OLED_CMD);//反色显示

}

}

//屏幕旋转180度

void OLED_DisplayTurn(u8 i)

{

if(i==0)

{

OLED_WR_Byte(0xC8,OLED_CMD);//正常显示

OLED_WR_Byte(0xA1,OLED_CMD);

}

if(i==1)

{

OLED_WR_Byte(0xC0,OLED_CMD);//反转显示

OLED_WR_Byte(0xA0,OLED_CMD);

}

}

//延时

void IIC_delay(void)

{

u8 t=3;

while(t--);

}

//起始信号

void OLED_I2C_Start(void)

{

OLED_SDA_Set();

OLED_SCL_Set();

IIC_delay();

OLED_SDA_Clr();

IIC_delay();

OLED_SCL_Clr();

IIC_delay();

}

//结束信号

void OLED_I2C_Stop(void)

{

OLED_SDA_Clr();

OLED_SCL_Set();

IIC_delay();

OLED_SDA_Set();

}

//等待信号响应

void OLED_I2C_WaitAck(void) //测数据信号的电平

{

OLED_SDA_Set();

IIC_delay();

OLED_SCL_Set();

IIC_delay();

OLED_SCL_Clr();

IIC_delay();

}

//写入一个字节

void OLED_Send_Byte(u8 dat)

{

u8 i;

for(i=0;i8;i++)

{

if(dat&0x80)//将dat的8位从最高位依次写入

{

OLED_SDA_Set();

}

else

{

OLED_SDA_Clr();

}

IIC_delay();

OLED_SCL_Set();

IIC_delay();

OLED_SCL_Clr();//将时钟信号设置为低电平

dat1;

}

}

//发送一个字节

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

void OLED_WR_Byte(u8 dat,u8 mode)

{

OLED_I2C_Start();

OLED_Send_Byte(0x78);

OLED_I2C_WaitAck();

if(mode){OLED_Send_Byte(0x40);}

else{OLED_Send_Byte(0x00);}

OLED_I2C_WaitAck();

OLED_Send_Byte(dat);

OLED_I2C_WaitAck();

OLED_I2C_Stop();

}

//开启OLED显示

void OLED_DisPlay_On(void)

{

OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能

OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵

OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕

}

//关闭OLED显示

void OLED_DisPlay_Off(void)

{

OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能

OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵

OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕

}

//更新显存到OLED

void OLED_Refresh(void)

{

u8 i,n;

for(i=0;i8;i++)

{

OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址

OLED_WR_Byte(0x00,OLED_CMD); //设置低列起始地址

OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址

OLED_I2C_Start();

OLED_Send_Byte(0x78);

OLED_I2C_WaitAck();

OLED_Send_Byte(0x40);

OLED_I2C_WaitAck();

for(n=0;n128;n++)

{

OLED_Send_Byte(OLED_GRAM[n][i]);

OLED_I2C_WaitAck();

}

OLED_I2C_Stop();

}

}

//清屏函数

void OLED_Clear(void)

{

u8 i,n;

for(i=0;i8;i++)

{

for(n=0;n128;n++)

{

OLED_GRAM[n][i]=0;//清除所有数据

}

}

OLED_Refresh();//更新显示

}

//画点

//x:0~127

//y:0~63

//t:1 填充 0,清空

void OLED_DrawPoint(u8 x,u8 y,u8 t)

{

u8 i,m,n;

i=y/8;

m=y%8;

n=1if(t){OLED_GRAM[x][i]|=n;}

else

{

OLED_GRAM[x][i]=~OLED_GRAM[x][i];

OLED_GRAM[x][i]|=n;

OLED_GRAM[x][i]=~OLED_GRAM[x][i];

}

// OLED_Refresh();

}

//画线

//x1,y1:起点坐标

//x2,y2:结束坐标

void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode)

{

u16 t;

int xerr=0,yerr=0,delta_x,delta_y,distance;

int incx,incy,uRow,uCol;

delta_x=x2-x1; //计算坐标增量

delta_y=y2-y1;

uRow=x1;//画线起点坐标

uCol=y1;

if(delta_x>0)incx=1; //设置单步方向

else if (delta_x==0)incx=0;//垂直线

else {incx=-1;delta_x=-delta_x;}

if(delta_y>0)incy=1;

else if (delta_y==0)incy=0;//水平线

else {incy=-1;delta_y=-delta_x;}

if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴

else distance=delta_y;

for(t=0;t1;t++)

{

OLED_DrawPoint(uRow,uCol,mode);//画点

xerr+=delta_x;

yerr+=delta_y;

if(xerr>distance)

{

xerr-=distance;

uRow+=incx;

}

if(yerr>distance)

{

yerr-=distance;

uCol+=incy;

}

}

// OLED_Refresh();

}

//x,y:圆心坐标

//r:圆的半径

void OLED_DrawCircle(u8 x,u8 y,u8 r)

{

int a, b,num;

a = 0;

b = r;

while(2 * b * b >= r * r)

{

OLED_DrawPoint(x + a, y - b,1);

OLED_DrawPoint(x - a, y - b,1);

OLED_DrawPoint(x - a, y + b,1);

OLED_DrawPoint(x + a, y + b,1);

OLED_DrawPoint(x + b, y + a,1);

OLED_DrawPoint(x + b, y - a,1);

OLED_DrawPoint(x - b, y - a,1);

OLED_DrawPoint(x - b, y + a,1);

a++;

num = (a * a + b * b) - r*r;//计算画的点离圆心的距离

if(num > 0)

{

b--;

a--;

}

}

// OLED_Refresh();

}

//在指定位置显示一个字符,包括部分字符

//x:0~127

//y:0~63

//size1:选择字体 6x8/6x12/8x16/12x24

//mode:0,反色显示;1,正常显示

void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode)

{

u8 i,m,temp,size2,chr1;

u8 x0=x,y0=y;

if(size1==8)size2=6;

else size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数

chr1=chr-' '; //计算偏移后的值

for(i=0;iif(size1==8)

{temp=asc2_0806[chr1][i];} //调用0806字体

else if(size1==12)

{temp=asc2_1206[chr1][i];} //调用1206字体

else if(size1==16)

{temp=asc2_1608[chr1][i];} //调用1608字体

else if(size1==24)

{temp=asc2_2412[chr1][i];} //调用2412字体

else return;

for(m=0;m8;m++)

{

if(temp&0x01)OLED_DrawPoint(x,y,mode);

else OLED_DrawPoint(x,y,!mode);

temp>>=1;

y++;

}

x++;

if((size1!=8)&&((x-x0)==size1/2))

{x=x0;y0=y0+8;}

y=y0;

}

OLED_Refresh();

}

//显示字符串

//x,y:起点坐标

//size1:字体大小

//*chr:字符串起始地址

//mode:0,反色显示;1,正常显示

void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode)

{

while((*chr>=' ')&&(*chr'~'))//判断是不是非法字符!

{

OLED_ShowChar(x,y,*chr,size1,mode);

if(size1==8)x+=6;

else x+=size1/2;

chr++;

}

OLED_Refresh();

}

//m^n

u32 OLED_Pow(u8 m,u8 n)

{

u32 result=1;

while(n--)

{

result*=m;

}

return result;

}

//显示数字

//x,y :起点坐标

//num :要显示的数字

//len :数字的位数

//size:字体大小

//mode:0,反色显示;1,正常显示

void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode)

{

u8 t,temp,m=0;

if(size1==8)m=2;

for(t=0;tOLED_Pow(10,len-t-1))%10;

if(temp==0)

{

OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);

}

else

{

OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);

}

}

OLED_Refresh();

}

//显示汉字

//x,y:起点坐标

//num:汉字对应的序号

//mode:0,反色显示;1,正常显示

void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode)

{

u8 m,temp;

u8 x0=x,y0=y;

u16 i,size3=(size1/8+((size1%8)?1:0))*size1; //得到字体一个字符对应点阵集所占的字节数

for(i=0;iif(size1==16)

{temp=Hzk1[num][i];}//调用16*16字体

else if(size1==24)

{temp=Hzk2[num][i];}//调用24*24字体

else if(size1==32)

{temp=Hzk3[num][i];}//调用32*32字体

else if(size1==64)

{temp=Hzk4[num][i];}//调用64*64字体

else return;

for(m=0;m8;m++)

{

if(temp&0x01)OLED_DrawPoint(x,y,mode);

else OLED_DrawPoint(x,y,!mode);

temp>>=1;

y++;

}

x++;

if((x-x0)==size1)

{x=x0;y0=y0+8;}

y=y0;

}

OLED_Refresh();

}

//num 显示汉字的个数

//space 每一遍显示的间隔

//mode:0,反色显示;1,正常显示

void OLED_ScrollDisplay(u8 num,u8 space,u8 mode)

{

u8 i,n,t=0,m=0,r;

while(1)

{

if(m==0)

{

OLED_ShowChinese(128,24,t,16,mode); //写入一个汉字保存在OLED_GRAM[][]数组中

t++;

}

if(t==num)

{

for(r=0;r16*space;r++) //显示间隔

{

for(i=1;i144;i++)

{

for(n=0;n8;n++)

{

OLED_GRAM[i-1][n]=OLED_GRAM[i][n];

}

}

OLED_Refresh();

}

t=0;

}

m++;

if(m==16){m=0;}

for(i=1;i144;i++) //实现左移

{

for(n=0;n8;n++)

{

OLED_GRAM[i-1][n]=OLED_GRAM[i][n];

}

}

OLED_Refresh();

}

}

//x,y:起点坐标

//sizex,sizey,图片长宽

//BMP[]:要写入的图片数组

//mode:0,反色显示;1,正常显示

void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode)

{

u16 j=0;

u8 i,n,temp,m;

u8 x0=x,y0=y;

sizey=sizey/8+((sizey%8)?1:0);

for(n=0;nfor(i=0;ifor(m=0;m8;m++)

{

if(temp&0x01)OLED_DrawPoint(x,y,mode);

else OLED_DrawPoint(x,y,!mode);

temp>>=1;

y++;

}

x++;

if((x-x0)==sizex)

{

x=x0;

y0=y0+8;

}

y=y0;

}

}

OLED_Refresh();

}

//OLED的初始化

void OLED_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(OLED_SCL_GPIO_CLK|OLED_SDA_GPIO_CLK, ENABLE); //使能A端口时钟

GPIO_InitStructure.GPIO_Pin = OLED_SCL_PIN;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz

GPIO_Init(OLED_SCL_PROT, &GPIO_InitStructure); //初始化PA0,1

GPIO_SetBits(OLED_SCL_PROT,OLED_SCL_PIN);

GPIO_InitStructure.GPIO_Pin = OLED_SDA_PIN;

GPIO_Init(OLED_SDA_PROT, &GPIO_InitStructure); //初始化PA0,1

GPIO_SetBits(OLED_SDA_PROT,OLED_SDA_PIN);

delay_ms(200);

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(0x30,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_Clear();

OLED_WR_Byte(0xAF,OLED_CMD);

}

四、实验效果

五、资料获取项目分享

相关推荐