一、OLED
1. OLED模块的外观
2. OLED模块的电路图
3. OLED模块参数
项目说明
接口特性3.3V(串电阻后,可与 5V 系统连接)通信接口4 线 SPI屏幕分辨率128*64屏幕尺寸0.96 寸工作温度-40℃~70℃
颜色 纯蓝色、黄蓝双色 模块尺寸| 27mm*26mm
二、GPIO模拟SPI
1. 硬件连接
通过引脚和模块电路图可以分析出SPI的电路连接
OLED STM32
GND <----------> GND
VCC <----------> 3.3V
D0 <----------> PA4(CLK)
D1 <----------> PA3(MOSI)
RES <----------> PA2(RET复位)
DC <----------> PA1(命令|数据dc)
CS <----------> GND
2. 软件驱动
由OLED模块数据手册上SPI的操作时序图写出由GPIO口模拟的SPI驱动代码
模块只支持向模块写数据不能读数据
所以只需要写SPI发送即可
2.1 “SPI.h”
#define OLED_CMD 0
#define OLED_DATA 1
#define OLED_CLK PAout(4)
#define OLED_MOSI PAout(3)
#define OLED_RST PAout(2)
#define OLED_DC PAout(1)
void OLED_SPI_Init(void);
void SPI_WriteByte(uint8_t addr
,uint8_t data
);
void WriteCmd(unsigned char cmd
);
void WriteDat(unsigned char data
);
2.2 “SPI.c”
void OLED_SPI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure
;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
,ENABLE
);
GPIO_InitStructure
.GPIO_Pin
=GPIO_Pin_1
|GPIO_Pin_2
|GPIO_Pin_3
|GPIO_Pin_4
;
GPIO_InitStructure
.GPIO_Mode
=GPIO_Mode_Out_PP
;
GPIO_InitStructure
.GPIO_Speed
=GPIO_Speed_50MHz
;
GPIO_Init(GPIOA
,&GPIO_InitStructure
);
}
void SPI_WriteByte(unsigned char data
,unsigned char cmd
)
{
unsigned char i
=0;
OLED_DC
=cmd
;
OLED_CLK
=0;
for(i
=0;i
<8;i
++)
{
OLED_CLK
=0;
if(data
&0x80)OLED_MOSI
=1;
else OLED_MOSI
=0;
OLED_CLK
=1;
data
<<=1;
}
OLED_CLK
=1;
OLED_DC
=1;
}
void WriteCmd(unsigned char cmd
)
{
SPI_WriteByte(cmd
,OLED_CMD
);
}
void WriteData(unsigned char data
)
{
SPI_WriteByte(data
,OLED_DATA
);
}
三、STM32对OLED模块的控制
3.1 指令集
序号HEX指令说明
081设置对比度值越大,屏幕越亮(默认 0X7F); 0X000XFF(1255)1AE/AF设置显示开关AE,关闭显示;AF,开启显示28D电荷泵设置0x10,关闭电荷泵;0x14开启电荷泵3B0~B7设置页地址0~7 对应页 0~7400~0F设置列地址(低四位)设置 8 位起始列地址的低四位510~1F设置列地址(高四位)设置 8 位起始列地址的高四位
更多请查询SSD1306 的data sheet
3.2 “OLED.h"
void OLED_Init(void);
void OLED_ON(void);
void OLED_OFF(void);
void OLED_Refresh_Gram(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x
,u8 y
,u8 t
);
void OLED_Fill(u8 x1
,u8 y1
,u8 x2
,u8 y2
,u8 dot
);
void OLED_ShowChar(u8 x
,u8 y
,u8 chr
,u8 size
,u8 mode
);
void OLED_ShowNum(u8 x
,u8 y
,u32 num
,u8 len
,u8 size
);
void OLED_ShowString(u8 x
,u8 y
,const u8
*p
,u8 size
);
3.3 “OLED.c”
u8 OLED_GRAM
[128][8];
void OLED_DLY_ms(unsigned int ms
)
{
unsigned int a
;
while(ms
)
{
a
=1335;
while(a
--);
ms
--;
}
}
void OLED_Init(void)
{
OLED_SPI_Init();
OLED_CLK
= 1;
OLED_RST
= 0;
OLED_DLY_ms(100);
OLED_RST
= 1;
WriteCmd(0xAE);
WriteCmd(0xD5);
WriteCmd(0x80);
WriteCmd(0xA8);
WriteCmd(0x3F);
WriteCmd(0xD3);
WriteCmd(0x00);
WriteCmd(0x40 | 0x00);
WriteCmd(0x8D);
WriteCmd(0x10 | 0x04);
WriteCmd(0x20);
WriteCmd(0x02);
WriteCmd(0xA0 | 0x01);
WriteCmd(0xC0);
WriteCmd(0xDA);
WriteCmd(0x02 | 0x10);
WriteCmd(0x81);
WriteCmd(0xCF);
WriteCmd(0xD9);
WriteCmd(0xF1);
WriteCmd(0xDB);
WriteCmd(0x40);
WriteCmd(0xA4 | 0x00);
WriteCmd(0xA6 | 0x00);
WriteCmd(0xAE | 0x01);
OLED_Clear();
}
void OLED_ON(void)
{
WriteCmd(0X8D);
WriteCmd(0X14);
WriteCmd(0XAF);
}
void OLED_OFF(void)
{
WriteCmd(0X8D);
WriteCmd(0X10);
WriteCmd(0XAE);
}
void OLED_Refresh_Gram(void)
{
u8 i
,n
;
for(i
=0;i
<8;i
++)
{
WriteCmd(0xb0+i
);
WriteCmd(0x00);
WriteCmd(0x10);
for(n
=0;n
<128;n
++)WriteData(OLED_GRAM
[n
][i
]);
}
}
void OLED_Clear(void)
{
u8 i
,n
;
for(i
=0;i
<8;i
++)for(n
=0;n
<128;n
++)OLED_GRAM
[n
][i
]=0X00;
OLED_Refresh_Gram();
}
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
;
}
void OLED_Fill(u8 x1
,u8 y1
,u8 x2
,u8 y2
,u8 dot
)
{
u8 x
,y
;
for(x
=x1
;x
<=x2
;x
++)
{
for(y
=y1
;y
<=y2
;y
++)OLED_DrawPoint(x
,y
,dot
);
}
OLED_Refresh_Gram();
}
void OLED_ShowChar(u8 x
,u8 y
,u8 chr
,u8 size
,u8 mode
)
{
u8 temp
,t
,t1
;
u8 y0
=y
;
u8 csize
=(size
/8+((size
%8)?1:0))*(size
/2);
chr
=chr
-' ';
for(t
=0;t
<csize
;t
++)
{
if(size
==12)temp
=asc2_1206
[chr
][t
];
else if(size
==16)temp
=asc2_1608
[chr
][t
];
else if(size
==24)temp
=asc2_2412
[chr
][t
];
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;
}
}
}
}
u32
mypow(u8 m
,u8 n
)
{
u32 result
=1;
while(n
--)result
*=m
;
return result
;
}
void OLED_ShowNum(u8 x
,u8 y
,u32 num
,u8 len
,u8 size
)
{
u8 t
,temp
;
u8 enshow
=0;
for(t
=0;t
<len
;t
++)
{
temp
=(num
/mypow(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);
}
}
void OLED_ShowString(u8 x
,u8 y
,const u8
*p
,u8 size
)
{
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
,1);
x
+=size
/2;
p
++;
}
}
四、用STM32的SPI资源(可选)
也可以不使用GPIO口模拟,使用STM32的SPI资源
驱动代码如下:
void OLED_SPI_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure
;
SPI_InitTypeDef SPI_InitStructure
;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA
|
RCC_APB2Periph_SPI1
, ENABLE
);
GPIO_InitStructure
.GPIO_Pin
= GPIO_Pin_5
| GPIO_Pin_7
;
GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_AF_PP
;
GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_50MHz
;
GPIO_Init(GPIOA
, &GPIO_InitStructure
);
GPIO_SetBits(GPIOA
,GPIO_Pin_5
|GPIO_Pin_7
);
GPIO_InitStructure
.GPIO_Pin
=GPIO_Pin_1
|GPIO_Pin_2
;
GPIO_InitStructure
.GPIO_Mode
=GPIO_Mode_Out_PP
;
GPIO_InitStructure
.GPIO_Speed
=GPIO_Speed_50MHz
;
GPIO_Init(GPIOA
,&GPIO_InitStructure
);
SPI_InitStructure
.SPI_Direction
= SPI_Direction_2Lines_FullDuplex
;
SPI_InitStructure
.SPI_Mode
= SPI_Mode_Master
;
SPI_InitStructure
.SPI_DataSize
= SPI_DataSize_8b
;
SPI_InitStructure
.SPI_CPOL
= SPI_CPOL_High
;
SPI_InitStructure
.SPI_CPHA
= SPI_CPHA_2Edge
;
SPI_InitStructure
.SPI_NSS
= SPI_NSS_Soft
;
SPI_InitStructure
.SPI_BaudRatePrescaler
= SPI_BaudRatePrescaler_16
;
SPI_InitStructure
.SPI_FirstBit
= SPI_FirstBit_MSB
;
SPI_InitStructure
.SPI_CRCPolynomial
= 7;
SPI_Init(SPI1
, &SPI_InitStructure
);
SPI_Cmd(SPI1
, ENABLE
);
}
void OLED_WB(uint8_t data
)
{
while (SPI_I2S_GetFlagStatus(SPI1
, SPI_I2S_FLAG_TXE
) == RESET
);
SPI_I2S_SendData(SPI1
, data
);
}
void SPI_WriteByte(unsigned char data
,unsigned char cmd
)
{
unsigned char i
=0;
OLED_DC
=cmd
;
OLED_WB(data
);
}
PS:可以通过添加公众号“山不高海不深”回复关键字“OLED代码“得到完整工程代码
回复关键字“OLED代码“得到完整工程代码