找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4559|回复: 8
打印 上一主题 下一主题
收起左侧

请教一个单片机io口识别两个按键的问题

[复制链接]
跳转到指定楼层
楼主
本人菜鸟工程师,最近公司业务给我一个单片机板子。要抄板。

主控室一颗8脚的mcu,丝印被磨掉了。其中一个引脚控制了两个按键。对应原理图如下。




现用代码实现如下。

  1. #include <STC15F2K60S2.H>
  2. #include <intrins.h>

  3. sbit key = P2^6;
  4. sbit test = P2^7;
  5. sbit test2 = P2^5;

  6. bit key1 = 0;
  7. bit key1_last = 0;
  8. bit key2 = 0;
  9. bit key2_last = 0;

  10. void ConfigTimer0();
  11. void Key_Scanf();

  12. void main()
  13. {
  14.         ConfigTimer0();
  15.         EA = 1;

  16.         while(1)
  17.         {
  18.                  Key_Scanf();
  19.         }
  20. }

  21. void ConfigTimer0()                        //12mhz  100us
  22. {
  23.         AUXR &= 0x7F;                //定时器时钟12T模式
  24.         TMOD &= 0xF0;                //设置定时器模式
  25.         TL0 = 0x30;                //设置定时初值
  26.         TH0 = 0xF8;                //设置定时初值
  27.         TF0 = 0;                //清除TF0标志
  28.         TR0 = 1;                //定时器0开始计时
  29.         ET0 = 1;
  30. }

  31. void Key_Scanf()
  32. {
  33.          if(key1_last != key1)
  34.         {
  35.                 key1_last = key1;
  36.                 if(1 == key1)
  37.                 {
  38.                         test = ~test;         
  39.                 }               
  40.         }
  41.         
  42.         if(key2_last != key2)
  43.         {
  44.                 key2_last = key2;
  45.                 if(1 == key2)
  46.                 {
  47.                         test2 = ~test2;         
  48.                 }               
  49.         }        
  50. }

  51. void InterruptTimer0() interrupt 1
  52. {
  53.          static unsigned char cnt = 0;
  54. //        static unsigned char key_down_cnt = 0;
  55. //        static unsigned char key_up_cnt = 0;
  56.         
  57.         static unsigned char key_buf = 0x0f;

  58.         key_buf <<= 1;

  59.         if(key == 1)
  60.         {
  61.                  key_buf = key_buf | 0x01;
  62.         }
  63.         else
  64.         {
  65.                 key_buf = key_buf & 0xfe;         
  66.         }

  67.         if(key_buf == 0xff)
  68.         {
  69.                  key1 = 1;
  70.                 key2 = 0;               
  71.         }
  72.         else if(key_buf == 0x00)
  73.         {
  74.                    key1 = 0;
  75.                 key2 = 1;
  76.         }
  77.         else
  78.         {
  79.                 key1 = 0;
  80.                 key2 = 0;
  81.         }


  82.         if(cnt == 0)
  83.         {
  84.                  key = 1;
  85.                 P2M0 = 0x00;P2M1 = 0x00;
  86. //                P2M0 = 0x00;P2M1 = 0xff;
  87. //                P2M0 = 0xff;P2M1 = 0x00;
  88. //                P2M0 = 0xff;P2M1 = 0xff;
  89. //                key = 1;
  90.                 cnt++;
  91.         }               
  92.         else
  93.         {
  94. //                 key = 0;
  95. //                P2M0 = 0x00;P2M1 = 0x00;
  96.                 P2M0 = 0x00;P2M1 = 0xff;
  97. //                P2M0 = 0xff;P2M1 = 0x00;
  98. //                P2M0 = 0xff;P2M1 = 0xff;
  99.                 key = 0;
  100.                 cnt = 0;
  101.         }
  102. //        else{}
  103. }
复制代码

示波器检测按键io口,如下。

无按键



上拉部分按键



下拉部分按键



但程序最终还是无法很好的实现功能。
给各位一下参考,共同探讨一下。




