0.96寸OLED的使用

7 篇文章 0 订阅
6 篇文章 0 订阅


本文参考和摘抄了部分文章,如下:

  1. 百度文库------0.96寸OLED点亮原理,通过对驱动芯片的设置,实现OLED的点亮,C语言例程,在OLED上显示汉字
  2. SSD1306(OLED驱动芯片)指令详解

写在前面,还是先讲一下OLED的点亮原理,当然是指映射的关系,而不是为什么会发光和和LCD有什么不一样的。


OLED的构造:

OLED由128*64个像素组成,64行和128列
在这里插入图片描述
以此为基础建立一个坐标系如下:
在这里插入图片描述


OLED的驱动芯片:

OLED的核心驱动芯片是SSD1306,单片机与SSD1306通信,SSD1306再驱动OLED点亮对应的OLED像素点。
SSD1306内部有一个GDDRAM数据内存,它有128*8字节,即128*64bit,每一个位对应一个像素点。
这些字节分别存储在Page0~Page7中,每一个页存储128*1个字节
在这里插入图片描述
COM和SEG的方向是可以软件设置的

  • 写入的数据是如何存储的?
    每一个bit存储在一个方格中,每一个方格代表着一个像素点,这样GDDRAM就和像素对应起来了
    在这里插入图片描述
  • SSD1306是如何寻址的?
    先设置内存的寻址模式,接着发送寻址模式

OLED_WCMD(0x20) // 设置内存寻址,模式
OLED_WCMD(0x02) // [1:0],00:垂直地址模式,01:水平地址模式,10:页地址模式

页地址模式:

页地址模式
通常在页地址模式下访问GDDRAM, 需要如下步骤来定义起始RAM访问指针指向:

通过命令(B0h-B7h)设置目标显示位置页起始地址
通过命令(00h-0Fh)设置列起始地址低位
通过命令(10h-1Fh)设置列起始地址高位

例如页地址是B2H,列地址的低地址是03H,列地址的高地址是10H,GDDRAM的访问指针如下:
在这里插入图片描述
给GDDRAM写数据的时候,其列地址会自动加1,列地址到SEG127之后会复位到SEG0,但是行地址不会自动增加,为了写下一页的数据,必须重新设置页地址列地址


水平地址模式:

水平地址模式下,GDDRAM访问,列地址自动加1,到达列地址终止地址时,复位到列地址起始地址,且页地址也自动加1
水平地址的访问图解如下,在页地址和列地址都达到终止地址的时候,都将复位到起始地址
在这里插入图片描述


垂直地址模式:

垂直地址模式下,GDDRAM访问,页地址自动加1,到达页地址终止地址时,复位到页地址起始地址,且列地址也自动加1
垂直地址的访问图解如下,在页地址和列地址都达到终止地址的时候,都将复位到起始地址
在这里插入图片描述
在这里插入图片描述
通常在(垂直/水平)地址模式下访问GDDRAM, 需要如下步骤来定义起始RAM访问指针指向:

通过命令(21h)设置目标显示位置列起始地址以及列终止地址
通过命令(22h)设置目标显示位置页起始地址以及页终止地址


