本文开发环境:
- MCU型号:STM32F103ZE
- IDE环境: MDK 5.27
- 显示模块:1.27寸全彩OLED(SSD1351)驱动
本文内容:
- OLED 显示简介
- 全彩 OLED 显存的设计与实现
Note:为提高传输速度,本文把spi速度由上文工程的9Mpbs调至18Mpbs。这部分与OLED编程无关,故正文不做提及
OLED 系列博客索引 :
- 全彩OLED(SSD1351)程序设计与应用(1)驱动的移植
- 全彩OLED(SSD1351)程序设计与应用(2)显存优化:显存的设计与实现
- 全彩OLED(SSD1351)程序设计与应用(3)字符,字符串以及位图的生成与显示
一、SSD1351 显示原理简介
关于SSD1351显示的原理,可以参考技新科技的教程:SSD1351 设计指南,这里不再赘述,只简单介绍一下,与编程相关的知识点。
1. OLED 绘图原理
在上一小节中,我们已经完成了全屏画一个纯色的函数,其定义如下所示:
void Fill_RAM(unsigned char a, unsigned char b)
{
unsigned char i,j;
Set_Column_Address(0x00,0x7F); //设置列的范围 0 ~ 127 (共128列)
Set_Row_Address(0x00,0x7F); //设置行的范围 0 ~ 127 (共127行)
Set_Write_RAM(); //设置写RAM模式,即开始写入像素数据
for(i=0;i<128;i++)
{
for(j=0;j<128;j++)
{
Write_Data(a); //写入颜色高字节
Write_Data(b); //写入颜色低字节
}
}
}
在SSD1351中,首先根据我们设置的行列地址,作为起始的坐标,启用RAM后,就开始按顺序一行一行填充颜色,这2两个for()循环语句,正好循环128×128次,保证了每一个像素点都被填充一次,每一次程序都发送了2个字节,这是颜色的数据。SSD1351采用RGB565颜色模式,两个字节16比特,其中每个bit比特含义为:RRRRRGGGGGGBBBBB。可以通过修改Fill_RAM()两个参数的值,来协助自己理解颜色与字节对应的关系。需要特别注意,本文使用的 oled 为1.27寸,其分辨率并非128×128,而是128×96,所以OLED最顶的一行,其行地址是 0x20 ,如果你写一个绘制点的函数,就可以很好的发现这一点——你在(50,50)绘制一个像素点,会发现它距离OLED的边框并不是一样的距离。(注:这是由于初始化造成的,实际上,128×96中,前文OLED_Init() 函数中 **Set_Multiplex_Ratio(0x7F)**参数应该为0x5F,0x7F为128×128驱动的设置,如果你改正此处,坐标值可以正确对应)
二、显示的优化:建立显存数组
在上一节中,我们可以明显的看到颜色刷新的时间,这是由于HAL库函数中 **HAL_SPI_Transmit()**函数代码量较大,而不是直接的控制寄存器,导致需要较长的时间,这个函数调用128x128x2写的时间不低于200ms,导致我们刷新一次屏幕的时候,需要200多毫秒,所以需要HAL_SPI_Transmit()一次性传输128x128x2的数据,而非每次传输1个,传128x128x2次。这就要求我们建立一个大的数组,其大小为 128x128x2 个字节,然后调用库函数,一次性传输。具体操作如下(oled.c 中)所示:
- 在 oled.c 中建立一个显存数组:
#define OLED_RAM_SIZE (128*128*2) //定义显存大小
static uint8_t oled_ram[OLED_RAM_SIZE] = {
0}; //建立显存
- 使用显存方式刷新 oled
/*FILE: oled.c*/
... ...
#include "spi.h" //包含 spi.h 头文件,程序需要使用到spi句柄
void OLED_Refresh(uint8_t *pRAM)
{
Set_Column_Address(0x00,0x7F); //设置列地址
Set_Row_Address(0x00,0x7F); //设置行地址
Set_Write_RAM(); //开始写RAM
OLED_DC_Clr();
uDelay(1);
OLED_DC_Set(); //写数据模式
uDelay(1);
HAL_SPI_Transmit(&hspi1,oled_ram,OLED_RAM_SIZE,200); //发送显存数组
OLED_DC_Set();
}
- 测试程序
当我们实现新的刷屏方法以后,就可以编写程序测试效果,(直接修改OLED_Test()函数):
... ...
# include "string.h" //需要使用menset来设置显存函数
... ...
void OLED_Test(void)
{
static uint8_t color = 0x0B;
memset(oled_ram,color,OLED_RAM_SIZE); //填充显存颜色
OLED_Refresh(oled_ram); //使用新的方式刷新oled
color += 0x0A; //改变显存颜色
HAL_Delay(500);
}
当我们运行完该程序以后,就可以发现屏幕的刷新是瞬间完成的,不在看到OLED刷新图片的过程,在以后的工程中,将以填充显存,刷新OLED的方式来显示,避免OLED刷新慢的问题。
- oled.c 完整代码:
#include "ssd1351.h"
#include "oled.h"
#include "spi.h"
#include "string.h"
#define OLED_RAM_SIZE (128*128*2)
static uint8_t oled_ram[OLED_RAM_SIZE] = {
0};
void OLED_Refresh(uint8_t *pRAM)
{
Set_Column_Address(0x00,0x7F);
Set_Row_Address(0x00,0x7F);
Set_Write_RAM();
OLED_DC_Clr();
uDelay(1);
OLED_DC_Set();
uDelay(1);
HAL_SPI_Transmit(&hspi1,oled_ram,OLED_RAM_SIZE,200);
OLED_DC_Set();
}
void Fill_RAM(unsigned char a, unsigned char b)
{
unsigned char i,j;
Set_Column_Address(0x00,0x7F);
Set_Row_Address(0x00,0x7F);
Set_Write_RAM();
for(i=0;i<128;i++)
{
for(j=0;j<128;j++)
{
Write_Data(a);
Write_Data(b);
}
}
}
void OLED_Init(void)
{
OLED_RSE_Clr();
Delay(1);
OLED_RSE_Set();
Set_Command_Lock(0x12); // Unlock Driver IC (0x12/0x16/0xB0/0xB1)
Set_Command_Lock(0xB1); // Unlock All Commands (0x12/0x16/0xB0/0xB1)
Set_Display_On_Off(0x00); // Display Off (0x00/0x01)
Set_Display_Clock(0xF1); // Set Clock as 90 Frames/Sec
Set_Multiplex_Ratio(0x7F); // 1/128 Duty (0x0F~0x7F)
Set_Display_Offset(0x00); // Shift Mapping RAM Counter (0x00~0x7F)
Set_Start_Line(0x00); // Set Mapping RAM Display Start Line (0x00~0x7F)
Set_Remap_Format(0x74); // Set Horizontal Address Increment
// Column Address 0 Mapped to SEG0
// Color Sequence D[15:0]=[RRRRR:GGGGGG:BBBBB]
// Scan from COM127 to COM0
// Enable COM Split Odd Even
// 65,536 Colors Mode (0x74)
// * 262,144 Colors Mode (0xB4)
Set_GPIO(0x00); // Disable GPIO Pins Input
Set_Function_Selection(0x01); // Enable Internal VDD Regulator
// Select 8-bit Parallel Interface
Set_VSL(0xA0); // Enable External VSL
Set_Contrast_Color(0xC8,0x80,0xC8); // Set Contrast of Color A (Red)
// Set Contrast of Color B (Green)
// Set Contrast of Color C (Blue)
Set_Master_Current(Brightness); // Set Scale Factor of Segment Output Current Control
Set_Gray_Scale_Table(); // Set Pulse Width for Gray Scale Table
Set_Phase_Length(0x32); // Set Phase 1 as 5 Clocks & Phase 2 as 3 Clocks
Set_Precharge_Voltage(0x17); // Set Pre-Charge Voltage Level as 0.50*VCC
Set_Display_Enhancement(0xA4); // Enhance Display Performance
Set_Precharge_Period(0x01); // Set Second Pre-Charge Period as 1 Clock
Set_VCOMH(0x05); // Set Common Pins Deselect Voltage Level as 0.82*VCC
Set_Display_Mode(0x02); // Normal Display Mode (0x00/0x01/0x02/0x03)
Fill_RAM(0x00,0x00); // Clear Screen
Set_Display_On_Off(0x01); // Display On (0x00/0x01)
}
void OLED_Test(void)
{
static uint8_t color = 0x0B;
memset(oled_ram,color,OLED_RAM_SIZE);
OLED_Refresh(oled_ram);
color += 0x0A;
HAL_Delay(500);
}
三、说明
由于本次改动只是在上一个工程中修改了oled.c文件,所以只需要复制以上完整代码覆盖上一个工程的 oled.c 文件即可测试,这里不再上传工程,注意上文工程为的SPI速度为9M,本文测试环境为18M。
今天的文章全彩OLED(SSD1351)程序设计与应用(2)显示优化:显存的设计与实现[通俗易懂]分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/88648.html