分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2018-5-8 21:02 | 只看该作者
//使用STC15W104系列
#include <STC15F2K60S2.H>
#define uint unsigned int
#define uchar unsigned char
sbit key = P3^2;
sbit LED1= P3^3;
sbit LED2= P3^4;

void delay(uint k)//1ms延时
{
        uint i,j;
        for(i=k;i>0;i--)
                for(j=114;j>0;j--);
}

void key_scan()//按键扫描程序
{
        P2M1|=0x40;        //P2.6设置高阻
        key=0;                //P2.6置0
        if(key==1)        //判断是否为1,S1按下
        {
                delay(10);//延时       
                if(key==1)//再次判断是否为1,S1按下
                {
                        LED1=0;//LED输出状态
                        LED2=1;
                }
        }
        P2M1&=0xBF; //P2.6设置准双向
        key=1;                //P2.6置1
        if(key==0)        //判断是否为0,S3按下
        {
                delay(10);//延时       
                if(key==0)//再次判断是否为0,S3按下
                {
                        LED1=1;//LED输出状态
                        LED2=0;
                }               
        }
}

void main()
{
        P3M0=0x00;        //初始化P3口准双向
        P3M1=0x00;        //初始化P3口准双向
        LED1=1;                //初始化LED1熄灭
        LED2=1;                //初始化LED2熄灭
        while(1)
        {
                key_scan();//按键扫描
        }
}
回复

使用道具 举报

板凳
ID:960619 发表于 2021-11-9 14:57 | 只看该作者
本帖最后由 baobao125 于 2021-11-9 14:59 编辑
wulin 发表于 2018-5-8 21:02
//使用STC15W104系列
#include
#define uint unsigned int

这样不行,实际电路这样按键S1是一直被按下的状态,P26一下置1一下置0,检测P26才1.5V左右跳动,为何就成了高电平?
回复

使用道具 举报

地板
ID:624769 发表于 2021-11-9 16:06 | 只看该作者
这东西8年前还是多少年前,STC刚出15系列的时候,倒是研究过。
这个电路,需要加个电容,和下拉电阻,

先用强推挽给电容充电,然后转高阻,读取按键,
如果依然是高,说明接地的按键没有按下,不然电容被放电了。
然后,等待一定时间,(取决于电容和下拉电阻),变低了,说明接VCC的按键也没有按下,反之,接VCC按键按下了。
回复

使用道具 举报

5#
ID:960619 发表于 2021-11-9 17:55 | 只看该作者
188610329 发表于 2021-11-9 16:06
这东西8年前还是多少年前,STC刚出15系列的时候,倒是研究过。
这个电路,需要加个电容,和下拉电阻,

就上面的电路,用ADC去判断应该可以吧
回复

使用道具 举报

6#
ID:624769 发表于 2021-11-9 18:35 | 只看该作者
baobao125 发表于 2021-11-9 17:55
就上面的电路,用ADC去判断应该可以吧

用ADC判断就没必要这样接了,这样接明显是没有ADC的IO,不过这个接法有缺陷,虽然IO = 1 可以被接地的按钮拉低, 但是IO = 0, 不是所有的单片机都可以被接VCC的按钮拉高,所以要有通用性的话,还是需要利用电容充放电来确认接VCC的按键有没有按下。
回复

使用道具 举报

7#
ID:587810 发表于 2021-11-10 16:15 | 只看该作者
识别高低电平就可以了吧
回复

使用道具 举报

8#
ID:966423 发表于 2021-12-2 10:26 | 只看该作者
你这样还不如直接放AD口,两个电阻不一样的话AD值就不一样了,就可以判断了
回复

使用道具 举报

9#
ID:979299 发表于 2021-12-2 11:25 | 只看该作者
图上不是一个引脚控制两个按键,是两个按键控制一个引脚,按上面输入高电平,按下面输入低电平。又看到回复S1是一直按下去的,那就一直是高电平了啊,就没有按键的意义了,如果P2.6为低电平按S3没有作用的,如果P2.6为高电平时,S1常通又按S3相当于经R7取得一个中间值,这个值对单片机无用。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表