基于Proteus无实物零基础STM32入门自学教程(十一)--0.96“OLED屏显示I2C接口

本文介绍如何在STM32中使用I2C接口驱动0.96英寸OLED显示屏,通过Protues进行仿真实现。讲解了OLED屏的工作原理,提供了MDK代码示例,包括I2C启动、停止、发送字节函数以及OLED写命令、写数据、定位等核心函数。此外,还展示了OLED初始化、清屏、更新显存和字符显示等关键函数,适合初学者实践。

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

本节课我们继续来点亮高端一点的显示器件--OLED显示屏,本来以笔者的经验这种屏比较小很少用在产品上,但是近年来随着校园的学科竞赛的蓬勃发展,这种体积小,超薄形状,显示效果佳的OLED屏越来越受使用者的追捧。最明显的就是基于显示原理的不同,OLED自发光的特性导致其体积小,并且超薄。这也是大部分手机采用OLED屏的原因之一。

一、Protues仿真图

本次选择的是4线制的0.96“OLED,这样只需要2个IO即可完成0.96“OLED显示功能,是最省IO的方案。特别适合大家新手初期的使用。如图所示,PB10连接到I2C的SCL端口,PB11连接到I2C的SDA端口。至此,OLED屏连接完毕,从硬件电路上它比LCD1602更加简单。

OLED屏的工作原理:

i2c的工作原理大家可以自行搜索一下。设计思路是,先驱动IIC的启动和停止,然后即可像驱动LCD一样,完成写命令和写数据的函数,再加上定位函数后,就可以编写最终的显示字符或者数字的单独函数。

二、MDK代码

同学们如果看不懂也没关系,程序已经经过调试,大家可以直接使用。就好像STM32已经由厂家编好了库一样,我们不需纠结底层怎么编成功的,只需要关心怎么调用,如何更改成自己的代码就可以了。

OLED的IIC的驱动代码如下:

/****  I2C启动函数  ****/
void OLED_I2C_Start(void)
{
		OLED_W_SDA(1);
		OLED_W_SCL(1);
		OLED_W_SDA(0);
		OLED_W_SCL(0);
}

/****  I2C停止函数  ****/
void OLED_I2C_Stop(void)
{
		OLED_W_SDA(0);
		OLED_W_SCL(1);
		OLED_W_SDA(1);
}

/****  I2C发送字节函数  ****/
void OLED_I2C_SendByte(uint8_t Byte)
{
		uint8_t i;
		for (i = 0; i < 8; i++)
		{
			OLED_W_SDA(Byte & (0x80 >> i));
			OLED_W_SCL(1);
			OLED_W_SCL(0);
		}
		OLED_W_SCL(1);	//额外的一个时钟,不处理应答信号
		OLED_W_SCL(0);
}

OLED的核心代码如下:


/****  OLED写命令函数,cmd为写入的命令 ****/
void OLED_WriteCommand(uint8_t Command)
{
		OLED_I2C_Start();
		OLED_I2C_SendByte(0x78);		//从机地址
		OLED_I2C_SendByte(0x00);		//写命令
		OLED_I2C_SendByte(Command); 
		OLED_I2C_Stop();
}

/****  OLED写数据函数,dat为写入的数据  ****/
void OLED_WriteData(uint8_t Data)
{
		OLED_I2C_Start();
		OLED_I2C_SendByte(0x78);		//从机地址
		OLED_I2C_SendByte(0x40);		//写数据
		OLED_I2C_SendByte(Data);
		OLED_I2C_Stop();
}

/****  根据OLED的起始地址,定位(x,y)-对应屏幕上的字符坐标,x为0-127,y为0-7  ****/
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
		OLED_WriteCommand(0xB0 | Y);					//设置Y位置
		OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));	//设置X位置低4位
		OLED_WriteCommand(0x00 | (X & 0x0F));			//设置X位置高4位
}

/****  OLED清屏函数  ****/
void OLED_Clear(void)
{  
		uint8_t i, j;
		for (j = 0; j < 8; j++)
		{
			OLED_SetCursor(j, 0);
			for(i = 0; i < 128; i++)
			{
				OLED_WriteData(0x00);
			}
		}
}

/****  OLED更新显存函数  ****/
void OLED_Refresh_Gram(void)
{
		uint8_t i, j;
		for (j = 0; j < 8; j++)
		{
			OLED_SetCursor(j, 0);
			for(i = 0; i < 128; i++)
			{
				OLED_WriteData(OLED_GRAM[i][j]);
			}
		}
}
 

OLED的初始化函数:

/****  OLED初始化函数  ****/
void OLED_Init(void)
{

		OLED_I2C_Init();			    //端口初始化
		
		OLED_WriteCommand(0xAE);	//关闭显示
		OLED_WriteCommand(0xD5);	//设置显示时钟分频值/震荡频率
		OLED_WriteCommand(0x80);  //设置分频比,将时钟设置为100帧/秒
		OLED_WriteCommand(0xA8);	//设置多路复用率
		OLED_WriteCommand(0x3F);  //默认0X3F(1/64) 
		OLED_WriteCommand(0xD3);	//设置显示偏移
		OLED_WriteCommand(0x00);  //默认为0 [5:0],行数.
		
		OLED_WriteCommand(0x40);	//设置显示开始行	
		
		OLED_WriteCommand(0x8D);	//设置充电泵设置
		OLED_WriteCommand(0x14);  //bit2,开启/关闭	
		OLED_WriteCommand(0x20);  //设置内存地址模式
		OLED_WriteCommand(0x02);  //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;
		OLED_WriteCommand(0xA1);	//设置左右方向,0xA1正常 0xA0左右反置
		OLED_WriteCommand(0xC0);	//设置上下方向,0xC8正常 0xC0上下反置
		OLED_WriteCommand(0xDA);	//设置COM引脚硬件配置
		OLED_WriteCommand(0x12);  //[5:4]配置
		
		OLED_WriteCommand(0x81);	//设置对比度控制
		OLED_WriteCommand(0xCF);  //1~255;默认0X7F (亮度设置,越大越亮)
		OLED_WriteCommand(0xD9);  //设置预充电周期
		OLED_WriteCommand(0xF1);  //[3:0],PHASE 1;[7:4],PHASE 2;
		OLED_WriteCommand(0xDB);  //设置VCOMH 电压倍率
		OLED_WriteCommand(0x30);  //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;

		OLED_WriteCommand(0xA4);  //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
		OLED_WriteCommand(0xA6);  //设置显示方式;bit0:1,反相显示;0,正常显示
		OLED_WriteCommand(0xAF);	//开启显示
			
		OLED_Clear();			       	//OLED清屏
}

OLED的显示函数代码:

/****  OLED画点函数,x,y为起点坐标x:0-127,y:0-63,t为0清空,为1填充  ****/
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
		u8 pos,bx,temp=0;
		if(x>127||y>63)return;//超出范围了.
		pos=7-y/8;
		bx=y%8;
		temp=1<<(7-bx);
		if(t)OLED_GRAM[x][pos]|=temp;
		else OLED_GRAM[x][pos]&=~temp;	    
}

/****  OLED字符显示函数,x,y为起点坐标,char为显示字符,size为字体大小12/16/24,mode为0反白显示,1为正常显示  ****/
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode)
{      			    
		u8 temp,t,t1;
		
		chr=chr-' ';//得到偏移后的值		 
    for(t=0;t<csize;t++)
				{   
					if(size==12)temp=asc2_1206[chr][t]; 	 	//调用1206字体
					else if(size==16)temp=asc2_1608[chr][t];	//调用1608字体
					else if(size==24)temp=asc2_2412[chr][t];	//调用2412字体
					else return;								//没有的字库
					for(t1=0;t1<8;t1++)
							{
								if(temp&0x80)OLED_DrawPoint(x,y,mode);
								else OLED_DrawPoint(x,y,!mode);
								temp<<=1;
								y++;
								if((y-y0)==size)
									{
										y=y0;
										x++;
										break;
									}
							}  	 
				}          
}

/****  OLED字符串显示函数,x,y为起点坐标,*p为显示字符串,size为字体大小,mode为0反白显示,1为正常显示  ****/
void OLED_ShowString(u8 x,u8 y, u8 *p,u8 size,u8 mode)
{	
    while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
				{       
						if(x>(128-(size/2))){x=0;y+=size;}
						if(y>(64-size)){y=x=0;OLED_Clear();}
						OLED_ShowChar(x,y,*p,size,mode);	 
						x+=size/2;
						p++;
				}  
}


	
/****  OLED数字显示函数,x,y为起点坐标,num为显示数值,len为数字的位数,size为字体大小  ****/
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{         	
		u8 t,temp;
		u8 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,' ',size,1);
									continue;
								}
							else enshow=1; 
							 
						}
						OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1); 
				}
}

 三、仿真效果和源代码资源

基于Proteus无实物零基础STM32入门自学教程(十一)--0.96“OLED屏显示I2C接口-单片机文档类资源-CSDN下载

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永远都是新手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值