一步步学习0.96寸七针OLED显示屏SPI接口驱动(附移植代码)--基于STM32

1 简单介绍和引脚说明

在这里插入图片描述
拿到手的OLED不会用, 有程序看不懂, 怎么办? 从引脚开始看起. 如果你知道引脚都是干嘛的, 自然就能看懂驱动代码.
先来看一下引脚说明:

GNDVCCD0D1RESDCCS
电源地电源正(3~5.5V)SPI 时钟管脚SPI 数据管脚复位管脚数据和命令控制管脚片选管脚

很显然, GNDVCC接供电电源,没电一切免谈.D0, D1,为SPI接口引脚, 完成数据或者命令的传输, 对于SPI协议不了解的,建议好好学习该协议的相关资料, 毕竟较为常用. CS为片选引脚, 拉低时传输才有效. DC呢,用来选择写数据还是还是写命令. 拉低为写命令, 拉高为写数据. 例如当需要设置对比度, 设置x,y坐标等, 用的是写命令; 当显示像素点时, 用的是写数据. RES为复位引脚,低电平复位,在初始化时拉低一段时间实现复位, 为后续工作做好准备.

2 驱动代码

2.1 初始化

2.1.1 引脚配置

普通引脚即可,全部配置为推挽输出.

2.2 OLED初始化

先复位,

    OLED_RST_Set();
	delay_ms(100);
	OLED_RST_Clr(); //拉低200ms实现复位
	delay_ms(200);
	OLED_RST_Set(); 

接下来开始写相关命令(这里主要是配置SSD1306(OLED驱动芯片)的寄存器, 详见对应的数据手册), 摘取部分代码:

	OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel(关闭oled面板显示)
	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(设置对比度控制控制寄存器)
	                            //写0x81命令后,紧接着写入相应数值(0-255),数值越大亮度越大
	OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness(0xCF表示亮度大小)
	......

最后是开启oled面板, 清除屏幕, 设置坐标为原点

	OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/ 
	OLED_Clear();
	OLED_Set_Pos(0,0);

2.2 功能函数

2.2.1 传输一个Byte的函数
void OLED_WR_Byte(u8 dat,u8 cmd)
{	
	u8 i;			  
	if(cmd) //cmd为1,拉高DC
	  OLED_DC_Set();
	else //cmd为0,拉低DC
	  OLED_DC_Clr();
	  		  
	OLED_CS_Clr();//拉低片选信号

	for(i=0;i<8;i++)//for循环完成一个字节的传输,每个CLK的上升沿,传输一个bit,参考spi传输时序图
	{			  
		OLED_SCLK_Clr();
		if(dat&0x80)
		   OLED_SDIN_Set();
		else 
		   OLED_SDIN_Clr();
		OLED_SCLK_Set();
		dat<<=1;   
	}				 		  
	OLED_CS_Set(); //拉高片选信号
	OLED_DC_Set(); //拉高DC 	  
} 

传输时序图:
在这里插入图片描述

2.2.2 显示一个char的函数
void OLED_ShowChar(u8 x,u8 y,u8 chr)
{      	
	unsigned char c=0,i=0;	
		c=chr-' ';//得到偏移值			
		if(x>Max_Column-1){x=0;y=y+2;} //x超过最后一列, 换行
		if(SIZE ==16)//8*16
		{
			OLED_Set_Pos(x,y);	//设置坐标,其中x为列地址,y为页地址,参考下图分页情况
			for(i=0;i<8;i++) //显示8*16点阵的上半部分
			OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
			
			OLED_Set_Pos(x,y+1);//光标移到下一页
			for(i=0;i<8;i++) //显示8*16点阵的下半部分,参考下图显示示意图
			OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
		}
		else //6*8
		{	
			OLED_Set_Pos(x,y+1);
			for(i=0;i<6;i++)
			OLED_WR_Byte(F6x8[c][i],OLED_DATA);	
		}
}

分页情况:
在这里插入图片描述
8*16格式的字符显示示意图, 从左到右, 从上到下, 先显示上半部分, 然后光标移至下一页, 继续显示下半部分
在这里插入图片描述
其他显示的功能函数, 都是基于字符显示, 有兴趣的自行研究

3 驱动代码链接

https://download.csdn.net/download/weixin_40134414/12302024