SSD1306提供的通信方式是多种的,IIC,4线SPI,3线SPI,还有6800并行,8080并行方式
关于SSD1306的指令详解

  • 10
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
下面是STM32F103C8T6通过I2C接口控制0.96OLED的按键切换代码示例。 首先,需要在STM32CubeMX中配置I2C接口和GPIO口,具体步骤如下: 1. 打开STM32CubeMX软件,选择对应的芯片型号。 2. 在Pinout选项卡中,将SCL和SDA引脚配置为I2C接口。 3. 在Configuration选项卡中,配置I2C接口的速度、地址等参数。 4. 配置按键所需的GPIO口,设置为输入模式。 5. 生成代码并导入到Keil中。 接下来,可以使用以下代码实现按键切换OLED显示内容: ```c /* I2C相关定义 */ #define I2C_SCL_Pin GPIO_PIN_6 #define I2C_SCL_GPIO_Port GPIOB #define I2C_SDA_Pin GPIO_PIN_7 #define I2C_SDA_GPIO_Port GPIOB #define OLED_I2C_ADDR 0x78 /* 按键相关定义 */ #define KEY1_Pin GPIO_PIN_13 #define KEY1_GPIO_Port GPIOC #define KEY2_Pin GPIO_PIN_14 #define KEY2_GPIO_Port GPIOC /* OLED相关定义 */ #define OLED_WIDTH 128 #define OLED_HEIGHT 64 #define OLED_CMD 0x00 #define OLED_DAT 0x40 /* OLED初始化命令 */ const uint8_t InitCmd[] = { 0xAE, // 关闭显示 0xD5, 0x80, // 设置时钟分频因子,震荡频率 0xA8, 0x3F, // 设置驱动路数 0xD3, 0x00, // 设置显示偏移 0x40, // 设置起始行 0x8D, 0x14, // 设置电荷泵 0x20, 0x00, // 设置地址模式,水平寻址模式 0xA0, // 设置段重定义 0xC8, // 设置COM扫描方向 0xDA, 0x12, // 设置COM硬件引脚配置 0x81, 0xCF, // 设置对比度 0xD9, 0xF1, // 设置预充电周期 0xDB, 0x40, // 设置VCOMH 0xA4, // 全局显示开启 0xA6, // 设置正反显示 0xAF, // 打开显示 }; /* OLED清屏命令 */ const uint8_t ClearCmd[] = { 0x00, 0x10, // 设置列起始地址 0x00, 0x7F, // 设置列结束地址 0xB0, // 设置页地址 }; /* OLED显示内容 */ const uint8_t Logo[] = { 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; /* I2C初始化函数 */ void I2C_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_I2C1_CLK_ENABLE(); HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 1); HAL_NVIC_EnableIRQ(I2C1_EV_IRQn); /* 配置SCL和SDA引脚 */ GPIO_InitStruct.Pin = I2C_SCL_Pin | I2C_SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* 配置I2C1 */ I2C_HandleTypeDef hi2c1 = {0}; hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 400000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(&hi2c1); } /* I2C发送数据函数 */ void I2C_SendData(uint8_t addr, uint8_t *data, uint16_t len) { HAL_I2C_Master_Transmit_IT(&hi2c1, addr, data, len); while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY); } /* OLED写命令函数 */ void OLED_WriteCmd(uint8_t cmd) { uint8_t data[] = {OLED_CMD, cmd}; I2C_SendData(OLED_I2C_ADDR, data, sizeof(data)); } /* OLED写数据函数 */ void OLED_WriteDat(uint8_t dat) { uint8_t data[] = {OLED_DAT, dat}; I2C_SendData(OLED_I2C_ADDR, data, sizeof(data)); } /* OLED初始化函数 */ void OLED_Init(void) { for (uint16_t i = 0; i < sizeof(InitCmd); i++) { OLED_WriteCmd(InitCmd[i]); } } /* OLED清屏函数 */ void OLED_Clear(void) { OLED_WriteCmd(ClearCmd[0]); OLED_WriteCmd(ClearCmd[1]); OLED_WriteCmd(ClearCmd[2]); for (uint16_t i = 0; i < OLED_HEIGHT / 8; i++) { OLED_WriteCmd(0xB0 + i); OLED_WriteCmd(0x00); OLED_WriteCmd(0x10); for (uint16_t j = 0; j < OLED_WIDTH; j++) { OLED_WriteDat(0x00); } } } /* OLED显示函数 */ void OLED_Show(uint8_t *data) { OLED_WriteCmd(0x00); OLED_WriteCmd(0x10); for (uint16_t i = 0; i < OLED_HEIGHT / 8; i++) { OLED_WriteCmd(0xB0 + i); OLED_WriteCmd(0x00); OLED_WriteCmd(0x10); for (uint16_t j = 0; j < OLED_WIDTH; j++) { OLED_WriteDat(data[i * OLED_WIDTH + j]); } } } /* 按键扫描函数 */ uint8_t KEY_Scan(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) { static uint8_t key_up = 1; if (key_up && HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) == GPIO_PIN_RESET) { HAL_Delay(10); key_up = 0; if (HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) == GPIO_PIN_RESET) { return 1; } } else if (HAL_GPIO_ReadPin(GPIOx, GPIO_Pin) == GPIO_PIN_SET) { key_up = 1; } return 0; } int main(void) { HAL_Init(); I2C_Init(); OLED_Init(); uint8_t show_logo = 1; while (1) { if (KEY_Scan(KEY1_GPIO_Port, KEY1_Pin)) { show_logo = !show_logo; } if (KEY_Scan(KEY2_GPIO_Port, KEY2_Pin)) { OLED_Clear(); } if (show_logo) { OLED_Show((uint8_t *)Logo); } else { OLED_Clear(); } HAL_Delay(10); } } ``` 在上述代码中,首先定义了I2C相关的引脚和OLED的I2C地址,以及按键和OLED的分辨率等参数。 然后,通过I2C_Init函数初始化I2C接口,并实现了I2C_SendData、OLED_WriteCmd、OLED_WriteDat等函数用于控制OLED的显示和清屏操作。 最后,在主函数中使用KEY_Scan函数对按键进行扫描,根据按键状态切换OLED显示内容或清屏,并通过OLED_Show函数将数据发送给OLED进行显示。 需要注意的是,本例中使用了HAL库进行操作,如果使用其他库或裸机编程,可能需要做出一些修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值