STM32F103C8T6-键盘+OLED

一、题目

键盘,编写键盘驱动程序,4键或者16键。实现功能:从都第一个按键到最后一个按键,OLED依次显示0~F。

二、分析

键盘线路如下所示:
在这里插入图片描述

行线

一般将行线设置为输出模式,用于向列线发送扫描信号。

列线

列线的主要功能是读取按键状态。当某一行线被选中(设置为低电平)时,微控制器会读取所有列线的电平状态,以判断是否有按键被按下。

方法

首先将所有 I/O 口设置成高电平。依次将每一行线设置为低电平。当某一行线被设置为低电平时,与之相交的列线会被检测。当检测到列线上有低电平时,可以确定被按下的按键位于当前选中的行上;若列线上无低电平,那么将此行线设置为高电平,下一行设置为低电平,进行新一轮按键检测。

三、CubeMX 配置

在这里插入图片描述
将 PA0 - PA3 (我这里的 PA6 坏了)设置成推挽输出,默认输出高电平;将 PA4 - PA7 设置成输入,默认上拉。
在这里插入图片描述
在这里插入图片描述
配置硬件 IIC:
在这里插入图片描述

四、代码编写

将模块文件复制到项目中:
百度网盘,提取码 2005,KEYBOARD
OLED
主函数中编写:

  /* USER CODE BEGIN 2 */
		OLED_Init();
		OLED_Clear();
  /* USER CODE END 2 */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
//		OLED_Clear();
		OLED_Refresh_Gram();
		char ch = scan_keyboard();
		OLED_ShowChar(0, 0, ch, 16, 1);
//		OLED_ShowChar(0, 16, 'A', 16, 1);
		
    /* USER CODE END WHILE */

此处存在的问题是:原先使用 for 循环进行轮询,使用 int 4 * 4 数组进行状态的记录,但是在 debug 的过程中发现数组经过循环并不能重新置 0,存在多个 1 的情况,因此按键会在按几下之后卡住。因此使用一个 char ch 变量进行状态记录,可以正常运行。

要注意的是,需要在 scan_keyboard 函数的末尾 return ch,当且仅当。

仍然存在的问题是在烧录完成没有按下按键时,会出现奇怪字符占位,尚未找到解决办法。

对于STM32F103C8T6搭配FreeRTOS和OLED直接卡死的问题,可从芯片内存、代码逻辑、任务调度等方面尝试解决。 芯片内存方面,STM32F103C8T6的FLASH为128Kb,SRAM为20Kb,相比正点原子使用的STM32F103VET6(FLASH 512Kb,SRAM 64Kb)内存较小,可能因内存不足导致系统卡死。可检查FreeRTOS的任务堆栈大小,避免分配过大。如在创建任务时,适当减小任务堆栈大小,像`xTaskCreate(Task_OLED,"Task_OLED",512,NULL,16,&TaskHandler_OLED);`中的512可根据实际情况调整。同时,检查代码中是否存在内存泄漏问题,确保内存使用合理[^2]。 代码逻辑方面,仔细检查OLED驱动代码和FreeRTOS任务代码。查看OLED初始化是否正确,如`OLED_Init();`是否成功执行,以及`OLED_Refresh();`和`OLED_ShowNum();`等函数是否正常工作。检查任务函数中的循环逻辑,避免出现死循环或阻塞任务调度的情况。例如在`Task_LED`和`Task_OLED`函数中,`vTaskDelay();`的使用是否合理,确保系统有机会执行其他任务[^3]。 任务调度方面,确认FreeRTOS调度器是否正常启动。在`main`函数中,`vTaskStartScheduler();`启动调度器后,可添加一些调试信息,判断调度器是否启动成功。如果调度器启动失败,程序会进入`while(1)`死循环,可在此处添加指示灯闪烁等调试手段,定位问题所在。同时,检查任务优先级设置是否合理,避免高优先级任务长时间占用CPU,导致其他任务无法执行[^3]。 ```c #include "stm32f10x.h" #include "freertos.h" #include "task.h" #include "semphr.h" #include "delay.h" #include "sys.h" #include "oled.h" BaseType_t FIREMuttex = pdFALSE; // 用于记录任务是否已创建 TaskHandle_t TaskHandler_LED; TaskHandle_t TaskHandler_OLED; void Task_LED(void *arg){ while(1) { LED_ON; //PC13 输出低 vTaskDelay(200);//延时200ms,使系统执行其他任务 LED_OFF; //PC13 输出高 vTaskDelay(200);//延时200ms,使系统执行其他任务 } vTaskDelete(NULL); } void Task_OLED(void *arg){ static int Time=0; while(1){ OLED_Refresh();//update screen OLED_ShowNum(0,0,Time,5,16,1); vTaskDelay(10); } } int main(void) { delay_init(); LED_Init(); OLED_Init(); OLED_ColorTurn(0); OLED_DisplayTurn(0); // 创建任务函数,可根据实际情况调整任务堆栈大小 xTaskCreate(Task_OLED,"Task_OLED",256,NULL,16,&TaskHandler_OLED); xTaskCreate(Task_LED,"Task_LED",256,NULL,10,&TaskHandler_LED); // 开启任务调度 if(xTaskStartScheduler() != pdPASS) { // 调度器启动失败,可添加调试信息 while(1){ LED_ON; // 指示灯常亮 } } // 如果调度器启动成功,程序不会执行到这里 while(1){ // 可添加其他调试信息 } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值