找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3130|回复: 25
收起左侧

单片机一个io口驱动发光二极管并扫描按键程序调试

[复制链接]
ID:777834 发表于 2021-9-3 08:24 来自手机 | 显示全部楼层 |阅读模式
各位大佬,这个程序怎样写,我按照之前的一个帖子例程反复调试都不成功,LED1在P1.5口、LED2在P1.4口,路过帮帮忙,多谢啊
IMG_20210903_081739.jpg
回复

使用道具 举报

ID:887371 发表于 2021-9-3 10:00 | 显示全部楼层
平时端口设为推挽,驱动led亮或灭。
需要读取按键时,端口设为弱上拉。此时按键如果是按下的,端口电压为1/11*Vcc,为低电平。按键如果没按下,端口电压是LED管压降,如果是红灯的话,约为2V。如果要准确识别为高电平的话,Vcc应小于2.85V(2/0.7=2.85)。绿灯管压降烧大于红灯,情形会稍微好点。

因此,这电路要能正常工作,Vcc电压要足够低才行。另外在检测按键时按键又没按下,灯会微弱发光。
总体上这电路不是很好。
回复

使用道具 举报

ID:332444 发表于 2021-9-3 10:18 | 显示全部楼层
有必要这样做?原先的独立按键一个IO就能实现2个按键,51与32的原理都是一样的只是写法不同而已。可参https://blog.csdn.net/xianfajushi/article/details/106518315
回复

使用道具 举报

ID:796531 发表于 2021-9-3 10:45 | 显示全部楼层
为啥要这么接 ,是否考虑I/O用开漏输出,发光管串电阻接vcc和I/O ,开关接I/O 和地, 写一个sbitI/O输出高电平 发光管亮;I/O输出低电平 ,读取I/O实际状态,按键没按读到高电平,按钮按下就会读到低电平,这样是否可行
回复

使用道具 举报

ID:415064 发表于 2021-9-3 14:39 | 显示全部楼层
分时复用,在小家电很常见。led你理解呼吸灯一亮一灭的,在灭的时候检测按键就行了
回复

使用道具 举报

ID:777834 发表于 2021-9-3 15:05 来自手机 | 显示全部楼层
wojiaoguogai 发表于 2021-9-3 14:39
分时复用,在小家电很常见。led你理解呼吸灯一亮一灭的,在灭的时候检测按键就行了

你好,我按照这个调试不行,可以帮看看
回复

使用道具 举报

ID:777834 发表于 2021-9-3 15:06 来自手机 | 显示全部楼层
wojiaoguogai 发表于 2021-9-3 14:39
分时复用,在小家电很常见。led你理解呼吸灯一亮一灭的,在灭的时候检测按键就行了

可以帮看看吗
http://www.51hei.com/bbs/dpj-194413-1.html
这个链接
回复

使用道具 举报

ID:161164 发表于 2021-9-3 15:30 | 显示全部楼层
jianuli 发表于 2021-9-3 15:06
可以帮看看吗
http://www.51hei.com/bbs/dpj-194413-1.html
这个链接

你把你的代码完整地贴上来看看
(不要截图!不要截图!不要截图!)
回复

使用道具 举报

ID:887371 发表于 2021-9-3 16:38 | 显示全部楼层
jianuli 发表于 2021-9-3 15:06
可以帮看看吗
http://www.51hei.com/bbs/dpj-194413-1.html
这个链接

我二楼已经分析清楚了。

另外我看了http://www.51hei.com/bbs/dpj-194413-1.html链接的帖子,代码OK。
要正常工作,请把Vcc电压调到2.5V。
回复

使用道具 举报

ID:887371 发表于 2021-9-3 17:10 | 显示全部楼层
楼主就不能有点独立思考的能力?正确解答摆你面前,也不会分析验证。就只会说不成功,求指导。

寻求解决问题的正确方式:
问题背景描述
问题现象
为解决问题做了哪些尝试?有啥效果?
回复

使用道具 举报

ID:161164 发表于 2021-9-3 17:53 来自手机 | 显示全部楼层
datouyuan 发表于 2021-9-3 16:38
我二楼已经分析清楚了。

另外我看了http://www.51hei.com/bbs/dpj-194413-1.html链接的帖子,代码OK。 ...

