锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

STM32 OLED屏(I2C接口)显示

时间:2022-10-30 20:30:00 4a2二极管集成电路2sa10132二极管a72sa1666ic集成电路g547g2p81u集成电路

SSD1306

    • OLED特性
    • 手册说明
      • GDDRAM寻址模式(0x20)
      • I2C地址与时序
    • 软件配置
      • I2C的配置
      • OLED初始化过程
      • 显示中文
      • 显示英文
      • 显示图片

OLED特性

型号:SSD1306
SSD1306是单
芯片CMOS OLED/PLED带有有机/聚合物发光二极管点阵图形显示系统的控制器。它由128段和64个公共区域组成。集成电路为普通阴极OLED面板设计。

SSD1306内置对比度控制,显示RAM振荡器减少了外部元件的数量和功耗。它有256步亮度控制。数据/命令与硬件可选的6800/8000系列兼容并行接口,I2C从用接口或串行外围接口MCU发送。

它适用于手机子显示器等许多小型便携式应用,MP播放器、计算器等。
在这里插入图片描述
实物图

手册说明

GDDRAM存储显示数据,大小为128x64bits.RAM从PAGE0~PAGE7.
每页内1个SEG对于一个Byte一页有128个数据Byte组成。10241024Byte

从下图可以看出SEG与COM的关系
整个画面有8页,每页有8页COM,128个SEG

涉及到一些配置寄存器,需要查看手册。手册中有几组寄存器

一、基本命令

命令 含义 使用说明
81 设置对比度 0x00~0xff 双字节命令,1-256对比等级,增加值,增加对比度
A4/A5 全显示开关 A4 x0=0b 重新显示RAM内容;A5 X0=1b 全部显示开
A6/A7 设置正常/翻转显示 A6,X[0]=0b,正常显示;A7,X[0]=1b:翻转显示
AE/AF 设置显示开/关 AE,X[0]=0b,关(睡眠模式);AF,X[0]=01b ON

二、地址设置命令

命令 含义 使用说明
00-0F 页地址模式下,设置低列起始地址 起始行寄存器显示重置后设置0000b
10-1F 在页面地址模式下,设置高列起始地址 起始行寄存器显示重置后设置0000b
20 设置寄存器地址模式 A[1:0]=00b01水平地址模式b 垂直地址模式,10页地址模式,11页地址模式b无效
21 设置列地址 设置列开始结束地址,A[6:0],start ;B[6:0] end
22 设置页地址 A[2:0]:起始地址范围07d,B[2:0]页末地址范围07d(复位:7d)
B0~B7 在页面地址模式下,设置页面起始地址 (PAGE0~PAGE7) for Page Addressing Modeusing X[2:0]

三、硬件配置命令

命令 含义 使用说明
40~7F 设置显示开始行
A0/A1 设置SEG重映射 A0h,X[0]=0b:列地址0,映射到SEG0(复位);A1h,x[0]=1b:127映射列地址SEG0
A8 多路复用设置
C0/C8 设置COM输出扫描模式 C0h,X[3]=0b:z=扫描正常模式 COM0COM[N-1];C8xX[3]=1b:重映射模式,扫描COM[N-1]COM[0]
D3 设置显示偏移 设置垂直偏移
DA 设置COM引脚硬件配置

四、滚动命令

命令 含义 使用说明
26/27 垂直水平滚动 26h x[0]=0 ,水平向右滚动;27 x[0]=1 水平向左滚动
29/2A 垂直滚动 29,向右 (上下);2A向左 (上下)

测试时,26、27命令无效,29、27命令无效A左右,左右 上下滚动的效果
打开命令码后,设置以下内容A,B,C,D,E参数如下:
滚动实例,在初始化时调用,26/27没有实验成功,29/2A可以实现滚动

void roll()
{ 
        
    WriteCmd(0x2e);//OFF
    WriteCmd(0x2A);//29,2a
    WriteCmd(0x00);//A:Dummy byte
    WriteCmd(0x00);//B:设置页起始地址
    WriteCmd(0x02);//C:滚动速度 000b-5frames 100b-3frames
	WriteCmd(0x01);//D:设置页结束地址
    WriteCmd(0x00);//E:垂直滚动偏移
	WriteCmd(0x2f);//START ROLL
}

GDDRAM寻址模式(0x20)

有三种模式设置,例如:

	OLED_WriteC(0X20);	// 设置模式
	OLED_WriteC(0X00);	// 设置值(水平寻址模式 )

页寻址、A[1:0]=10

水平寻址、A[1:0]=00

垂直寻址 A[1:0]=01

I2C地址与时序


