[应用方案] 按键和LED复用扫描程序

[复制链接]
3163|11
 楼主| dentsgot 发表于 2016-4-7 20:31 | 显示全部楼层 |阅读模式
在我们的实际产品开发过程中,为了节省成本,常常会采用按键和LED复用,从而达到节省IO口的目的。很多刚刚碰到这种情况的工程师,可能会不知道如何处理,PS:大神请自动略过。下面由我来给大家讲讲按键和LED复用IO口时,程序该如何处理吧。(上一讲已经讲过,我个人比较喜欢状态机编程,因此这里还是采用状态机编程的方法,来实现按键和LED复用扫描功能)。
LEDC是LED灯的COM控制端,LED1_K1和LED2_K2是按键和LED的复用IO口。扫描过程如下:
1、上电初始化时,先将LEDC、LED1_K1和LED2_K2设置为推挽输出高;
2、首先扫描LED1和LED2,LEDC输出高,LED1_K1根据系统标志判断,LED1需要亮,就输出低,LED1不需要亮,就输出高,LED2和LED1处理一样。
3、LED1和LED2扫描完成以后,LEDC输出低,LED1和LED2输出高,将LED1_K1和LED2_K2的IO口切换为输入状态,并且用一个变量备份一下LED1和LED2的输出电平状态,以便按键扫描完成后,恢复LED1和LED2的亮灭状态。
4、进入按键扫描状态,读取LED1_K1和LED2_K2引脚的电平状态,读取IO口电平完成以后,立即将LED1_K1和LED2_K2切换为推挽输出低模式,并且恢复步骤3中备份的LED1_K1和LED2_K2的电平状态到LED1_K1和LED2_K2管脚上。
以上四个步骤就是按键和LED复用时,程序的扫描过程,看不懂的话没有关系,大家结合源代码理解,就很清楚了。按键和LED复用扫描程序如下:
  1. /**********************************************************
  2. * 名称: void Led2Disp_Scan(void)
  3. * 功能: led2和按键扫描函数
  4. * 形参: 无
  5. * 返回: 无
  6. * 说明: 无
  7. 注意:当在使用STM8单片机编程时,切换IO口的输入输出状态时,请将IO口配置成低速模式(2MHz),要不然在切换IO口的输入输出状态时,会触发IO口的外部中断,造成程序异常。
  8. **********************************************************/
  9. void Led2Disp_Scan(void)
  10. {
  11.    static INT8U scan_num = 0;//扫描状态变量
  12.    scan_num++;
  13.    switch(scan_num)
  14.    {
  15.       case 1://状态1扫描LED灯
  16.       {
  17.         COM1_ON();//置高LED公共端
  18.       LedDisp_Process(0,Bit_TyPeDefStructure.led2_disp);//根据标志位控制LED2的亮灭
  19.       LedDisp_Process(1,Bit_TyPeDefStructure.led1_disp);//根据标志位控制LED1的亮灭
  20.       }
  21.       break;
  22.       case 2://LED灯扫描完毕
  23.       {
  24.         COM1_OFF();//置低LED公共端
  25.         PC_ODR_BACK = GPIOC->ODR;//备份LED端口输出寄存器

  26.         LED1_ON();//LED1和LED2引脚置高
  27.         LED2_ON();
  28.         IO_INPUT();//切换成输入模式
  29.       }
  30.       break;
  31.       case 12://按键扫描一次的时间12*250us等于3ms
  32.       {
  33.         process_key();//按键处理函数,看不懂请参考源代码理解,还是看不懂,请阅读我上一篇帖子“基于状态机的按键扫描程序”
  34.         scan_num = 0;//按键扫描完成后,回到状态0,继续LED灯的扫描
  35.       }
  36.       break;
  37.       default :
  38.       break;
  39.    }
  40. }
  41. 以上就是整个扫描过程,注释已经讲解的很清楚了,就不在继续讲了。按键处理函数看不懂,请看我上一篇博文“基于状态机的按键扫描程序”一文。

  42. //main函数如下:
  43. int main(void)
  44. {
  45.        //设置内部16M晶振为系统时钟
  46.        System_Init();////
  47.        while (1)
  48.        {
  49.               IWDG_ReloadCounter();//清看门狗

  50.               if(fTimer1_250us)//查询是否到250us
  51.               {
  52. Led2Disp_Scan();
  53.                      fTimer1_250us = FALSE;//250us到任务处理完成,清除250us到标志
  54.               }           
  55.        }
  56. }