二楼的分析有一个问题
就是设置完弱上拉后
端口要先置1才可以读取输入状态
这时端口电压还是1/11 VCC吗?
Screenshot_2021-09-03-17-52-12-922_cn.wps.moffice_eng~01.jpg
回复

使用道具 举报

ID:887371 发表于 2021-9-4 08:48 | 显示全部楼层
lkc8210 发表于 2021-9-3 17:53
二楼的分析有一个问题
就是设置完弱上拉后
端口要先置1才可以读取输入状态

问题不大,mcu内部上拉等效电阻约为500k欧姆,对10K电阻上拉电阻影响太小了,1/11 VCC这个值没错。
另外端口要置1后才可以读取输入状态,这是51mcu必须要的,否则端口值不是1/11 VCC了,而是接近于0V。
回复

使用道具 举报

ID:887371 发表于 2021-9-4 08:54 | 显示全部楼层
lkc8210 发表于 2021-9-3 17:53
二楼的分析有一个问题
就是设置完弱上拉后
端口要先置1才可以读取输入状态
端口要先置1才可以读取输入状态

这不是stc12le2052ad独有的,这是所有准双向的共有特性,包括但不限于51.
回复

使用道具 举报

ID:517951 发表于 2021-9-4 09:22 | 显示全部楼层
IO口带上LED灯,还要检测按键,这种操作怎么搞?按键拉低的时候,led灯就亮不了啦
回复

使用道具 举报

ID:887371 发表于 2021-9-4 09:33 | 显示全部楼层
rayin 发表于 2021-9-4 09:22
IO口带上LED灯,还要检测按键,这种操作怎么搞?按键拉低的时候,led灯就亮不了啦

图上按键串联了电阻,按键拉低的时候,不会影响led。
回复

使用道具 举报

ID:491577 发表于 2021-9-6 11:45 | 显示全部楼层
本帖最后由 hhh402 于 2021-9-6 11:54 编辑

楼主的电路有问题,10K电阻是来捣蛋的要去掉,接按键的电阻1K改为2.2k,想点亮LED就推挽输出高电平,想检测按键时设置成双向模式,读到0就是有按键按下。按键按下不会影响到LED.
回复

使用道具 举报

ID:777834 发表于 2021-9-14 20:00 | 显示全部楼层
#include <reg52.h>
#include<intrins.h>

sfr P1M0  = 0x91;
sfr P1M1  = 0x92;

sbit LED1 = P1^4;        //LED端口声明
sbit LED2 = P1^5;
sbit LED3 = P1^6;
sbit LED4 = P1^7;

unsigned char KeySec=0;//键值变量

/**********************************
  1ms延时程序
**********************************/
void Delay1ms()                //@12.000MHz
{
        unsigned char i, j;

        _nop_();
        _nop_();
        i = 12;
        j = 168;
        do
        {
                while (--j);
        } while (--i);
}
/**********************************
        按键扫描程序
**********************************/
void key_scan()
{
        static unsigned char count=0;//静态计数变量
        static bit sign_key=0;                        //静态标志位
        unsigned char time_key,time_LED;//临时变量

        time_LED=P1&0xf0;//保存4个LED状态
        P1M0=0xf0;//P1.4~7设置弱上拉
        P1M1=0x00;//P1.4~7设置弱上拉
        P1|=0xf0; //P1.4~7置高电平        
        if(P1&0xf0!=0xf0)//有键按下
        {
                if(++count>=10 && sign_key==0)//消抖
                {
                        sign_key=1;//自锁
                        time_key=P1&0xf0;//保存P1.4~7状态
                        switch(time_key)
                        {
                                case 0xe0: KeySec=1; break;//输出键值
                                case 0xd0: KeySec=2; break;
                                case 0xb0: KeySec=3; break;
                                case 0x70: KeySec=4; break;
                        }
                }
        }
        else //抬起
        {
                count=0;//计数变量清0
                sign_key=0;//键态标志清0
        }
        P1&=0x0f;    //P1.4~7清0
        P1|=time_LED;//还原4个LED状态
        P1M0=0x00;   //还原P1.4~7推挽设置
        P1M1=0xf0;   //还原P1.4~7推挽设置
}
/*********************************
        按键服务程序
*********************************/
void key_service()
{
        switch(KeySec)
        {
                case 1:        LED1=~LED1;KeySec=0;break;
                case 2:        LED2=~LED2;KeySec=0;break;
                case 3:        LED3=~LED3;KeySec=0;break;
                case 4:        LED4=~LED4;KeySec=0;break;
        }                  
}
/********************************
        主程序
********************************/
void main()
{
        P1M0=0xf0;//P1.4~7设置推挽
        P1M1=0x00;//P1.4~7设置推挽
        while(1)
        {
                key_scan();
                key_service();
                Delay1ms();//控制主循环周期约1ms
        }
}

