#define OLED_SCL_Clr() GPIO_ResetBits(SCL_GPIO_PORT,SCL_GPIO_PIN)//SCL #define OLED_SCL_Set() GPIO_SetBits(SCL_GPIO_PORT,SCL_GPIO_PIN) #define OLED_SDA_Clr() GPIO_ResetBits(SDA_GPIO_PORT,SDA_GPIO_PIN)//DIN #define OLED_SDA_Set() GPIO_SetBits(SDA_GPIO_PORT,SDA_GPIO_PIN) #define OLED_RES_Clr() #define OLED_RES_Set() #define OLED_CMD 0 //дÃüÁî #define OLED_DATA 1 //дÊý¾Ý
时间: 2025-05-20 12:40:23 浏览: 15
### 按键扫描与 OLED 显示功能实现及优化方法
#### 按键扫描逻辑分析
按键扫描通常用于检测用户输入,以便控制系统的行为。以下是对按键扫描部分的详细解读:
1. **轮询方式**
- 使用循环定期检查按键状态是最常见的实现方法之一。例如,在代码中通过函数 `key_Scan(0)` 获取当前按键编号[^9]。
- 轮询的优点在于简单易懂,缺点则是会占用 CPU 时间,尤其是在高频查询的情况下。
2. **去抖动处理**
- 物理按键由于机械特性可能会产生多次瞬态信号(即“抖动”)。因此,必须加入延时或其他滤波算法来消除这种干扰[^10]。
- 示例代码如下:
```c
uint8_t key_scan(uint8_t mode) {
static uint8_t last_key = NO_KEY;
uint8_t current_key;
// 模拟读取硬件端口
current_key = read_hardware_port();
if (current_key != last_key) {
delay_ms(20); // 去抖延迟
if (read_hardware_port() == current_key) {
last_key = current_key;
return current_key; // 返回有效按键值
}
}
return NO_KEY; // 表示无按键按下
}
```
3. **中断驱动型按键扫描**
- 对于实时性要求较高的场景,推荐采用外部中断的方式捕获按键事件。这种方式能够显著降低功耗并提高响应速度[^11]。
---
#### OLED 显示功能实现详解
OLED 显示屏作为嵌入式设备的重要外设之一,常被用来呈现图形化界面或动态数据。以下是其实现的关键要点:
1. **IIC/SPI 接口通信协议**
- 大多数小型 OLED 屏幕支持 IIC 或 SPI 协议进行数据传输。其中,IIC 更适合低速率应用,而 SPI 提供更高的吞吐率[^12]。
- 初始化屏幕前需正确配置相应的 GPIO 引脚以及波特率/频率参数。
2. **字符与图像渲染**
- 字符显示可通过逐点写入 ASCII 编码对应的像素矩阵完成。对于复杂字体或者中文字符,则需要加载预定义好的字库文件[^13]。
- 图像绘制涉及更多计算量,建议预先存储 BMP 文件或者其他格式的数据模板再上传至内存缓冲区最后刷新到屏幕上。
3. **性能优化策略**
- 减少不必要的重绘操作——仅更新发生变化的部分区域而非整个画面;
- 利用双缓冲技术避免闪烁现象发生;
- 将频繁使用的图案存放在 Flash 中减少 RAM 占用量同时加快访问速度[^14].
---
### 综合案例:结合按键与 OLED 的互动程序
下面给出一段综合运用以上知识点的例子,展示如何让四个不同按钮分别调整数值并通过 OLED 输出结果:
```c
#include "stm32fxxx_hal.h"
#include "ssd1306.h"
#define DELAY_TIME_MS 50
uint8_t waternumber = 1, watertime1 = 1, Time1 = 1;
char strTest[5];
void update_oled(void){
SSD1306_Clear();
sprintf(strTest,"Water:%d",waternumber);
SSD1306_GotoXY(0 , 0 );
SSD1306_WriteString(strTest,FONT_11X18,White);
sprintf(strTest,"Time1:%d",watertime1);
SSD1306_GotoXY(0 , 20);
SSD1306_WriteString(strTest,FONT_7X10,White);
sprintf(strTest,"Delay:%d",Time1);
SSD1306_GotoXY(0 , 35);
SSD1306_WriteString(strTest,FONT_7X10,White);
}
int main(){
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
SSD1306_Init();
while (true){
switch(key_Scan(0)){
case KEY1_PRES:
waternumber++;
if(waternumber > 3) waternumber = 1;
break;
case KEY2_PRES:
watertime1 += 1;
if(watertime1 > 40) watertime1 = 1;
break;
case KEY3_PRES:
/* Toggle Motor State Logic Here */
break;
case KEY4_PRES:
Time1 += 1;
if(Time1 > 40) Time1 = 1;
break;
}
update_oled();
HAL_Delay(DELAY_TIME_MS);
}
}
```
---
阅读全文
相关推荐



















