数码之家

标题: 让按键按下输出一个脉冲松开输出一个脉冲 [打印本页]

作者: gongyu    时间: 2021-1-5 09:39
标题: 让按键按下输出一个脉冲松开输出一个脉冲
本帖最后由 gongyu 于 2021-1-5 09:42 编辑

请教一下各位大神,如何用单片机编写一个程序,用四个按键控制四个灯。功能是:按键一按下灯一闪一下,松开闪一下;按键二按下灯二闪一下,松开也闪一下;每一路都是如此。也可以四路同时按下或者松开。
简单的说就是四路自锁开关的功能反过来。
对单片机只了解一点,还没入门不会使用中断
逻辑图如下:

作者: ww5223017240    时间: 2021-1-5 10:06
按下和松开之间有间隔?那估计用轮询好点吧?
作者: gongyu    时间: 2021-1-5 10:14
ww5223017240 发表于 2021-1-5 10:06
按下和松开之间有间隔?那估计用轮询好点吧?

按下跟松开时间不是固定的,用轮询也可以,无奈不会写啊
作者: msold5    时间: 2021-1-5 10:26
学Linkboy吧,半小时就编好这个程序了
作者: 高级会员    时间: 2021-1-5 10:32
提示: 作者被禁止或删除 内容自动屏蔽
作者: 72hour    时间: 2021-1-5 10:48
去抖 松手检测,单片机基础教程就有
作者: ww5223017240    时间: 2021-1-5 12:02
高级会员 发表于 2021-1-5 10:32
如果不按就这么放着是输出什么波形?

不按哪来的波形?IO口没动作就不会有波形啊
作者: ww5223017240    时间: 2021-1-5 12:05
gongyu 发表于 2021-1-5 10:14
按下跟松开时间不是固定的,用轮询也可以,无奈不会写啊

矩阵按键的编程看一下简单的,傻了,中断也可以的
作者: gongyu    时间: 2021-1-5 12:06
ww5223017240 发表于 2021-1-5 12:05
矩阵按键的编程看一下简单的,傻了,中断也可以的

是的
作者: gongyu    时间: 2021-1-5 12:07
高级会员 发表于 2021-1-5 10:32
如果不按就这么放着是输出什么波形?

按着不动输出低电平
作者: 夜游虾    时间: 2021-1-5 13:22
新手就用arduino搞定,最小板10块钱左右
作者: 高级会员    时间: 2021-1-5 13:34
提示: 作者被禁止或删除 内容自动屏蔽
作者: ks11900    时间: 2021-1-5 14:05
边沿检测,检测到一次跳变就软件控制led亮灭一次。。。问题是你两次按键多长时间内算连击?
作者: gongyu    时间: 2021-1-5 14:38
ks11900 发表于 2021-1-5 14:05
边沿检测,检测到一次跳变就软件控制led亮灭一次。。。问题是你两次按键多长时间内算连击? ...

1秒内算连击
作者: gongyu    时间: 2021-1-5 14:46
高级会员 发表于 2021-1-5 13:34
楼主要求是松开也要闪,松开不就是不按么?不按的话是一直闪还是一条直线?还是不动作? ...

是状态跳变的瞬间闪  比如说上升沿和下降沿跳变1-0  0-1的时候输出脉冲   不按或者一直按着不动是没有跳变的,所以没有输出
作者: njchg567    时间: 2021-1-5 14:56
高级会员 发表于 2021-1-5 13:34
楼主要求是松开也要闪,松开不就是不按么?不按的话是一直闪还是一条直线?还是不动作? ...

按下是下降沿触发,松开是上升沿触发。
作者: njchg567    时间: 2021-1-5 15:00
njchg567 发表于 2021-1-5 14:56
按下是下降沿触发,松开是上升沿触发。

松开是一个动作,有脉冲变化,不按是没有动作,没有脉冲变化。
作者: njchg567    时间: 2021-1-5 15:01
njchg567 发表于 2021-1-5 15:00
松开是一个动作,有脉冲变化,不按是没有动作,没有脉冲变化。

我觉得用简单的触发电路就可以方便的实现。
作者: gongyu    时间: 2021-1-5 15:31
njchg567 发表于 2021-1-5 15:01
我觉得用简单的触发电路就可以方便的实现。

有类似的电路吗   用硬件做也行
作者: njchg567    时间: 2021-1-5 16:11
本帖最后由 njchg567 于 2021-1-5 16:43 编辑
gongyu 发表于 2021-1-5 15:31
有类似的电路吗   用硬件做也行

两个单稳态触发器,一个上升沿有效,一个下降沿有效,输出接到一个或门。
或者简单点这样我觉得可以吧!


作者: njchg567    时间: 2021-1-5 16:46
也可以考虑用一个施密特触发器。
作者: njchg567    时间: 2021-1-5 16:50
也可以考虑用一个施密特触发器,或者上面的图的按钮也可以改成单路按钮。各有特点吧!
作者: gongyu    时间: 2021-1-5 17:24
njchg567 发表于 2021-1-5 16:11
两个单稳态触发器,一个上升沿有效,一个下降沿有效,输出接到一个或门。
或者简单点这样我觉得可以吧!


谢谢  用这个做的话4路搞起来体积有点大
作者: ww5223017240    时间: 2021-1-5 18:15
高级会员 发表于 2021-1-5 13:34
楼主要求是松开也要闪,松开不就是不按么?不按的话是一直闪还是一条直线?还是不动作? ...

松开和不按怎么是一个概念?有跳变就有波形啊!
作者: ks11900    时间: 2021-1-5 20:07
看会中断吧,要不了多久,实际很简单
作者: 温力口    时间: 2021-1-5 21:01
本帖最后由 温力口 于 2021-1-5 21:40 编辑