大佬们,帮看下哪里的问题,我反复调试好久都不行,谢谢啦
回复

使用道具 举报

ID:887371 发表于 2021-9-20 15:11 | 显示全部楼层

假如推挽和弱上拉设置没错的画,io口驱动发光二极管并扫描按键这部分代码没有问题。
键值处理分析这部分有问题,你需要一个全局变量保存之前的键值。
我根据你的代码修改了一下。
  1. #include <reg52.h>
  2. #include <intrins.h>

  3. sfr P1M0 = 0x91;
  4. sfr P1M1 = 0x92;

  5. sbit LED1 = P1 ^ 4; //LED端口声明
  6. sbit LED2 = P1 ^ 5;
  7. sbit LED3 = P1 ^ 6;
  8. sbit LED4 = P1 ^ 7;
  9. //unsigned char KeySec=0;//键值变量
  10. /**********************************
  11.   1ms延时程序
  12. **********************************/
  13. void Delay1ms() //@12.000MHz
  14. {
  15.         unsigned char i, j;
  16.         _nop_();
  17.         _nop_();
  18.         i = 12;
  19.         j = 168;
  20.         do
  21.         {
  22.                 while (--j);
  23.         } while (--i);
  24. }

  25. /*********************************
  26.         按键值读取程序
  27. *********************************/
  28. unsigned char KeyGet(void)
  29. {
  30.         unsigned char r;
  31.         unsigned char time_LED;

  32.         //EA=0;//如能保证中断不会在此期间操作P1.4~7,可注释
  33.         time_LED = P1 & 0xf0; //保存4个LED状态
  34.         P1M0 = 0xf0;                  //P1.4~7设置弱上拉
  35.         P1M1 = 0x00;                  //P1.4~7设置弱上拉
  36.         P1 |= 0xf0;                          //P1.4~7置高电平

  37.         _nop_();_nop_();_nop_();_nop_();_nop_();           //延时等待按键稳定
  38.         r = P1 & 0xf0; //读键值

  39.         P1 &= 0x0f;                //P1.4~7清0
  40.         P1 |= time_LED; //还原4个LED状态
  41.         P1M0 = 0x00;        //还原P1.4~7推挽设置
  42.         P1M1 = 0xf0;        //还原P1.4~7推挽设置
  43.         //EA=1;
  44.         return r;
  45. }
  46. /*********************************
  47.         按键服务程序
  48. *********************************/
  49. void key_service(unsigned char KeySec)
  50. {
  51.         if((KeySec&(1<<4))==0) LED1 = ~LED1;
  52.         if((KeySec&(1<<5))==0) LED2 = ~LED2;
  53.         if((KeySec&(1<<6))==0) LED3 = ~LED3;
  54.         if((KeySec&(1<<7))==0) LED4 = ~LED4;
  55. }
  56. /**********************************
  57.         按键扫描程序
  58. **********************************/
  59. void key_scan()
  60. {
  61.         static unsigned char keyOld = 0xf0; //上一次按键值
  62.         static unsigned char count = 0;                //静态计数变量
  63.         unsigned char KeyCur;                                //当前按键值 临时变量

  64.         KeyCur = KeyGet();
  65.         if (keyOld == KeyCur)
  66.         { //按键未变化
  67.                 if (++count == 0)
  68.                         --count;
  69.                 if (KeyCur != 0xf0)
  70.                 { //有键按下
  71.                         if (count == 10)
  72.                         { //消抖
  73.                                 key_service(KeyCur);
  74.                         }
  75.                 }
  76.         }
  77.         else
  78.         {
  79.                 count = 0; //计数变量清0
  80.                 keyOld = KeyCur;
  81.         }
  82. }


  83. /********************************
  84.         主程序
  85. ********************************/
  86. void main()
  87. {
  88.         // P1M0 = 0xf0; //P1.4~7设置推挽
  89.         // P1M1 = 0x00; //P1.4~7设置推挽
  90.         KeyGet();         //P1.4~7设置推挽
  91.         while (1)
  92.         {
  93.                 key_scan();
  94.                 //key_service();
  95.                 Delay1ms(); //控制主循环周期约1ms
  96.         }
  97. }