以上程序实现的功能是,短按K1,LED1亮,LED2灭;短按K2,LED1灭,LED2亮;长按K1两秒,LED1翻转;长按K2两秒,LED2翻转;K1和K2同时按下2秒,LED1和LED2都翻转。附件使用的是STM8S003F3单片机编程实现的,大家可以移植到任何平台,不会的可以跟帖回复,我可以和大家共同探讨,具体源代码请查看附件,大家可以安装source insight软件进行阅读。

gejigeji521 发表于 2016-4-7 21:46 | 显示全部楼层
看半天终于明白 了,原来可以这么使用管脚
gaoyang9992006 发表于 2016-4-8 18:17 | 显示全部楼层
IO口复用图例
降低成本,IO复用势在必得,设计是种艺术,IO复用的关键就是分时轮流扫描或检测,下面是一些复用例子,自己体会吧。
001.jpg 002.png 003.jpg 004.jpg 005.png

gaoyang9992006 发表于 2016-4-8 18:17 | 显示全部楼层
gaoyang9992006 发表于 2016-4-8 18:19 | 显示全部楼层
有的高级键盘按下去就会亮,就是这个道理。
zhuotuzi 发表于 2016-4-8 18:28 | 显示全部楼层
那几个图不错,可以学习学习,以后项目中可以做几个炫酷的按键了
DreamofOven 发表于 2016-4-11 15:17 | 显示全部楼层
一个按键就能实现那么多的功能,单片机真是博大精深啊
Rooney30 发表于 2016-4-12 20:46 | 显示全部楼层
这个按键相互之间会不会有干扰啊
gradyhuang 发表于 2016-11-22 17:41 | 显示全部楼层
赛元触摸MCU。可以实现触摸和LED复用,性能优异,可过CS动态10V,可加Q2920952784索取资料
831.png
quray1985 发表于 2016-11-22 20:46 | 显示全部楼层
以前按键和LED都是分开用,现在学习了可以复用了
643757107 发表于 2016-11-22 22:30 | 显示全部楼层

一、  按键和LED复用原理图如下:

20160224195615214.jpg

LEDC是LED灯的COM控制端,LED1_K1和LED2_K2是按键和LED的复用IO口。扫描过程如下:

1、上电初始化时,先将LEDC、LED1_K1和LED2_K2设置为推挽输出高;

2、首先扫描LED1和LED2,LEDC输出高,LED1_K1根据系统标志判断,LED1需要亮,就输出低,LED1不需要亮,就输出高,LED2和LED1处理一样。

3、LED1和LED2扫描完成以后,LEDC输出低,LED1和LED2输出高,将LED1_K1和LED2_K2的IO口切换为输入状态,并且用一个变量备份一下LED1和LED2的输出电平状态,以便按键扫描完成后,恢复LED1和LED2的亮灭状态。

4、进入按键扫描状态,读取LED1_K1和LED2_K2引脚的电平状态,读取IO口电平完成以后,立即将LED1_K1和LED2_K2切换为推挽输出低模式,并且恢复步骤3中备份的LED1_K1和LED2_K2的电平状态到LED1_K1和LED2_K2管脚上。


500days 发表于 2016-11-24 18:54 | 显示全部楼层
按键和LED可以复用,这样真的很节省资源
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

164

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部