6.(OLED屏幕)在STM32C8T6上使用OLED模块

stm32c8t6、oled屏幕、stlink即可实现点亮屏幕

本文基于该教程【STM32入门教程-2024】第14集 如何在OLED屏幕上挥毫_哔哩哔哩_bilibili

大家记得一键三连!!!

1.可以简单了解下OLED模块的硬件底层构造及其原理

OLED(Organic Light-Emitting Diode),有机发光二极管/半导体

是一种有可发光特性的有机分子聚合物

优点:功耗低、体积小、成本低

OLED通信采用I2C协议,详细可见上一篇文章


2.memset()函数

格式:memset(GRAM,0,sizeof(GRAM));

作用:该函数可以将内存都设置成同一个数

参数:数组、设置的值、长度

!!!记得——#include "string.h"


3.(实验)将OLED模块与STM32设置的打开I2C的GPIO口相连,并将写好的代码通过stlink烧录进STM32中,实现点亮OLED屏幕

3.1 器材

硬件:STM32F103C8T6、OLED屏幕、面包板、STLink、若干杜邦线

软件:CubeMX、keil5

3.2 结果

简单使用OLED

3.3 接线

大家对照相应杜邦线接线即可

将OLED的SDA、SCL口接到你stm32打开I2C的GPIO口上即可

(我这里PB6是SCL口、PB7是SDA口)

总体接线图

OLED屏幕接线图 

3.4 CubeMX配置

 SYS配置 

RCC配置 

I2C1设置,下方设置为:Fast Mode

时钟配置,改为72 MHZ

3.5 代码(仅添加修改处)

/*oled.h*/
#ifndef INC_OLED_H_
#define INC_OLED_H_

#include "i2c.h"

void OLED_Init();
void OLED_DisPlay_On();
void OLED_NewFrame();
void OLED_ShowFrame();
void OLED_SetPixel(uint8_t x,uint8_t y);
void OLED_Test();

#endif /* INC_OLED_H_*/
/*oled.c*/
#include "oled.h"
#include "string.h"

#define OLED_ADDRESS 0x78

void OLED_SendCmd(uint8_t cmd){
	uint8_t sendBuffer[2];//2字节大小的数组
	sendBuffer[0] = 0x00;//代表指令通信
	sendBuffer[1] = cmd;//指令
	//I2C发送函数,参数:外设句柄的指针、从机地址、发送数据的指针、数据长度、等待超时时间
	HAL_I2C_Master_Transmit(&hi2c1,OLED_ADDRESS,sendBuffer,2,HAL_MAX_DELAY);
}

//OLED初始化函数,驱动包里有
void OLED_Init()
{
  OLED_SendCmd(0xAE); /*关闭显示 display off*/

  OLED_SendCmd(0x20);
  OLED_SendCmd(0x10);

  OLED_SendCmd(0xB0);

  OLED_SendCmd(0xC8);

  OLED_SendCmd(0x00);
  OLED_SendCmd(0x10);

  OLED_SendCmd(0x40);

  OLED_SendCmd(0x81);

  OLED_SendCmd(0xDF);
  OLED_SendCmd(0xA1);

  OLED_SendCmd(0xA6);
  OLED_SendCmd(0xA8);

  OLED_SendCmd(0x3F);

  OLED_SendCmd(0xA4);

  OLED_SendCmd(0xD3);
  OLED_SendCmd(0x00);

  OLED_SendCmd(0xD5);
  OLED_SendCmd(0xF0);

  OLED_SendCmd(0xD9);
  OLED_SendCmd(0x22);

  OLED_SendCmd(0xDA);
  OLED_SendCmd(0x12);

  OLED_SendCmd(0xDB);
  OLED_SendCmd(0x20);

  OLED_SendCmd(0x8D);
  OLED_SendCmd(0x14);

  OLED_NewFrame();
  OLED_ShowFrame();

  OLED_SendCmd(0xAF); /*开启显示 display ON*/
}

/**
 * @brief 开启OLED显示
 */
void OLED_DisPlay_On()
{
  OLED_SendCmd(0x8D); // 电荷泵使能
  OLED_SendCmd(0x14); // 开启电荷泵
  OLED_SendCmd(0xAF); // 点亮屏幕
}

//设置“显存”
uint8_t GRAM[8][128];//8页*128列,缓存128*64个像素值

//将显存清空为0
void OLED_NewFrame(){
/*	for(uint8_t i = 0;i < 8;i++){
		for(uint8_t j = 0; j <128;j++){
			GRAM[i][j] = 0;
		}
	}*/
	memset(GRAM,0,sizeof(GRAM));//memset函数可以将内存都设置成同一个数,参数:数组、设置的值、长度
}

//将显存显示到屏幕上的函数
void OLED_ShowFrame(){
	uint8_t sendBuffer[129];//存储待发送数据的数组
	sendBuffer[0] = 0x40;//指令
	//总览是,将显存里的一页先显示出来,再+i来增加页数
	for(uint8_t i = 0;i < 8; i++){
		/*此处列循环可以直接用memcpy来代替*/
		for(uint8_t j = 0;j < 128; j++){
			//将数组的第j+1字节都赋值为第i页第j列的数据,把二位数组GRAM的值全部压到一位数组(待发送数据的数组)sendBuffer中
			sendBuffer[j+1] = GRAM[i][j];//这里加1,是因为[0]存的是0x40
		}
		OLED_SendCmd(0xB0 + i);//页地址设置为第0页,页数增加,要+i
		OLED_SendCmd(0x00);//列地址低四位设置为0
		OLED_SendCmd(0x10);//列地址高四位设置为0
		HAL_I2C_Master_Transmit(&hi2c1,OLED_ADDRESS,sendBuffer,sizeof(sendBuffer),HAL_MAX_DELAY);
	}
}

