OLED屏幕应用实验

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

OLED显示屏:
驱动器型号:使用MCU控制OLED本质上是MCU与屏的驱动控制器进行通信,本项目中OLED的驱动器是SSD1306。
物理尺寸:0.96寸
分辨率:在图像方面,分辨率表示图像上的像素点的个数和分布情况。物理尺寸相同时,分辨率越大,则图片更清晰。
像素点:构成图像的最小单元,每个像素点仅有一种颜色。
与OLED通信:通信方式、通信速度、接口…
开发板: 采用STM32f103系列
原理图:
OLED屏幕应用实验_第1张图片
确定使用SPI通信,分析以上引脚的配置方法:
O_MOSI – 数据传输引脚(主发从收) PB15 推挽复用输出
(这里没有O_MISO引脚原因是驱动OLED时,不需要接收来自OLED的数据)
O_CLK – 时钟引脚 PB13 推挽复用输出
O_RST – 复位引脚(低电平有效) PB14 推挽输出
O_DC – 数据/命令选择引脚 PB12 推挽输出
使用OLED屏时,会传输各类数据,至少包含 字模数据 和 坐标数据,但这些数据都是通过O_MOSI数据线传输的,为了区分各类数据的类型,所以OLED上有O_DC引脚:
当O_DC表示数据选择时,接下来流过O_MOSI的一个字节将视为参数。
当O_DC表示命令选择时,接下来流过O_MOSI的一个字节将视为命令。

三、实验步骤

OLED显示文字
在单色屏下,一般文字的大小为16 x 16 、 24 x 24 或 32 x 32。

  1. 运行取模软件PCtoLCD 2002
  2. 选择“模式”->“字符模式”,点击“选项”,按如下要求

OLED屏幕应用实验_第2张图片

0x00,0x80,0x60,0xF8,0x07,0x40,0x20,0x18,0x0F,0x08,0xC8,0x08,0x08,0x28,0x18,0x00,
0x01,0x00,0x00,0xFF,0x00,0x10,0x0C,0x03,0x40,0x80,0x7F,0x00,0x01,0x06,0x18,0x00,/“你”,0/

0x10,0x10,0xF0,0x1F,0x10,0xF0,0x00,0x80,0x82,0x82,0xE2,0x92,0x8A,0x86,0x80,0x00,
0x40,0x22,0x15,0x08,0x16,0x61,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,/“好”,1/

  1. 设置字宽、字高、字体
  2. 输入文字
  3. 取模,并保存到工程中
    OLED屏幕应用实验_第3张图片
