51单片机学习——OLED屏

本文详细介绍了如何通过编程实现OLED屏幕的写命令、图像显示,包括GDDRAM的使用、寻址模式设置、初始化过程以及解决显示问题的方法,如雪花屏和列地址调整。还涉及了I2C通信和字符显示的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OLED屏幕学习

1、OLED写命令

1.1、写数据

1.2、编程实现

2、OLED图像显示

2.1、GDDRAM是位映射静态RAM,保存要显示的位模式。RAM大小128 x 64,RAM分为8个页面,从PAGE0到PAGE7,用于单色128x64点阵显示。

以一列0列(SEG0)为例,Page2由8位组成,组成如下图

2.2、寻址模式

   页地址模式

   水平模式

   垂直地址模式

   寻址命令地址表(配置寻址模式)

   选择Page

   配置页寻址模式:1、发送cmd:0x20  2、再发送0x02

配置好后,默认到Page0的0列,若再0列写入数据后,默认去1列。

2.3、初始化OLED

void OLED_INIT()
{
	OLED_Write_Cmd(0xAE);//--display off
	OLED_Write_Cmd(0x00);//---set low column address
	OLED_Write_Cmd(0x10);//---set high column address
	OLED_Write_Cmd(0x40);//--set start line address
	OLED_Write_Cmd(0xB0);//--set page address
	OLED_Write_Cmd(0x81); // contract control
	OLED_Write_Cmd(0xFF);//--128
	OLED_Write_Cmd(0xA1);//set segment remap
	OLED_Write_Cmd(0xA6);//--normal / reverse
	OLED_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
	OLED_Write_Cmd(0x3F);//--1/32 duty
	OLED_Write_Cmd(0xC8);//Com scan direction
	OLED_Write_Cmd(0xD3);//-set display offset
	OLED_Write_Cmd(0x00);//
	
	OLED_Write_Cmd(0xD5);//set osc division
	OLED_Write_Cmd(0x80);//
	
	OLED_Write_Cmd(0xD8);//set area color mode off
	OLED_Write_Cmd(0x05);//
	
	OLED_Write_Cmd(0xD9);//Set Pre-Charge Period
	OLED_Write_Cmd(0xF1);//
	
	OLED_Write_Cmd(0xDA);//set com pin configuartion
	OLED_Write_Cmd(0x12);//
	
	OLED_Write_Cmd(0xDB);//set Vcomh
	OLED_Write_Cmd(0x30);//
	
	OLED_Write_Cmd(0x8D);//set charge pump enable
	OLED_Write_Cmd(0x14);//
	
	OLED_Write_Cmd(0xAF);//--turn on oled panel
}

2.4、在OLED屏幕上显示一条线

2.4.1、选择列地址显示

出现问题:1、雪花屏幕   2、Page0的终止列是Page5起始列

2.4.1.1、解决列问题:

2.4.1.2、解决雪花屏:

   A、增加清屏函数

   B、屏幕VCC连接3V

2.5、在屏屏幕上显示爱你一万年

   1、用字模软件生成对应字符的矩阵

   2、一次给屏幕发送数据

2.5.1、代码实现

#include "reg52.h"
#include "intrins.h"

sbit SCL = P0^1;
sbit SDA = P0^3;

void IIC_Start()
{
	SCL = 0;
	SDA = 1;
	SCL = 1;			//SCL一直为高电平		
	_nop_();			//SDA为高电平,持续时间>4.7us
	SDA = 0;			//SDA跳变成低电平,表示起始信号
	_nop_();			//低电平持续时间>4us
}

void IIC_Stop()
{
	SCL = 0;
	SDA = 0;
	SCL = 1;
	_nop_();			//SDA为低电平,持续时间>4us
	SDA = 1;			//跳变到高电平,终止信号
	_nop_();			//高电平持续时间>4.7us
}

char IIC_ACK()	//判断是否有效应答
{
	char flag;
	SDA = 1;			//在脉冲9释放数据线
	_nop_();			//等待一段时间
	SCL = 1;			//在SCL高电平期间去读取SDA的状态
	_nop_();
	flag = SDA;		//在SCL为高电平期间,读取SDA信号
	_nop_();
	SCL = 0;
	_nop_();
	
	return flag;	//返回读取的SDA状态
}

void IIC_Send_Byte(char dataSend)			//发送一个字节时序
{
	char i;
	
	for(i = 0 ; i<8 ; i++){		//每循环一次发送1位数据
		SCL = 0;								//拉低SCL,让SDA做好发数据准备
		SDA = dataSend & 0x80;	//建立发送数据,&操作取出发送的最高位
		_nop_();								//发送数据建立时间
		SCL = 1;								//SCL为高电平,开始发送数据
		_nop_();								//发送数据时间
		SCL = 0;								//发送完毕
		_nop_();
		dataSend <<= 1;					// 左移将第二个数据放到最高位,以便下一次发送
	}
}

