1261|1

6992

帖子

11

TA的资源

版主

楼主
 

[ ST NUCLEO-U575ZI-Q 测评] 优化OLED显示 [复制链接]

[ ST NUCLEO-U575ZI-Q 测评] HAL移植U8G2 - stm32/stm8 - 电子工程世界-论坛 (eeworld.com.cn)

[ ST NUCLEO-U575ZI-Q 测评] 时钟——U8g2 - stm32/stm8 - 电子工程世界-论坛 (eeworld.com.cn)

上面的帖子是用u8g2实现OLED的显示,为了更进一步的熟悉ssd1306的使用,以及对hal库i2c的数据发送,这段时间又继续研究了ssd1306的数据发送。

STM32U575的HAL_I2C库的输出操作函数有两种模式,一种是阻塞模式,另一种是非阻塞模式。

阻塞模式:在轮询模式下执行通信。所有数据处理的状态由同一函数返回完成转移后。

无阻塞模式:使用中断进行通信或DMA。这些函数返回传输启动的状态。数据处理的结束将通过

 

阻塞模式功能发送有:

HAL_I2C_Master_Transmit()

HAL_I2C_Slave_Transmit()

HAL_I2C_Mem_Write()

带中断的无阻塞模式发送有:

HAL_I2C_Master_Transmit_IT()

HAL_I2C_Slave_Transmit_IT()

HAL_I2C_Mem_Write_IT()

DMA无阻塞模式功能:

HAL_I2C_Master_Transmit_DMA()

HAL_I2C_Slave_Transmit_DMA()

HAL_I2C_Mem_Write_DMA()

因为ssd1306的驱动没有做读取函数,所以只需要用到发送即可。

1、首先创建一个ssd1306的缓存,屏幕总共有128*8 = 1024字节,所以建立一个u8 OLED_GRAM[8][128];的缓存,用于存放显存数据。

2、把缓存数据发送给ssd1306的第一版函数:

//更新显存到OLED	
void OLED_Refresh(void)
{
	u8 i,n;
	for(i=0;i<8;i++)
	{
		OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
		OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
		OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
		for(n=0;n<128;n++)
		{
			OLED_WR_Byte(OLED_GRAM[i][n],OLED_DATA);
		}

  }
}

这样的话,总共要执行设置行起始地址、设置低列起始地址、设置高列起始地址8次,执行写入从机地址、数据位、位数8*128次。等待超时时间8*3+8*128次。

3、优化为发送数据128位时用一个函数来发送:

//更新显存到OLED	
void OLED_Refresh(void)
{
	u8 i,n;
	for(i=0;i<8;i++)
	{
		OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
		OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
		OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
		//for(n=0;n<128;n++)
		//{
		//	OLED_WR_Byte(OLED_GRAM[i][n],OLED_DATA);
		//}
        修改为一次发送128数据,减少了127个发送从机地址、命令位的时间。
        HAL_I2C_Mem_Write(&hi2c1, oled_addr, 0x00,1, &OLED_GRAM[i][n], 128, 100);

  }
}

这样的话就优化到少了8*127次发送从机地址+数据位命令的时间。

4、优化页写入命令,将所有数据做一次发送:

//在OLED初始化中修改页面寻址方式
OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
//OLED_WR_Byte(0x02,OLED_CMD);//把页地址修改为水平方式(页地址0x02,水平0x00,垂直0x01)
OLED_WR_Byte(0x00,OLED_CMD);//
//更新显存到OLED	
void OLED_Refresh(void)
{
   /*
	u8 i,n;
	for(i=0;i<8;i++)
	{
		OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
		OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
		OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
		//for(n=0;n<128;n++)
		//{
		//	OLED_WR_Byte(OLED_GRAM[i][n],OLED_DATA);
		//}
        修改为一次发送128数据,减少了127个发送从机地址、命令位的时间。
        HAL_I2C_Mem_Write(&hi2c1, oled_addr, 0x00,1, &OLED_GRAM[i][n], 128, 100);

  }
  */
  //修改为一次发送1024数据。减少了8*4个地址位发送时间+8*4个数据位令发送时间。
  HAL_I2C_Mem_Write(&hi2c1, oled_addr, 0x00,1, &OLED_GRAM[i][n], 128, 100);
}

这样的话更进一步少了发送时间。

5、上面为阻塞式发送数据,下面修改为中断发送,首先在stm32cubeMax下配置为中断事件。

 然后修改发送函数为:

//更新显存到OLED	
void OLED_Refresh(void)
{
	HAL_I2C_Mem_Write_IT(&hi2c1, oled_addr, 0x40,1, &OLED_GRAM[0][0], 1024);
}

6、更换为DMA发送模式:

 配置好后修改发送函数为:

//更新显存到OLED	
void OLED_Refresh(void)
{
	HAL_I2C_Mem_Write_DMA(&hi2c1, oled_addr, 0x40,1, &OLED_GRAM[0][0], 1024);
}

【总结】经过以上的估化,刷新速度明显提高,而且代码量也变得少了。

 

 

此帖出自无线连接论坛

最新回复

测评汇总:免费申请|ST NUCLEO-U575ZI-Q https://bbs.eeworld.com.cn/thread-1228653-1-1.html   详情 回复 发表于 2023-1-12 09:33
点赞 关注
 

回复
举报

1万

帖子

203

TA的资源

管理员

沙发
 

测评汇总:免费申请|ST NUCLEO-U575ZI-Q https://bbs.eeworld.com.cn/thread-1228653-1-1.html

此帖出自无线连接论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
个人签名玩板看这里:
https://bbs.eeworld.com.cn/elecplay.html
EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表