STM32F103-OLED使用教程

1. OLED屏介绍

  • OLED(Organic Light Emitting Diode):有机发光二极管
  • OLED显示屏:性能优异的新型显示屏,具有功耗低、相应速度快、宽视角、轻薄柔韧等特点
    本文使用的是0.96寸OLED模块,小巧玲珑、占用接口少、简单易用,是电子设计中非常常见的显示屏模块。

OLED屏幕特点

供电:3~5.5V
通信协议:I2C/SPI
分辨率:128*64

OLED屏分两种,一种是4针OLED,通过IIC总线通信,另一种是7针OLED,通过SPI总线通信如下图所示:

本文使用的为4针OLED屏,接线说明如下:

在这里插入图片描述

OLED屏幕显存

在这里插入图片描述
OLED本身是没有显存的,他的现存是依赖SSD1306提供的,而SSD1306提供一块显存。
SSD1306显存总共为128*64bit大小,SSD1306将这些显存分成了8页。每页包含了128个字节。

OLED屏幕原理

STM32内部建立一个缓存(共128*8个字节),每次修改的时候,只是修改STM32上的缓存(实际上就是SRAM),修改完后一次性把STM32上的缓存数据写入到OLED的GRAM。这个方法也有坏处,对于SRAM很小的单片机(51系列)就比较麻烦。

OLED屏幕常用指令

在这里插入图片描述

  • 0X81: 设置对比度。包含两个字节,第一个0X81为命令,随后方法是的一个字节要设置这个对比度,值越大屏幕越亮。

  • 0XAE/0XAF: 0XAE为关闭显示命令,0XAF为开启显示命令。

  • 0X8D: 电荷泵设置,包含两个字节,第一个为命令字,第二个为设置值,第二个字节的BIT2表示电荷泵的开关状态,该位为1开启电荷泵,为0则关闭。模块初始化的时候,这个必须要开启,否则看不到屏幕显示。

  • 0XB0~B7:用于设置页地址,其低三位的值对应GRAM页地址。

  • 0X00~0X0F:用于设置显示时的起始列地址低四位。

  • 0X10~0X1F: 用于设置显示时的起始列地址高四位。

2. OLED如何显示一个点

OLED屏幕分为页寻址模式,水平地址模式,垂直地址模式。
本文主要介绍用的最多的页寻址模式,页寻址模式如下图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

首先把整个OLED屏幕分成八页,也就是把OLED的屏幕把宽平均分成了八份。
比如,想在第3行第0列的开头显示一个点,那就是按位来配置,0000 1000(0x08)。

3. 配置OLED屏幕

我们配置硬件IIC的步骤就是根据下面这张时序图,发送一次数据后不断获取不同的应答即可。
在这里插入图片描述

硬件IIC配置:

#include "stm32f10x.h"
#include "oled.h"
 
void IIC_Configuration(void)
{
	 GPIO_InitTypeDef  GPIO_InitStructure;
	 I2C_InitTypeDef   I2C_InitStructure;
	
	 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE	);
     RCC_APB1PeriphClockCmd( RCC_APB1Periph_I2C1, ENABLE	);
	 
	 //PB6--SCL   PB7--SDL
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	 GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	 I2C_DeInit(I2C1);
	 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	 I2C_InitStructure.I2C_ClockSpeed = 400000;
	 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	 I2C_InitStructure.I2C_OwnAddress1 = 0x30;
     I2C_Init(I2C1, &I2C_InitStructure);
	 I2C_Cmd(I2C1, ENABLE);
 
}
 
void I2C_WriteByte(uint8_t addr,uint8_t data)
{
	while( I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); //检查IIC总线是否繁忙
	
	I2C_GenerateSTART(I2C1, ENABLE);  //开启IIC,发送起始信号
	while(!I2C_CheckEvent(I2C1,  I2C_EVENT_MASTER_MODE_SELECT)); //EV5主模式
 
	I2C_Send7bitAddress(I2C1, OLED_ADDRESS ,  I2C_Direction_Transmitter);  //发送OLED地址
	while(!I2C_CheckEvent(I2C1,  I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); //检查EV6
	
	I2C_SendData(I2C1, addr); //发送寄存器地址
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
	
    I2C_SendData(I2C1, data); //发送数据
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING));
 
    I2C_GenerateSTOP(I2C1, ENABLE);
}