//设置某个像素亮起
void OLED_SetPixel(uint8_t x,uint8_t y){
	if(x >= 128 || y >= 64)return;//防止数组越界
	GRAM[y/8][x] |= 0x01 << (y % 8);//像素共是128*64,即6页128列,所以y/8,一列上是8个像素,所以要进行左移操作
}

void OLED_Test(){
	OLED_SendCmd(0xB0);//页地址设置为第0页
	OLED_SendCmd(0x00);//列地址低四位设置为0
	OLED_SendCmd(0x10);//列地址高四位设置为0
	
	uint8_t sendBuffer[] = {0x40,0xAA};//设置发送数据内容
	HAL_I2C_Master_Transmit(&hi2c1,OLED_ADDRESS,sendBuffer,sizeof(sendBuffer),HAL_MAX_DELAY);
}
/*main.c内需要include的地方*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "oled.h"
/* USER CODE END Includes */
/*main.c内BEGIN 2和while循环内代码*/
 /* USER CODE BEGIN 2 */
	HAL_Delay(200);//OLED比stm32启动慢,需要加延时
	OLED_DisPlay_On();
	OLED_Init();
	OLED_NewFrame();
	OLED_ShowFrame(); 
	OLED_Test();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		for(uint8_t i = 0;i < 64;i++){
			OLED_NewFrame();
			OLED_SetPixel(2*i,i);
			OLED_ShowFrame();
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }


[重点]!!!实验注意:(一些区别、问题以及解决方法)

①视频当中的编译软件是CubeIDE,这里使用keil5软件;视频里使用的是up自己的开发板,我们需要自己连线

②出现中文乱码情况,keil5软件需要将编码规则改为UTF-8

 打开扳手

更改编码规则为UTF-8 

③注意自己的OLED屏幕地址(从机地址码)

视频里的是0x70,我这里的是0x78(写在OLED屏幕背面)

④main.c里的BEGIN 2中延时设置为200,视频里为20

⑤屏幕还是没有反应,还需要打开OLED显示

在main.c中的BEGIN 2内写上:OLED_DisPlay_On() 

别忘了在oled.c内声明下函数:

OLED_DisPlay_On()  定义

 详细见上面3.5代码

⑥OLED_Init()初始化代码,是其驱动包内的,可以直接复制我上方OLED_Init()代码

⑦视频内若有不懂代码,可以见我上方3.5代码详细注释!!!

⑧如果代码部分还是不对,别忘了在.h文件中声明下

### STM32 驱动 OLED 显示不清晰的解决方案 当遇到 STM32 控制 OLED 屏幕显示效果不佳的情况时,可能的原因涉及多个方面。为了确保最佳显示质量,可以从以下几个角度进行排查和优化。 #### 1. 检查硬件连接 确认所有硬件连线无误非常重要。特别是对于 SPI 或 I2C 接口,需仔细核对接线是否牢固以及是否存在接触不良等问题[^2]。如果使用的是面包板或其他临时接插件,则更要注意这一点。 #### 2. 调整初始化参数设置 不同的 OLED 屏幕有不同的初始化命令序列。确保所使用的初始化代码完全匹配当前型号的屏幕规格书中的推荐值。例如,在某些情况下调整对比度寄存器可以显著改善视觉体验[^1]。 ```c // 设置OLED对比度(假设为SSD1306芯片) void set_contrast(uint8_t contrast){ SSD1306_WriteCommand(0x81); // 对比度控制指令 SSD1306_WriteCommand(contrast); } ``` #### 3. 修改刷新频率 适当提高或降低帧率也可能有助于解决问题。过高的更新速率可能会导致图像模糊不清;而太慢则会使动画显得卡顿。找到一个平衡点来满足具体应用场景的需求是很重要的[^4]。 #### 4. 更新固件版本 有时制造商会对驱动库做出改进以修复已知缺陷并提升性能表现。因此建议定期访问官方资源获取最新版软件包,并按照说明文档完成升级操作[^3]。 #### 5. 编写高效的图形处理算法 针对特定的应用场景编写更加有效的绘图函数同样能带来明显的好处。比如采用双缓冲技术减少闪烁现象的发生,或是利用DMA传输机制加快数据传送速度从而获得更好的实时响应能力。 ```c // 使用DMA加速像素数据发送 (伪代码示例) HAL_DMA_Start(&hdma_spi_tx, (uint32_t)buffer, (uint32_t)&hspi.Instance->DR, size); while(HAL_SPI_GetState(&hspi)!= HAL_SPI_STATE_READY){}; ``` 通过上述措施通常能够有效解决大部分由软硬件因素引起的STM32驱动下的OLED显示质量问题。当然实际调试过程中还需要结合具体情况灵活应对。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值