单片机学习笔记——按键和LED复用扫描程序

58 篇文章 0 订阅
32 篇文章 1 订阅

在我们的实际产品开发过程中,为了节省成本,常常会采用按键和LED复用,从而达到节省IO口的目的。很多刚刚碰到这种情况的工程师,可能会不知道如何处理,PS:大神请自动略过。下面由我来给大家讲讲按键和LED复用IO口时,程序该如何处理吧。(上一讲已经讲过,我个人比较喜欢状态机编程,因此这里还是采用状态机编程的方法,来实现按键和LED复用扫描功能)。

一、  按键和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复用扫描程序如下:

/**********************************************************

 * 名称: void Led2Disp_Scan(void)

 * 功能: led2和按键扫描函数

 * 形参: 无

 * 返回: 无

 * 说明: 无

注意:当在使用STM8单片机编程时,切换IO口的输入输出状态时,请将IO口配置成低速模式(2MHz),要不然在切换IO口的输入输出状态时,会触发IO口的外部中断,造成程序异常。

 **********************************************************/

void Led2Disp_Scan(void)

{

   static INT8U scan_num = 0;//扫描状态变量

   scan_num++;

   switch(scan_num)

   {

      case 1://状态1扫描LED灯

      {

        COM1_ON();//置高LED公共端

      LedDisp_Process(0,Bit_TyPeDefStructure.led2_disp);//根据标志位控制LED2的亮灭

      LedDisp_Process(1,Bit_TyPeDefStructure.led1_disp);//根据标志位控制LED1的亮灭

      }

      break;

      case 2://LED灯扫描完毕

      {

        COM1_OFF();//置低LED公共端

        PC_ODR_BACK = GPIOC->ODR;//备份LED端口输出寄存器

       

        LED1_ON();//LED1和LED2引脚置高

        LED2_ON();

        IO_INPUT();//切换成输入模式

      }

      break;

      case 12://按键扫描一次的时间12*250us等于3ms

      {

        process_key();//按键处理函数,看不懂请参考源代码理解,还是看不懂,请阅读我上一篇帖子“基于状态机的按键扫描程序”

        scan_num = 0;//按键扫描完成后,回到状态0,继续LED灯的扫描

      }

      break;

      default :

      break;

   }

}

以上就是整个扫描过程,注释已经讲解的很清楚了,就不在继续讲了。按键处理函数看不懂,请看我上一篇博文“基于状态机的按键扫描程序”一文。

 

//main函数如下:

int main(void)

{

       //设置内部16M晶振为系统时钟

       System_Init();

       while (1)

       {

              IWDG_ReloadCounter();//清看门狗

             

              if(fTimer1_250us)//查询是否到250us

              {

Led2Disp_Scan();

                     fTimer1_250us = FALSE;//250us到任务处理完成,清除250us到标志

              }           

       }

}

 

以上程序实现的功能是,短按K1,LED1亮,LED2灭;短按K2,LED1灭,LED2亮;长按K1两秒,LED1翻转;长按K2两秒,LED2翻转;K1和K2同时按下2秒,LED1和LED2都翻转。附件使用的是STM8S003F3单片机编程实现的,大家可以移植到任何平台,不会的可以跟帖回复,我可以和大家共同探讨,具体源代码请查看附件,大家可以安装source insight软件进行阅读。

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
数码管是一种常见的数字显示器件,可以用于显示各种数字、字母等字符。在单片机应用中,数码管通常用于显示计数器、计器、温度、湿度等实数据。 数码管的种类有很多,包括共阳数码管、共阴数码管、共阳共阴混合数码管等。其中,共阳数码管是最常见的一种,也是本文所涉及的数码管类型。 单片机控制数码管的原理是通过对数码管的各个管脚进行控制,使其显示相应的数字或字符。数码管的控制方式有两种,即静态显示和动态显示。 静态显示是指将要显示的数字或字符的每一位分别输出到数码管的每个管脚上,然后使其保持不变,从而实现显示效果。静态显示的缺点是需要使用大量的I/O口,且不能灵活地改变显示内容。 动态显示是指将要显示的数字或字符的每一位依次输出到数码管的每个管脚上,并在短间内快速切换下一个数字或字符,从而形成连续的显示效果。动态显示的优点是可以使用较少的I/O口,且可以灵活地改变显示内容。 以下是一个简单的动态显示数码管的实现示例: 1. 定义数码管的引脚 ```c #define DIG_PORT P2 // 数码管位选端口 #define DIG_COM 0x00 // 数码管位选端口初始值 #define LED_PORT P0 // 数码管段选端口 ``` 2. 定义数码管显示的数字或字符 ```c unsigned char code ledChar[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; ``` 3. 实现数码管动态显示函数 ```c void display(unsigned char i) { unsigned char j, k; for (j = 0; j < 8; j++) { DIG_PORT = DIG_COM | (1 << j); // 选择数码管位(从左到右) for (k = 0; k < 100; k++); // 延,视情况可调整 LED_PORT = ledChar[i]; // 显示数码管上的数字或字符 } } ``` 4. 调用数码管动态显示函数 ```c int main() { unsigned char i = 0; while (1) { display(i % 10); // 显示数字 i 的个位数 i++; } return 0; } ``` 以上就是一个简单的数码管动态显示的实现示例。需要注意的是,数码管的控制方式和具体实现方法可能因不同的硬件平台和编程语言而有所不同。因此,在具体应用中需要根据实际情况进行适当的调整和修改。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值