【嵌入式底层知识修炼】按键和LED共用IO口的分时复用扫描方法


只要我跑的速度够快,寂寞就追不上我
只要Key和Led切换速度够快,人眼就看不出来

————小白


  如果你存在按键Key和显示Led共用同一个IO时,需要分时复用的需求,则可以移植代码进行使用:

  • 代码所占code少于0.5K
  • 线程安全,中断安全
  • 可移植性高,配置容易
  • 注意:系统需要存在一个至少为1ms的时钟中断

01 - PCB原理图例程

  举2个Key和Led共用IO口的例子,当MCU的IO口资源不足时,通常会让一些可以用速度欺骗人眼的做法进行资源的节省,比如Key扫描、Led扫描等,例如Led的扫描只要高于25Hz的速度,人眼就基本看不出闪烁,例如Key扫描只要大于100Hz,人的触感就难以察觉。

例程1

在这里插入图片描述

例程2

在这里插入图片描述

02 - 分时复用的注意项和设计

2.1 - 注意项

  Led和Key的分时复用需要考虑几个情况:
  1、Led扫描的频率,必须高于肉眼能看见闪烁的频率25HZ。一般为了效果较好,都会大于50HZ,也就是Led扫描时间<=20ms
  2、保证分时复用,扫描一定要有先后顺序。要确保Led扫描期间不能进行Key扫描,同时确保Key扫描期间不能进行Led扫描
  3、Led需要备份当前状态。因为扫描Key时Led是不起作用的,Key扫描完成后需要恢复Led的状态
  4、注意Led切换为Key时的准备动作。Led切换为Key时根据原理图要做哪些准备工作以防止切换后Key误触发,而Key切换为Led时按照电路决定是否需要做准备动作
  5、Led扫描时间比Key扫描时间长。考虑到肉眼的观察是最容易受影响的,时刻都能看见,而按键的使用次数则较低

2.2 - 设计

  根据注意项,总体设计如下:
  1、系统需要有一个至少为1ms的时钟中断,里面调用扫描ISR函数LedKeyStatusSwitchService_1ms,用于保证高频扫描
  2、理清状态机,存在2种状态的切换,分别为KeyState和LedState,值得注意的是,Led和Key的数量暂时未知,如果数量较多则实际的扫描动作不宜在中断内进行,此时中断则只做状态切换,所以2个状态分别需要一个记录器
  3、决定取舍,Led为人眼可见,最为敏感,Led的扫描动作直接放在中断进行,舍弃Key的中断扫描,让Key在前台进行扫描

03 - 代码实现

  以例程1的PCB为例,整个分时复用时间为6ms(167Hz),其中Led扫描占据4ms,Key扫描占据2ms,下面为参考代码:

#define LED_SACND_TIME_MS	4
#
### 解决STM32G431RBT6在蓝桥杯比赛中遇到的冲突问题 #### 一、理解冲突原因 对于STM32G431RBT6,在蓝桥杯嵌入式竞赛中,LCD与LED显示存在引脚重叠的情况。具体来说,LCD涉及的引脚数量较多,并且这些引脚(如PC8至PC15)也用于控制LED灯,这可能导致两者同时工作时发生资源争用,进而引起LED状态混乱[^4]。 #### 二、解决方案概述 针对上述提到的硬件资源共享带来的干扰问题,可以采取以下几种方法来有效缓解或彻底消除这种影响: #### 三、方案详情 ##### 方法一:分时复用技术的应用 通过编程手段实现对共享GPIO的时间片分配管理,即让LCDLED轮流占用相同的物理接进行操作。这样可以在不影响各自功能的前提下避免直接竞争同一组I/O线路。此方式简单易行但可能会影响响应速度。 ##### 方法二:修改硬件连接布局 如果条件允许的话,重新设计电路板使得LCD屏幕不再依赖于原本被用来驱动指示灯的部分管脚;或者增加额外的逻辑电平转换器件作为中介层隔离二者之间的电气联系。不过这种方法通常只适用于项目初期规划阶段而非临时调整策略。 ##### 方法三:软件层面优化配置 利用微控制器内部丰富的外设特性——比如DMA (Direct Memory Access),定时器等辅助模块配合中断服务程序巧妙安排任务优先级以及执行时机从而达到错开访问周期的效果。这种方式灵活性较高而且不会改变现有硬件架构。 ```c // 使用DMA传输数据给LCD, 减少CPU干预时间窗 HAL_DMA_Start(&hdma_memtomem_dma2_stream0,(uint32_t)&bufferlcd,(uint32_t)LCD_FRAME_BUFFER,LCD_DATA_SIZE); __HAL_LINKDMA(htim,&htim->HDMA_Tx, hdma_memtomem_dma2_stream0); // 设置定时器触发事件处理函数更新LED状态 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ static uint8_t led_state=0; if (htim==&htim2){ // 假定使用TIM2作为计数源 GPIO_WritePin(GPIOC, LED_PIN, !led_state); led_state=!led_state; } } ``` 以上三种途径均可不同程度地改善因共用IO造成的异常状况,实际应用当中可根据具体情况选择最适合的一种或是组合多种措施共同作用以获得最佳效果。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值