SPI+DMA刷新OLED
文章目录
- SPI+DMA刷新OLED
- 原理简介
- 一、修改缓存区大小
- 二、修改SSD1306的指令
- 三、替换原来的刷新函数
- 验证结果
原理简介
OLED屏幕有三种刷新方式分别为页地址模式, 水平地址模式和垂直地址模式,。市面上厂家提供的历程为页刷新,这种刷新方式需要用户自己手动进行行列的切换,这种操作方式我个人感觉比较麻烦。三种刷新方式的具体方式可以参考厂家的文档。我这里参考了另一个人的博客,具体连接如下。
https://blog.csdn.net/gengyuchao/article/details/86608037
页地址模式
水平寻址模式
垂直寻址模式
可以发现如果我们采用水平地址寻址或者垂直地址寻址的话,只需要源源不断的发送数据就可以了,再结合DMA的话可以实现自动快速刷新,减轻处理器的负担。非常NICE!缺点就是必须整个刷一帧屏幕全屏幕,但是我们数据全部走DMA,所以还是划得来这个性价比的。
一、修改缓存区大小
uint8_t OLED_GRAM[128][8];//原大小为144 8,我也不知道为啥中景园这么写
把缓存区的大小修改为一帧的数量大小,128 64的分辨率,算下来正好128 8字节
二、修改SSD1306的指令
OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)OLED_WR_Byte(0x01,OLED_CMD);//OLED_WR_Byte(0x21,OLED_CMD);//设置列地址OLED_WR_Byte(0x00,OLED_CMD);OLED_WR_Byte(0x7f,OLED_CMD); OLED_WR_Byte(0x22,OLED_CMD);//设置页地址OLED_WR_Byte(0x00,OLED_CMD);OLED_WR_Byte(0x07,OLED_CMD);
修改为垂直地址寻址模式,设置列行的起始和结束地址。
三、替换原来的刷新函数
//更新显存到OLED
void OLED_Refresh(void)
{
// OLED_WR_Byte(0xb0,OLED_CMD); //设置行起始地址
// OLED_WR_Byte(0x00,OLED_CMD); //设置低列起始地址
// OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)OLED_GRAM, 128*8);
}
当然也可以修改DMA为循环模式,使得数据自动刷新。
//hdma_spi1_tx.Init.Mode =DMA_NORMAL;hdma_spi1_tx.Init.Mode = DMA_CIRCULAR;//切换为循环模式
这样一来这个刷新函数甚至都不需要调用了,只要修改缓存区,数据自动发送,屏幕就跟着刷新了。
验证结果
OLED_Refresh();//循环模式DMA要先开一次OLED_ShowPicture(0,0,128,64,BMP1,1);//之后就不要调用DMA函数了,自动就会刷新//只需要调用画图函数,OLED刷新函数不用调用了,舒服多了。
我这个图片显示有问题不清晰,是因为我的这块0.96OLED屏幕坏了,导致隔一行有一行没有的。后续我会整理好代码后发出来。