复制代码



回复

使用道具 举报

ID:887371 发表于 2021-9-20 15:27 | 显示全部楼层

刚查了下手册,你配置弱上拉除了错。
读键值代码如下:
  1. /*********************************
  2.         按键值读取程序
  3. *********************************/
  4. unsigned char KeyGet(void)
  5. {
  6.         unsigned char r;
  7.         unsigned char time_LED;

  8.         //EA=0;//如能保证中断不会在此期间操作P1.4~7,可注释
  9.         time_LED = P1 & 0xf0; //保存4个LED状态
  10.         //P1M0 = 0xf0;                  //P1.4~7设置弱上拉
  11.         P1M1 = 0x00;                  //P1.4~7设置弱上拉
  12.         P1 |= 0xf0;                          //P1.4~7置高电平

  13.         _nop_();_nop_();_nop_();_nop_();_nop_();           //延时等待按键稳定
  14.         r = P1 & 0xf0; //读键值

  15.         P1 &= 0x0f;                //P1.4~7清0
  16.         P1 |= time_LED; //还原4个LED状态
  17.         P1M0 = 0x00;        //还原P1.4~7推挽设置
  18.         P1M1 = 0xf0;        //还原P1.4~7推挽设置
  19.         //EA=1;
  20.         return r;
  21. }
复制代码
回复

使用道具 举报

ID:777834 发表于 2021-9-24 00:23 来自手机 | 显示全部楼层
datouyuan 发表于 2021-9-20 15:27
刚查了下手册,你配置弱上拉除了错。
读键值代码如下:

以上程序都跑过了,也调试了好久,就是关闭LED时灯还有微亮,
回复

使用道具 举报

ID:887371 发表于 2021-9-24 09:05 | 显示全部楼层
jianuli 发表于 2021-9-24 00:23
以上程序都跑过了,也调试了好久,就是关闭LED时灯还有微亮,

请看我2楼的分析。
回复

使用道具 举报

ID:777834 发表于 2021-9-24 09:31 来自手机 | 显示全部楼层
datouyuan 发表于 2021-9-24 09:05
请看我2楼的分析。

实际10K电阻我没接,接与不接结果都一样,还有不可能像你说的要把电压调低才能用吧,像充电宝之类的很多产品都用这种电路,它们关闭后都没有微亮,
回复

使用道具 举报

ID:887371 发表于 2021-9-24 11:09 | 显示全部楼层
jianuli 发表于 2021-9-24 09:31
实际10K电阻我没接,接与不接结果都一样,还有不可能像你说的要把电压调低才能用吧,像充电宝之类的很多 ...

我的分析是没有错的,10K不接的话,需要更低些的电压才能正常。
充电宝电路和这电路肯定不一样,我做过4个IO同时驱动6个灯6个按键。
回复

使用道具 举报

ID:161164 发表于 2021-9-28 02:11 | 显示全部楼层
jianuli 发表于 2021-9-24 00:23
以上程序都跑过了,也调试了好久,就是关闭LED时灯还有微亮,

是有微亮
经过一整晚的研究
终于发现微亮的成因和解决方法
已经夜深,明天再说

答案提示:PWM
回复

使用道具 举报

ID:777834 发表于 2021-9-28 08:33 来自手机 | 显示全部楼层
lkc8210 发表于 2021-9-28 02:11
是有微亮
经过一整晚的研究
终于发现微亮的成因和解决方法

是吧,我实际搭电路验证的,确实关闭后有微亮,但就是有人不信,我也觉得有解决方法,但是本人还是菜鸟一个,没法解决
回复

使用道具 举报

ID:1064915 发表于 2023-6-28 15:55 | 显示全部楼层
STC89C52RC可以试验吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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