这东东,晚上试试看看。
作者: nnn2688    时间: 2021-1-5 22:19
感觉用硬件做更简单一些
作者: xixia001    时间: 2021-1-5 22:57
如果就1个按键,
if(S1==0)
{
     delay();  //去抖
    if(S1==0)   //确认
    {
        ...... //闪灯程序
        while(S1==0);
        ...... //闪灯程序
    }
}
作者: 温力口    时间: 2021-1-6 09:30
利用晚上时间折腾了一个小时,你看看适合用吗?

#include <REG52.h>
#define uchar unsigned char
#define uint unsigned int
sbit AA=P1^0;  //AA,BB,CC,DD为四灯的控制开关。
sbit BB=P1^1;  //低电平有效。
sbit CC=P1^2;
sbit DD=P1^3;

sbit aa=P1^4;  //aa,bb,cc,dd为四灯输出的控制I/O口。
sbit bb=P1^5;  //低电平灯亮。
sbit cc=P1^6;
sbit dd=P1^7;

bit flag_A;  //按键按下标志位
bit flag_B;
bit flag_C;
bit flag_D;


bit last_A;  //上次按键状态位
bit last_B;
bit last_C;
bit last_D;


bit current_A;  //当前按键状态位
bit current_B;
bit current_C;
bit current_D;

uint temp_A;    //延时时间变量
uint temp_B;
uint temp_C;
uint temp_D;

void Delay10ms()                //@12.000MHz
{
        unsigned char i, j;

        i = 20;
        j = 113;
        do
        {
                while (--j);
        } while (--i);
}

void Timer0Init(void)                //50000微秒@12.000MHz
{
        TMOD |= 0x01;                //设置定时器模式
        TL0 = 0xB0;                //设置定时初值
        TH0 = 0x3C;                //设置定时初值
        TR0 = 1;                //定时器0开始计时
        EA=1;
        ET0=1;
}


void time0(void) interrupt 1
{       
        TL0 = 0xB0;
        TH0 = 0x3C;
        if(flag_A)
                {
                        aa=0;
                        temp_A++;
                        if(temp_A==10)
                                {
                                        aa=1;
                                        temp_A=0;
                                        flag_A=0;
                                }                       
                }
               
        if(flag_B)
        {
                bb=0;
                temp_B++;
                if(temp_B==10)
                        {
                                bb=1;
                                temp_B=0;
                                flag_B=0;
                        }                       
        }

        if(flag_C)
        {
                cc=0;
                temp_C++;
                if(temp_C==10)
                        {
                                cc=1;
                                temp_C=0;
                                flag_C=0;
                        }                       
        }

        if(flag_D)
        {
                dd=0;
                temp_D++;
                if(temp_D==10)
                        {
                                dd=1;
                                temp_D=0;
                                flag_D=0;
                        }                       
        }       
}



void main(void)
{
        Timer0Init();
        while(1)
        {
                last_A=AA;
                last_B=BB;
                last_C=CC;
                last_D=DD;
                Delay10ms();
                current_A=AA;
                if(last_A!=current_A)
                        {
                                flag_A=1;                               
                        }                       

                current_B=BB;
                if(last_B!=current_B)
                        {
                                flag_B=1;                               
                        }
                       
                current_C=CC;
                if(last_C!=current_C)
                        {
                                flag_C=1;                               
                        }
                       
                current_D=DD;
                if(last_D!=current_D)
                        {
                                flag_D=1;                               
                        }                       
        }               
}





       
       


作者: firn    时间: 2021-1-6 14:52
http://www.51hei.com/bbs/dpj-150209-1.html
作者: 蕴殇    时间: 2021-1-6 16:09
本帖最后由 蕴殇 于 2021-1-6 16:11 编辑

不用单片机,使用双向LED,按键串联电容到LED,在电容和LED前面按键后面并联一个电阻就可以实现了,双向LED可以换成桥式整流加上普通LED。小灯泡也可以直接用,亮灯时间和电容容量成正比
作者: gongyu    时间: 2021-1-6 17:29
温力口 发表于 2021-1-6 09:30
利用晚上时间折腾了一个小时,你看看适合用吗?

#include

感谢温总   不管合不合适先谢谢  我试试
作者: gongyu    时间: 2021-1-6 17:31
firn 发表于 2021-1-6 14:52
http://www.51hei.com/bbs/dpj-150209-1.html

谢谢   学习一下
作者: gongyu    时间: 2021-1-6 17:32
xixia001 发表于 2021-1-5 22:57
如果就1个按键,
if(S1==0)
{

谢谢    单路简单4路不会了
作者: xixia001    时间: 2021-1-6 19:37
本帖最后由 xixia001 于 2021-1-6 20:10 编辑
gongyu 发表于 2021-1-6 17:32
谢谢    单路简单4路不会了

重新看了一下,要求4个按键能同时按,28楼做法就不合适了。
如果对灯闪的时间没什么要求,不用中断应该也可以实现。
以下几步不断循环就可以了
1,记录4个按键端口状态
2,将现在的端口状态跟上一次的端口状态比较,如果不一样就点亮对应的LED,否则关闭
3,将第一步记录的端口状态保存为上一次的端口状态
4,延时10到20毫秒


作者: szset99    时间: 2021-1-7 09:43
不停的查询IO口电平就行了  ,
作者: 红色电波    时间: 2021-1-7 10:10
用PLC可以实现吧:titter:
找个带常开常闭的按钮可以省去防抖,时间上的纠结,其他电路就简单了




欢迎光临 数码之家 (https://www.mydigit.cn/) Powered by Discuz! X3.4