void OLED_Write_Cmd(char dataCmd)
{
		//1.Start 开始信号
	IIC_Start();
	//2. Slave Address从机地址(011110(SA0)(R/W#)  SA0控制接入多个显示屏的选择 R/W#设置0为写入模式)
	IIC_Send_Byte(0x78); 				//0111 1000   0x78
	//3. 是否有效应答
	IIC_ACK();
	//4. Control byte  ((C0)(D/C)000000)   C0设置0表示传输的内容为Data byte   D/0为0写入指令  为1写入数据  
	IIC_Send_Byte(0x00);				// 0000 0000   0x00
	//5. ACK
	IIC_ACK();
	//6. 写入指令/数据
	IIC_Send_Byte(dataCmd);		//写入数据
	//7. ACK
	IIC_ACK();
	//8.STOP
	IIC_Stop();
}

void OLED_Write_Data(char dataData)
{
	//1.Start(IIC_Start) 开始信号
	IIC_Start();
	//2. Slave Address从机地址(011110(SA0)(R/W#)  SA0控制接入多个显示屏的选择 R/W#设置0为写入模式)
	IIC_Send_Byte(0x78); 				//0111 1000   0x78
	//3. 是否有效应答
	IIC_ACK();
	//4. Control byte  ((C0)(D/C)000000)   C0设置0表示传输的内容为Data byte   D/0为0写入指令  为1写入数据  
	IIC_Send_Byte(0x40);				// 0100 0000   0x40
	//5. ACK
	IIC_ACK();
	//6. 写入指令/数据
	IIC_Send_Byte(dataData);		//写入数据
	//7. ACK
	IIC_ACK();
	//8.STOP
	IIC_Stop();
}

void OLED_INIT()
{
	OLED_Write_Cmd(0xAE);//--display off
	OLED_Write_Cmd(0x00);//---set low column address
	OLED_Write_Cmd(0x10);//---set high column address
	OLED_Write_Cmd(0x40);//--set start line address
	OLED_Write_Cmd(0xB0);//--set page address
	OLED_Write_Cmd(0x81); // contract control
	OLED_Write_Cmd(0xFF);//--128
	OLED_Write_Cmd(0xA1);//set segment remap
	OLED_Write_Cmd(0xA6);//--normal / reverse
	OLED_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)
	OLED_Write_Cmd(0x3F);//--1/32 duty
	OLED_Write_Cmd(0xC8);//Com scan direction
	OLED_Write_Cmd(0xD3);//-set display offset
	OLED_Write_Cmd(0x00);//
	
	OLED_Write_Cmd(0xD5);//set osc division
	OLED_Write_Cmd(0x80);//
	
	OLED_Write_Cmd(0xD8);//set area color mode off
	OLED_Write_Cmd(0x05);//
	
	OLED_Write_Cmd(0xD9);//Set Pre-Charge Period
	OLED_Write_Cmd(0xF1);//
	
	OLED_Write_Cmd(0xDA);//set com pin configuartion
	OLED_Write_Cmd(0x12);//
	
	OLED_Write_Cmd(0xDB);//set Vcomh
	OLED_Write_Cmd(0x30);//
	
	OLED_Write_Cmd(0x8D);//set charge pump enable
	OLED_Write_Cmd(0x14);//
	
	OLED_Write_Cmd(0xAF);//--turn on oled panel
}

void OLED_Clear()				//给屏幕写入0
{
	unsigned char i,j;
	for(i = 0 ; i<8 ; i++){		//Page0~Page
		//	选择Page
		OLED_Write_Cmd( 0xB0 + i);
		//	每选择一次Page,重新让光标指向0列
		OLED_Write_Cmd(0x00);
		OLED_Write_Cmd(0x10);
		for(j = 0 ; j<128 ; j++){		//显示屏大小128x64
			OLED_Write_Data(0);		//0列到127列依次写入0,每写入数据,列地址自动偏移
		}
	}
}

/*--  文字:  爱  --*/
/*--  宋体18;  此字体下对应的点阵为:宽x高=24x24   --*/   //3Page  列 = (16*4+8)/3=24列
code char Love[3][24] = {0x00,0x00,0x00,0x88,0x88,0x18,0x78,0xF8,0xE8,0x48,0x1C,0x7C,0xFC,0xEC,0x0C,0x84,\
						0xE4,0x7E,0x3E,0x16,0x86,0x84,0x00,0x00,\
						0x00,0x0C,0x0E,0x1F,0x37,0x11,0x11,0x11,0xF1,0xFF,0xFF,0x5D,0x51,0x51,0x51,0x51,\
						0xD1,0xF1,0xD9,0x1F,0x17,0x03,0x01,0x00,\
						0x00,0x40,0x60,0x30,0x70,0x58,0x4E,0x67,0x63,0x21,0x33,0x37,0x1E,0x1C,0x1E,0x3F,\
						0x33,0x31,0x70,0x70,0x60,0x60,0x20,0x00};