写的不够详细不够深入, 后续有更好的理解再继续补充.

  • 32
    点赞
  • 193
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用STM32F103C8T6控制0.96寸4针OLED显示屏代码示例: ``` #include "stm32f10x.h" #include "stm32f10x_spi.h" #include "stm32f10x_gpio.h" #define OLED_DC_PIN GPIO_Pin_5 #define OLED_DC_PORT GPIOB #define OLED_RST_PIN GPIO_Pin_6 #define OLED_RST_PORT GPIOB #define OLED_CS_PIN GPIO_Pin_7 #define OLED_CS_PORT GPIOB void OLED_Init(void); void OLED_Write_Command(uint8_t cmd); void OLED_Write_Data(uint8_t data); void OLED_Set_Pos(uint8_t x, uint8_t y); void OLED_Fill_Screen(uint8_t data); void OLED_Show_String(uint8_t x, uint8_t y, uint8_t *str); void delay_ms(uint16_t n); int main(void) { OLED_Init(); while(1) { OLED_Fill_Screen(0x00); OLED_Show_String(0, 0, "Hello World!"); delay_ms(1000); } } void OLED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_SPI1, ENABLE); GPIO_InitStructure.GPIO_Pin = OLED_DC_PIN | OLED_RST_PIN | OLED_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(OLED_DC_PORT, &GPIO_InitStructure); GPIO_SetBits(OLED_DC_PORT, OLED_CS_PIN | OLED_DC_PIN | OLED_RST_PIN); delay_ms(100); GPIO_ResetBits(OLED_RST_PORT, OLED_RST_PIN); delay_ms(20); GPIO_SetBits(OLED_RST_PORT, OLED_RST_PIN); delay_ms(100); SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); OLED_Write_Command(0xAE); //display off OLED_Write_Command(0x20); //Set Memory Addressing Mode OLED_Write_Command(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid OLED_Write_Command(0xB0); //Set Page Start Address for Page Addressing Mode,0-7 OLED_Write_Command(0xC8); //Set COM Output Scan Direction OLED_Write_Command(0x00); //---set low column address OLED_Write_Command(0x10); //---set high column address OLED_Write_Command(0x40); //--set start line address OLED_Write_Command(0x81); //--set contrast control register OLED_Write_Command(0xFF); OLED_Write_Command(0xA1); //--set segment re-map 0 to 127 OLED_Write_Command(0xA6); //--set normal display OLED_Write_Command(0xA8); //--set multiplex ratio(1 to 64) OLED_Write_Command(0x3F); // OLED_Write_Command(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content OLED_Write_Command(0xD3); //-set display offset OLED_Write_Command(0x00); //-not offset OLED_Write_Command(0xD5); //--set display clock divide ratio/oscillator frequency OLED_Write_Command(0xF0); //--set divide ratio OLED_Write_Command(0xD9); //--set pre-charge period OLED_Write_Command(0x22); // OLED_Write_Command(0xDA); //--set com pins hardware configuration OLED_Write_Command(0x12); OLED_Write_Command(0xDB); //--set vcomh OLED_Write_Command(0x20); //0x20,0.77xVcc OLED_Write_Command(0x8D); //--set DC-DC enable OLED_Write_Command(0x14); // OLED_Write_Command(0xAF); //--turn on oled panel } void OLED_Write_Command(uint8_t cmd) { GPIO_ResetBits(OLED_DC_PORT, OLED_DC_PIN); GPIO_ResetBits(OLED_CS_PORT, OLED_CS_PIN); SPI_I2S_SendData(SPI1, cmd); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); GPIO_SetBits(OLED_CS_PORT, OLED_CS_PIN); } void OLED_Write_Data(uint8_t data) { GPIO_SetBits(OLED_DC_PORT, OLED_DC_PIN); GPIO_ResetBits(OLED_CS_PORT, OLED_CS_PIN); SPI_I2S_SendData(SPI1, data); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); GPIO_SetBits(OLED_CS_PORT, OLED_CS_PIN); } void OLED_Set_Pos(uint8_t x, uint8_t y) { OLED_Write_Command(0xB0 + y); OLED_Write_Command(((x & 0xF0) >> 4) | 0x10); OLED_Write_Command(x & 0x0F); } void OLED_Fill_Screen(uint8_t data) { uint8_t i, j; for (i = 0; i < 8; i++) { OLED_Write_Command(0xB0 + i); OLED_Write_Command(0x00); OLED_Write_Command(0x10); for (j = 0; j < 128; j++) { OLED_Write_Data(data); } } } void OLED_Show_String(uint8_t x, uint8_t y, uint8_t *str) { while (*str != '\0') { OLED_Set_Pos(x, y); uint8_t i; for (i = 0; i < 8; i++) { OLED_Write_Data(FONT8x8[(*str)][i]); } x += 8; str++; } } void delay_ms(uint16_t n) { uint16_t i, j; for (i = 0; i < n; i++) { for (j = 0; j < 1141; j++); } } ``` 其中,`OLED_Init()`进行OLED屏幕初始化,`OLED_Write_Command()`和`OLED_Write_Data()`用于向OLED屏幕写入指令和数据,`OLED_Set_Pos()`用于设置OLED屏幕显示位置,`OLED_Fill_Screen()`用于填充整个OLED屏幕,`OLED_Show_String()`用于在指定位置显示字符串。注意,此代码使用的是8x8大小的字体,需要提供相应的字体库。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值