这段话的意思是,SA0 提供可扩展的从机地址,通过SA0(D/C#)脚的上拉和下拉来设置从机地址,拉高则为1,即 0111101;拉低则为0,即0111100
最后一个是读写R/W

I2C地址为0x78

I2C收发数据开始和结束时序

IIC写入时序如下所示:

  • 主机先发起开始(START)信号(SDA从高到底,SCL从底到高),

  • 然后发送1byte首字节,包括从机地址(7位)和读写数据位(1位,最低位,0为写模式),

  • 驱动器识别从机地址为本机地址之后,将会发出 应答信号(ACK)

  • 主机收到从机的应答信号之后,随后传输命令或者数据。一个控制字节主要由CO 和 D/C# 位后面再加上六个0组成的。

  • 接受每一个控制字节或者数据字节都要产生ACK信号

  • 传输完毕之后主机发出结束(STOP)信号,SDA 从低到高 SCL保持高

软件配置

  • I2C配置,配置SCL、SDL的GPIO
    SCL <—>PB6
    SDA <—>PB7
  • 根据手册配置OLED

I2C的配置

#define OLED_I2C I2C1
#define OLED_I2C_CLK RCC_APB1Periph_I2C1
#define OLED_I2C_CLK_INIT RCC_APB1PeriphClockCmd

#define OLED_I2C_SCL_PIN GPIO_Pin_6 
#define OLED_I2C_SCL_GPIO_PORT GPIOB 
#define OLED_I2C_SCL_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_I2C_SCL_SOURCE GPIO_PinSource6
#define OLED_I2C_SCL_AF GPIO_AF_I2C1

#define OLED_I2C_SDA_PIN GPIO_Pin_7 
#define OLED_I2C_SDA_GPIO_PORT GPIOB 
#define OLED_I2C_SDA_GPIO_CLK RCC_APB2Periph_GPIOB
#define OLED_I2C_SDA_SOURCE GPIO_PinSource7
#define OLED_I2C_SDA_AF GPIO_AF_I2C1

void I2C_Configuration(void)
{ 
        
	  I2C_InitTypeDef  I2C_InitStructure;
	  GPIO_InitTypeDef  GPIO_InitStructure; 

	  //外设I2C时钟使能
  	  OLED_I2C_CLK_INIT(OLED_I2C_CLK,ENABLE);
	  //外设GPIO时钟使能
	  RCC_APB2PeriphClockCmd(OLED_I2C_SCL_GPIO_CLK | OLED_I2C_SDA_GPIO_CLK,ENABLE);

	 /* I2C_SCL、I2C_SDA*/
	  GPIO_InitStructure.GPIO_Pin = OLED_I2C_SCL_PIN;
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;	
	  GPIO_Init(OLED_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
		
	  GPIO_InitStructure.GPIO_Pin = OLED_I2C_SDA_PIN;
	  GPIO_Init(OLED_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);	
		
		/* I2C */
	  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;	
	  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	  I2C_InitStructure.I2C_OwnAddress1 =OLED_ADDRESS;    //I2C地址
	  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;	
	  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;	//寻址方式
	  I2C_InitStructure.I2C_ClockSpeed = I2C_Speed;//速度
	  
	  I2C_Init(OLED_I2C, &I2C_InitStructure);	 //使能初始化
	  I2C_Cmd(OLED_I2C, ENABLE); //使能I2C
}

通过I2C写数据

//硬件I2C时序配置
void I2C_WriteByte(uint8_t addr,uint8_t data)
{ 
        
    //Checks whether the specified I2C flag is set or not.
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
	
	I2C_GenerateSTART(I2C1, ENABLE);//产生I2C起始信号
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,,主模式*/

	I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//器件I2C地址0x78
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	I2C_SendData(I2C1, addr);//寄存器地址
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_SendData(I2C1, data);//数据
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	
	I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C
}

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

OLED初始化过程

//手册中提供的初始化函数
void OLED_Init(void)
{ 
        
	Delay_s(1);		// 1s,
	WriteCmd(0xAE); //屏幕关
	WriteCmd(0x20);	//设置寻址模式
	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);	//COM扫描反向
	WriteCmd(0x00); //起始列地址低位
	WriteCmd(0x10); //起始列地址高位
	WriteCmd(0x40); //--set start line address
	WriteCmd(0x81); //设置对比度
	WriteCmd(0xff); //亮度调节 范围0x00~0xff
	WriteCmd(0xa1); //set segment re-map 0 to 127
	WriteCmd(0xa6); //正常显示
	
	WriteCmd(0xa8); //设置MUX数(1 to 64)
	WriteCmd(0x3F); //MUX=63 显示63行
	
	WriteCmd(0xa4); //0xa4,输出 RAM 内容;0xa5,忽略 RAM 内容
	WriteCmd(0xd3); // 设置显示偏移
	WriteCmd(0x00); //没有偏移
	
	WriteCmd(0xd5); //设置显示时钟分频数、振荡器频率
	WriteCmd(0xf0); //--set divide ratio
	WriteCmd(0xd9); //设置预充电周期
	WriteCmd(0x22); //
	WriteCmd(0xda); //COM引脚配置
	WriteCmd(0x12);//启用左右反置
	
	WriteCmd(0xdb); //设置 vcomh 输出
	WriteCmd(0x20); //0x20,0.77xVcc
	
	WriteCmd(0x8d); //--set DC-DC enable
	WriteCmd(0x14); //
	WriteCmd(0xaf); //--turn on oled panel
}

//OLED_ON 从休眠中唤醒
void OLED_ON(void)
{ 
        
	WriteCmd(0X8D);  //
	WriteCmd(0X14);  //
	WriteCmd(0XAF);  //
}
// OLED_OFF 休眠
void OLED_OFF(void)
{ 
        
	WriteCmd(0X8D);  //
	WriteCmd(0X10);  //
	WriteCmd(0XAE);  //
}

//设置读写坐标
void OLED_SetPos(unsigned char x, unsigned char y) //设置起始坐标
{ 
         
	WriteCmd(0xb0+y);//y取值 0 -7 (B0h~B7h)
	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++)
	{ 
        
	   //Set Page Start Address for Page Addressing Mode (B0h~B7h)
		WriteCmd(0xb0+m);		//page0-page1
		WriteCmd(0x00);		//low column start address
		WriteCmd(0x10);		//high column start address
		for(n=0;n<128;n++)
			{ 
        
				WriteDat(fill_Data);
			}
	}
}
void OLED_CLS(void)
{ 
        
	OLED_Fill(0x00);
}