/*--  文字:  你  --*/
/*--  宋体18;  此字体下对应的点阵为:宽x高=24x24   --*/
code char You[3][24] = {0x00,0x00,0x00,0x00,0xC0,0xF0,0xFE,0x3E,0x0E,0x04,0xC0,0xF8,0x7E,0x5E,0x44,0x40,\
						0x40,0x40,0x40,0xC0,0xE0,0xE0,0xC0,0x00,\
						0x20,0x38,0x1C,0x0F,0xFF,0xFF,0xFF,0x09,0x0C,0xC7,0xFB,0xF9,0x38,0x10,0xFF,0xFF,\
						0xFF,0x10,0x32,0xF3,0xE1,0xC0,0x00,0x00,\
						0x00,0x00,0x00,0x00,0x7F,0x7F,0x7F,0x0C,0x0E,0x07,0x03,0x30,0x30,0x70,0x7F,0x7F,\
						0x3F,0x00,0x00,0x00,0x03,0x0F,0x0F,0x00};

/*--  文字:  一  --*/
/*--  宋体18;  此字体下对应的点阵为:宽x高=24x24   --*/
code char One[3][24] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
						0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
						0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,\
						0x08,0x08,0x08,0x0C,0x0C,0x0C,0x08,0x00,\
						0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
						0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

/*--  文字:  万  --*/
/*--  宋体18;  此字体下对应的点阵为:宽x高=24x24   --*/
code char Wan[3][24] = {0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x90,0xF0,0xF0,0xF0,0x10,0x10,0x10,0x10,\
						0x10,0x10,0x10,0x18,0x18,0x18,0x10,0x00,\
						0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x3F,0x03,0x02,0x02,0x02,0x02,\
						0x02,0xFE,0xFF,0xFF,0x02,0x00,0x00,0x00,\
						0x00,0x40,0x60,0x70,0x38,0x1C,0x0F,0x07,0x03,0x00,0x00,0x00,0x18,0x18,0x30,0x70,\
						0x78,0x3F,0x3F,0x0F,0x00,0x00,0x00,0x00};

/*--  文字:  年  --*/
/*--  宋体18;  此字体下对应的点阵为:宽x高=24x24   --*/
code char Age[3][24] = {0x00,0x00,0x00,0xC0,0xF0,0x7C,0x3E,0x1E,0x16,0x10,0x10,0xF0,0xF0,0xF0,0x10,0x10,\
						0x10,0x10,0x10,0x18,0x18,0x10,0x00,0x00,\
						0x00,0x82,0x83,0x81,0xFC,0xFE,0xFC,0x84,0x84,0x84,0x84,0xFF,0xFF,0xFF,0x84,0x84,\
						0x84,0x86,0x86,0x86,0xC4,0xC0,0x80,0x00,\
						0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x7F,0x7F,0x00,0x00,\
						0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
void Print()
{
	char i,j;
	char ilen = sizeof(Love)/sizeof(Love[0]);
	char jlen = sizeof(Love[0])/sizeof(Love[0][0]);
	for(i = 0 ; i<ilen; i++){
		OLED_Write_Cmd(0xB0 + i);			//选择Page0 1011 0000  0XB0
		//	每选择一次Page,重新让光标指向0列
		OLED_Write_Cmd(0x00);
		OLED_Write_Cmd(0x10);
		for(j = 0 ; j<jlen ; j++){
			OLED_Write_Data(Love[i][j]);
		}
		for(j = 0 ; j<jlen ; j++){
			OLED_Write_Data(You[i][j]);
		}
		for(j = 0 ; j<jlen ; j++){
			OLED_Write_Data(One[i][j]);
		}
		for(j = 0 ; j<jlen ; j++){
			OLED_Write_Data(Wan[i][j]);
		}
		for(j = 0 ; j<jlen ; j++){
			OLED_Write_Data(Age[i][j]);
		}
}
}

void main()
{
	//	1.初始化显示屏
	OLED_INIT();
	//	2.选择寻址模式
	OLED_Write_Cmd(0x20);
	OLED_Write_Cmd(0x02);			//页寻址模式 光标默认在Page0的0列
	//	2.1清屏
	OLED_Clear();
/*	
	//  3.选择Page
	OLED_Write_Cmd(0xB0 + 0);			//选择Page0 1011 0000  0XB0
	//	每选择一次Page,重新让光标指向0列
	OLED_Write_Cmd(0x00);
	OLED_Write_Cmd(0x10);
*/
	Print();
	
	while(1);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值