/***********************************
函数名:spi2_init
参数:无
返回值:无
功能:SPI2初始化
备注:SPI2_SCK 	PB13
			SPI2_MOSI	PB15
			连接到OLED
***********************************/
static void spi2_init(void)
{
	GPIO_InitTypeDef gpio_InitStruct;
	SPI_InitTypeDef 	spi_InitStruct;
	/*1.将SPI2相关引脚配置为复用*/
		//激活相应的GPIOx
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB, ENABLE);
		//引脚的推挽复用输出(变为SPI2引脚)
	gpio_InitStruct.GPIO_Mode 	=	GPIO_Mode_AF_PP ; 
	gpio_InitStruct.GPIO_Pin 		= GPIO_Pin_13 | GPIO_Pin_15 ;
	gpio_InitStruct.GPIO_Speed	= GPIO_Speed_2MHz ;
		//导入清单,进行配置
	GPIO_Init (GPIOB, &gpio_InitStruct);

	/*2.激活SPI2,SPI2库函数初始化*/
	RCC_APB1PeriphClockCmd (RCC_APB1Periph_SPI2, ENABLE);//36MHz
		//需要根据模块的不同调整配置
	spi_InitStruct.SPI_BaudRatePrescaler 	= SPI_BaudRatePrescaler_4 ;//36 / 4 == 9M Hz
	spi_InitStruct.SPI_CPHA 							= SPI_CPHA_1Edge ;
	spi_InitStruct.SPI_CPOL 							= SPI_CPOL_Low ;
	spi_InitStruct.SPI_DataSize 					= SPI_DataSize_8b ;	//一帧数据8位
	spi_InitStruct.SPI_FirstBit 					= SPI_FirstBit_MSB ;//先发送数据高位
		//几乎是固定的配置
	spi_InitStruct.SPI_Direction 					= SPI_Direction_2Lines_FullDuplex ;//全双工
	spi_InitStruct.SPI_CRCPolynomial 			= 0x7 ;//CRC多项式
	spi_InitStruct.SPI_Mode 							= SPI_Mode_Master ;//主机模式
	spi_InitStruct.SPI_NSS 								= SPI_NSS_Soft ;//软件管理从设备
	SPI_Init (SPI2, &spi_InitStruct);
	/*3.使能SPI1*/
	SPI_Cmd(SPI2,ENABLE);
}
/***********************************
函数名:spi2_send_recv_byte
参数:u8 data 待发送内容
		若用于接收数据,则该参数任意填写
返回值:u8 		接收内容
	若用于发送数据,则该返回值可以忽略
功能:SPI2发送并接收一个字节
备注:每发送1位数据后,就会在半个周期
后接收到一位数据
***********************************/
static u8 spi2_send_recv_byte(u8 data)
{
	//等待本次可以发送
	while(RESET == SPI_I2S_GetFlagStatus (SPI2, SPI_I2S_FLAG_TXE));
	//往DR写入数据
	SPI_I2S_SendData (SPI2, data);
	//等待数据可以接收
	while(RESET == SPI_I2S_GetFlagStatus (SPI2, SPI_I2S_FLAG_RXNE));
	//从DR读取数据
	return SPI_I2S_ReceiveData (SPI2);
}
/****************************************************************************
函数功能:发送命令函数
函数参数:
	Command :要发送的命令
****************************************************************************/
static void OLED_WriteCom(u8 Command)
{
	DC_L;              		 //数据/命令选择管脚拉低,表示发送的是命令
	spi2_send_recv_byte(Command);  //发送命令
}
/****************************************************************************
函数功能:发送参数函数
函数参数:
	Data :要发送的参数
*****************************************************************************/
static void OLED_WriteData(u8 Data)
{
	DC_H;             //数据/命令选择管脚拉高,表示发送的是数据
	spi2_send_recv_byte(Data);   //发送数据
}
void OLED_init(void)
{
	GPIO_InitTypeDef gpio_InitStruct;
	//1. 引脚初始化
		//激活相应的GPIOx
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB, ENABLE);
		//引脚的推挽输出
	gpio_InitStruct.GPIO_Mode 	=	GPIO_Mode_Out_PP ; 
	gpio_InitStruct.GPIO_Pin 		= GPIO_Pin_12 | GPIO_Pin_14 ;
	gpio_InitStruct.GPIO_Speed	= GPIO_Speed_2MHz ;
		//导入清单,进行配置
	GPIO_Init (GPIOB, &gpio_InitStruct);
	
	//2. SPI2通信接口初始化
	spi2_init();
	
	//3. OLED初始时的命令
	RST_L;
	TIM1_delayms(500); 
	RST_H; 
	TIM1_delayms(500); 
	
	OLED_WriteCom(0xAE); /*display off*/ 

	OLED_WriteCom(0x00); /*set lower column address*/ 

	OLED_WriteCom(0x10); /*set higher column address*/ 

	OLED_WriteCom(0x40); /*set display start line*/ 

	OLED_WriteCom(0xB0); /*set page address*/ 

	OLED_WriteCom(0x81); /*contract control*/ 
	OLED_WriteCom(0xBF); /*对比度值*/ 

	OLED_WriteCom(0xA1); /*set segment remap  左右翻转*/ 

	OLED_WriteCom(0xA6); /*normal / reverse*/ 

	OLED_WriteCom(0xA8); /*multiplex ratio*/ 
	OLED_WriteCom(0x3F); /*duty = 1/64*/ 

	OLED_WriteCom(0xad); /*set charge pump enable*/ 
	OLED_WriteCom(0x8a); /* 0x8a ??VCC */ 

	OLED_WriteCom(0x32); /*0X30---0X33 set VPP 8V */ 

	OLED_WriteCom(0xC8); /*Com scan direction*/ 

	OLED_WriteCom(0xD3); /*set display offset*/ 
	OLED_WriteCom(0x00); /* 0x20 */ 

	OLED_WriteCom(0xD5); /*set osc division*/ 
	OLED_WriteCom(0x80); 

	OLED_WriteCom(0xD9); /*set pre-charge period*/ 
	OLED_WriteCom(0x22); /*0x22*/ 

	OLED_WriteCom(0xDA); /*set COM pins*/ 
	OLED_WriteCom(0x12); 

	OLED_WriteCom(0xdb); /*set vcomh*/ 
	OLED_WriteCom(0x40); 

	OLED_WriteCom(0x8D);
	OLED_WriteCom(0x14);

	OLED_WriteCom(0xAF); /*display ON*/ 

	OLED_Clear(0,0,127,7);	  //清屏函数
}
/*************************************************************************
函数功能:OLED设置坐标函数 
参数说明:
		x:像素点的X轴坐标,x的范围0~127,
		y:像素点的Y轴坐标,y为页的范围0~7
返回值:无
**************************************************************************/
static void OLED_SetPos(u8 x, u8 y) 
{ 
	x = x & 0x7F;	//	x = x % 0x80
	y = y & 7;		//  y = y % 8
	OLED_WriteCom(0xB0 + y);		//页地址设置:光标设置到第y页
	OLED_WriteCom(((x & 0xf0) >> 4)| 0x10);
	OLED_WriteCom((x & 0x0f) | 0x00); 	//列地址设置:光标设置到第x列
} 
//显示汉字
void OLED_DisGB2312(u8 x,u8 y,u8 size,u8 *model)
{
	u8 i,j;
	x = x & 127;
	y = y & 7;
	size = size / 8 * 8;
	for(i = y; i < y + size/8 ; i++)
	{
		OLED_SetPos(x , i);
		for(j = x ; j < x + size ; j++)
		{
			OLED_WriteData(*model);
			model++;
		}
	}
}

在PCtoLCD软件中,若取模设置相同,则英文取模大小是汉字取模大小的一半(字宽减半)。

//英文字符
void OLED_DisASCII(u8 x,u8 y,u8 size,u8 *model)
{
	u8 i,j;
	x = x & 127;
	y = y & 7;
	size = size / 8 * 8;
	for(i = y; i < y + size/8 ; i++)
	{
		OLED_SetPos(x , i);
		for(j = x ; j < x + size/2 ; j++)
		{
			OLED_WriteData(*model);
			model++;
		}
	}
}

四、实验效果

OLED屏幕应用实验_第4张图片

你可能感兴趣的:(C/C++,stm32,stm32)