显示中文

字位图(bmp)提取软件 pctolcd2002

所需要的配置

生成的汉字bmp数据
//16*16点阵,维护世界和平

unsigned char F16x16[]=
{ 
        
	0x20,0x30,0xAC,0x63,0x20,0x58,0x20,0xF8,0x4F,0x48,0x49,0xFA,0x48,0x48,0x08,0x00,
	0x22,0x67,0x22,0x12,0x12,0x12,0x00,0xFF,0x22,0x22,0x22,0x3F,0x22,0x22,0x20,0x00,//维
	0x10,0x10,0x10,0xFF,0x10,0x90,0x00,0xF8,0x88,0x89,0x8E,0x88,0x88,0x88,0xF8,0x00,
	0x04,0x44,0x82,0x7F,0x81,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,//护
	0x20,0x20,0x20,0xFE,0x20,0x20,0xFF,0x20,0x20,0x20,0xFF,0x20,0x20,0x20,0x20,0x00,
	0x00,0x00,0x00,0x7F,0x40,0x40,0x47,0x44,0x44,0x44,0x47,0x40,0x40,0x40,0x00,0x00,//世
	0x00,0x00,0x00,0xFE,0x92,0x92,0x92,0xFE,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,0x00,
	0x08,0x08,0x04,0x84,0x62,0x1E,0x01,0x00,0x01,0xFE,0x02,0x04,0x04,0x08,0x08,0x00,//界
	0x20,0x24,0x24,0xA4,0xFE,0x23,0x22,0x20,0x00,0xF8,0x08,0x08,0x08,0xF8,0x00,0x00,
	0x10,0x08,0x06,0x01,0xFF,0x01,0x06,0x00,0x00,0x3F,0x10,0x10,0x10,0x3F,0x00,0x00,//和
	0x00,0x02,0x02,0x12,0x62,0x02,0x02,0xFE,0x02,0x02,0x42,0x32,0x02,0x02,0x00,0x00,
	0x01,0x01,0x01,0x01,0x01,0x01,0x01,0xFF,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,//平
};

//显示中文函数
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{ 
        
	unsigned char wm=0;
	unsigned int  adder=32*N;
	OLED_SetPos(x , y);
	for(wm = 0;wm < 16;wm++)
	{ 
        
		WriteDat(F16x16[adder]);
		adder += 1;
	}
	OLED_SetPos(x,y + 1);
	for(wm = 0;wm < 16;wm++)
	{ 
        
		WriteDat(F16x16[adder]);
		adder += 1;
	}
}

//主函数调用
for(i=0;i<6;i++)//6 代表有6个字
{ 
        
	OLED_ShowCN(22+i*16,0,i);	//测试显示中文
}

显示英文

//6*8点阵
const unsigned char F6x8[][6] =
{ 
        
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
	0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
	0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
	0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
	0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
	0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
	0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
	0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
	0x00, 

相关文章