写命令函数&写数据函数:

void WriteCmd(unsigned char IIC_Command)  //写命令
{
	 I2C_WriteByte(0x00,IIC_Command);
}
 
void WriteDat(unsigned char IIC_Data)  //写数据
{
	 I2C_WriteByte(0x40,IIC_Data);
}

OLED初始化:

void OLED_Init(void) //OELD屏幕初始化
{
  delay_ms(100);
	WriteCmd(0xAE); //display off
	WriteCmd(0x20);	//Set Memory Addressing Mode	
	WriteCmd(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
	WriteCmd(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7
	WriteCmd(0xc8);	//Set COM Output Scan Direction
	WriteCmd(0x00); //---set low column address
	WriteCmd(0x10); //---set high column address
	WriteCmd(0x40); //--set start line address
	WriteCmd(0x81); //--set contrast control register
	WriteCmd(0xff); //ÁÁ¶Èµ÷½Ú 0x00~0xff
	WriteCmd(0xa1); //--set segment re-map 0 to 127
	WriteCmd(0xa6); //--set normal display
	WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
	WriteCmd(0x3F); //
	WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
	WriteCmd(0xd3); //-set display offset
	WriteCmd(0x00); //-not offset
	WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
	WriteCmd(0xf0); //--set divide ratio
	WriteCmd(0xd9); //--set pre-charge period
	WriteCmd(0x22); //
	WriteCmd(0xda); //--set com pins hardware configuration
	WriteCmd(0x12);
	WriteCmd(0xdb); //--set vcomh
	WriteCmd(0x20); //0x20,0.77xVcc
	WriteCmd(0x8d); //--set DC-DC enable
	WriteCmd(0x14); //
	WriteCmd(0xaf); //--turn on oled panel
}

设置起点坐标:

void SetPos(unsigned char x,unsigned char y)  //设置起点坐标
{
	WriteCmd(0xb0+y);
	WriteCmd((x&0xf0)>>4|0x10); //取高位
	WriteCmd((x&0x0f)|0x01);    //取低位

全屏填充(可以全屏填充,也可用于清屏):

void OLED_Fill(unsigned char Fill_Data)  //全屏填充
{
	unsigned char m,n;
	
	for(m=0;m<8;m++){
		WriteCmd(0xb0+m);
		WriteCmd(0x00);
		WriteCmd(0x10);
	
	  for(n=0;n<128;n++){
		WriteDat(Fill_Data);
		}
	}
}

清屏:

void OLED_Clean(void)  //清屏
{
	OLED_Fill(0x00);
}

打开/关闭OLED:

void OLED_ON(void)   //打开OLED
{
	WriteCmd(0X8D);   //设置电荷泵
	WriteCmd(0X14);   //开启电荷泵
	WriteCmd(0XAF);   //OLED唤醒
}
 
void OLED_OFF(void)  //关闭OLED
{
	WriteCmd(0X8D);   //设置电荷泵
	WriteCmd(0X10);   //关闭电荷泵
	WriteCmd(0XAE);   //关闭OLED
}

4. OLED显示字符串和汉字

OLED显示字符串:

//显示字符串
void OLED_ShowStr(unsigned char x,unsigned char y,unsigned char ch[],unsigned TextSize)
{
    unsigned char c = 0,i = 0,j = 0;
	  switch(TextSize)
		{
			case 1:   //8*16模式
			{
				while(ch[j] != '\0')
				{
				   c = ch[j] - 32;
					if(x>126)
					{
					    x= 0;
						  y++;					
					}
					OLED_SetPos(x,y);
					for(i=0;i<6;i++)
           WriteDat( F6x8[c][i] );
					x+=6 ;
					j++;				
				}
				
				}break;
			case 2:    //16*16模式
			{
			   while(ch[j] !='\0')
				 {
						 c= ch[j] - 32;
					 if(x >120)
					 {
							 x = 0;
							 y++ ;
					 }
					 OLED_SetPos(x,y);
					 for(i = 0;i<8;i++)
					 WriteDat( F8X16[c*16+i] );
					 OLED_SetPos(x,y+1);
					 for(i = 0;i<8;i++)
					 WriteDat( F8X16[c*16+i+8] );
					 x+=8;
					 j++;
			 }	 
		}break;
			
	}
}	

OLED显示汉字:

//显示汉字 (x:横坐标  y:纵坐标  N:字数)
void OLED_ShowCN(unsigned char x,unsigned char y,unsigned char N)
{
    unsigned char wm=0;
	  unsigned int addr = 32*N;
		OLED_SetPos(x,y);
    for(wm=0;wm<16;wm++)
	{
		WriteDat( F16X16[addr]);
    addr +=1;	
	}
	 OLED_SetPos(x,y+1);
   for(wm=0;wm<16;wm++)
	{
		WriteDat( F16X16[addr]);
    addr +=1;	
	}
 
}

然后通过取字模软件(PCtoLCD2002),输入我们想显示的汉字和大小,通过软件生成字库,再添加到我们代码中的字库文件里。

以我自己的工程为例,如下:
在这里插入图片描述

5. OLED屏幕显示图片

//显示图片
//x0:横坐标;y0:纵坐标;x1:图片起点;y1:所占页数;BMP[]:选用的结构体名称
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
	unsigned int j=0;
	unsigned char x,y;
	
	if(y1%8 == 0)
		y = y1/8;
	else
		y = y1/8 +1;
	for(y=y0;y<y1;y++)
	{
				OLED_SetPos(x0,y);
       for(x=x0;x<x1;x++)
		{	
				WriteDat(BMP[j++]);
		}		
	}
}

步骤:

  1. 选一张照片,保存格式改为.png
  2. 将大小调整为跟我们的屏幕一样的分辨率(128*64)
  3. 改完大小之后再保存为BMP格式。
  4. 打开我们的取模软件(Image2Lcd v2.9),生成一个文档。
  5. 然后把数组里面的内容粘贴到BMP1的数组里面。

最终效果:在这里插入图片描述

6. 总结

本文使用的是4针OLED屏,是通过硬件IIC驱动,当然大家也可以通过软件IIC实现,使用引脚更加灵活。同时大家也可以使用7针的OLED屏,通过SPI进行驱动。
文献:https://blog.csdn.net/aaaaaaaa123345/article/details/124350330

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基于STM32F103OLED的波形显示是一种通过STM32F103微控制器驱动OLED屏幕显示波形的应用。STM32F103是一款基于ARM Cortex-M3内核的单片机,具有丰富的外设资源,包括GPIO、定时器、SPI等。OLED(有机发光二极管)是一种具有自发光和高对比度特点的显示技术。 首先,我们需要将STM32F103OLED连接起来。通过SPI接口或I2C接口连接STM32F103OLED屏幕。然后,在STM32F103的程序中,我们需要配置SPI或I2C的相关寄存器,设置通信参数和时钟频率,以确保STM32F103能够正确地与OLED通信。 接下来,我们需要准备波形数据。可以通过STM32F103的ADC模块进行模拟信号采样,或者通过其他方式获取数字化的波形数据。将获取的波形数据存储在STM32F103的存储器中,例如数组或缓冲区。 然后,在STM32F103的程序中,我们需要编写相应的代码来读取波形数据,并将其发送给OLED屏幕进行显示。根据OLED驱动程序,我们可以通过SPI或I2C发送命令和数据来控制OLED的显示。通过逐点方式,将波形数据发送给OLED,以在屏幕上显示出波形。 为了实时显示波形,我们可以使用定时器中断来定时刷新屏幕上的波形数据。在每个定时器中断中,我们可以更新屏幕的显示,将新的波形数据发送给OLED进行更新。 此外,为了更好地显示波形,我们可以添加一些图形化的界面元素,例如坐标轴、刻度线等,以增强用户的可视化体验。 总而言之,基于STM32F103OLED的波形显示是一种通过STM32F103微控制器驱动OLED屏幕显示波形的应用。通过合理的硬件连接和程序设计,我们可以实现波形的实时显示,并提供更好的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Dzhuser

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

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

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

打赏作者

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

抵扣说明:

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

余额充值