找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5218|回复: 37
收起左侧

4个单片机IO,LED灯,按键共用,STC怎么编程?

  [复制链接]
ID:341833 发表于 2020-8-14 23:44 | 显示全部楼层 |阅读模式
4个IO,LED灯,按键共用,STC怎么编程
回复

使用道具 举报

ID:748096 发表于 2020-8-15 05:44 | 显示全部楼层
建议LED灯PWM模式,调整占空比,在IO口高电平时检测按键是否按下,如果按下等待按键处理程序,LED灯暂时就不要管了。
回复

使用道具 举报

ID:332444 发表于 2020-8-15 06:45 | 显示全部楼层
IO口复用必须借助其它芯片先行解放IO才能谈及复用的可能,还需要有控制其它芯片的IO。
回复

使用道具 举报

ID:213173 发表于 2020-8-15 07:36 | 显示全部楼层
LED灯、按键共用4个单片机IO示例
无标题.jpg

#include <reg52.h>

sfr P1M0 = 0x92;  //0000,0000 端口1模式寄存器0
sfr P1M1 = 0x91;  //0000,0000 端口1模式寄存器1

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

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

/**********************************
  1ms延时程序(仅限于STC15W 1T MCU)
**********************************/
void Delay1ms()                //@12.000MHz
{
        unsigned char i, j;
        i = 12;
        j = 169;
        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=0x00;//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=0xf0;   //还原P1.4~7推挽设置
        P1M1=0x00;   //还原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:716656 发表于 2020-8-15 08:36 | 显示全部楼层
wulin 发表于 2020-8-15 07:36
LED灯、按键共用4个单片机IO示例

学习了
回复

使用道具 举报

ID:259648 发表于 2020-8-15 23:18 | 显示全部楼层
wulin 发表于 2020-8-15 07:36
LED灯、按键共用4个单片机IO示例

  又涨姿势了  很实用
回复

使用道具 举报

ID:777834 发表于 2021-8-31 15:35 来自手机 | 显示全部楼层
wulin 发表于 2020-8-15 07:36
LED灯、按键共用4个单片机IO示例



你好,我按你上面的程序在stc12c2052ad上不能工作,不知道是那里的原因,P1M0、P1M1有修改,LED1在P1.5、LED2在P1.4,其它一样
回复

使用道具 举报

ID:777834 发表于 2021-8-31 15:42 来自手机 | 显示全部楼层
wulin 发表于 2020-8-15 07:36
LED灯、按键共用4个单片机IO示例



程序如下
IMG_20210831_153850.jpg
IMG_20210831_153905.jpg
回复

使用道具 举报

ID:161164 发表于 2021-8-31 16:29 | 显示全部楼层
本帖最后由 lkc8210 于 2021-8-31 16:33 编辑

例子用的是STC15
2021-08-31_162223.png


你用的是STC12
2021-08-31_162210.png


有试过跟STC15一样设置吗?
P1M0=0xF0;
P1M1=0x00;
回复

使用道具 举报

ID:963053 发表于 2021-8-31 17:01 来自手机 | 显示全部楼层
………………
CSDN_1630400410697.jpg
回复

使用道具 举报

ID:777834 发表于 2021-8-31 17:31 来自手机 | 显示全部楼层
lkc8210 发表于 2021-8-31 16:29
例子用的是STC15



那我灯在P1口啊,
回复

使用道具 举报

ID:624769 发表于 2021-8-31 17:56 | 显示全部楼层
你是几个LED,几个按键?一般一个IO复用LED和按键,不是很推荐,如果LED是周期点亮,比如数码管的公共级,通常是一个IO复用多个按键,接到不同数码管的公共级,通过数码管的周期点亮,区别不同按键的状态,这样的效果比较好,比反复切换IO状态要好。
回复

使用道具 举报

ID:777834 发表于 2021-8-31 20:41 来自手机 | 显示全部楼层
188610329 发表于 2021-8-31 17:56
你是几个LED,几个按键?一般一个IO复用LED和按键,不是很推荐,如果LED是周期点亮,比如数码管的公共级,通 ...

2个灯,2个按键,电路跟手册上的一样
回复

使用道具 举报

ID:777834 发表于 2021-8-31 22:19 来自手机 | 显示全部楼层
没人说下了吗
回复

使用道具 举报

ID:777834 发表于 2021-9-8 11:24 来自手机 | 显示全部楼层
温存723 发表于 2020-8-15 23:18
又涨姿势了  很实用

我反复调试都不行,说说你的想法或程序,谢谢啦
回复

使用道具 举报

ID:777834 发表于 2021-9-14 16:59 来自手机 | 显示全部楼层
wulin 发表于 2020-8-15 07:36
LED灯、按键共用4个单片机IO示例



大佬,帮忙分析下,我反复调试都不行,谢谢啦
回复

使用道具 举报

ID:777834 发表于 2021-9-14 19:20 来自手机 | 显示全部楼层
wulin 发表于 2020-8-15 07:36
LED灯、按键共用4个单片机IO示例



大佬,帮我分析下,我反复调试好久了都不行,谢谢啦
回复

使用道具 举报

ID:777834 发表于 2021-9-14 21:09 | 显示全部楼层
电路图
捕获.PNG
回复

使用道具 举报

ID:777834 发表于 2021-9-14 21:33 来自手机 | 显示全部楼层
wulin 发表于 2020-8-15 07:36
LED灯、按键共用4个单片机IO示例



原理图
U
回复

使用道具 举报

ID:155507 发表于 2021-9-14 22:03 | 显示全部楼层
你把你的代码完整地贴上来看看
(不要截图!不要截图!不要截图!)

语焉不详、去头掐尾也是爱莫能助的了。。。

回复

使用道具 举报

ID:777834 发表于 2021-9-14 22:49 来自手机 | 显示全部楼层
angmall 发表于 2021-9-14 22:03
你把你的代码完整地贴上来看看
(不要截图!不要截图!不要截图!)


代码我贴了呀,怎么显示,我再重新贴上,不好意思
回复

使用道具 举报

ID:777834 发表于 2021-9-14 22:54 来自手机 | 显示全部楼层
#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:777834 发表于 2021-9-15 12:39 来自手机 | 显示全部楼层
angmall 发表于 2021-9-14 22:03
你把你的代码完整地贴上来看看
(不要截图!不要截图!不要截图!)


大佬,代码己贴上
回复

使用道具 举报

ID:130230 发表于 2021-9-17 09:06 | 显示全部楼层
可以用状态机做,在较短的时间间隔里面切换状态,一个状态用来检测按键,一个状态用来点亮led。
回复

使用道具 举报

ID:777834 发表于 2021-9-17 09:31 来自手机 | 显示全部楼层
jizhongbiao 发表于 2021-9-17 09:06
可以用状态机做,在较短的时间间隔里面切换状态,一个状态用来检测按键,一个状态用来点亮led。

来个例程
回复

使用道具 举报

ID:959346 发表于 2021-9-17 10:10 | 显示全部楼层

    while(1)
        {
                vLedOff(); // 关闭LED,将IO口设置成输入模式
                Delay1ms();//控制主循环周期约1ms,等待IO稳定后检测按键
                key_scan(); // 按键检测,不用处理LED
                key_service();
                vLedDisplay(); // 检测完按键后点亮LED
                Delay1ms();//控制主循环周期约1ms,LED点亮周期。
        }
// 另,你LED数据最好用一个变量来保存,不要通过读IO口状态备份,容易产生问题。
回复

使用道具 举报

ID:161164 发表于 2021-9-17 17:39 | 显示全部楼层

ezgif.com-gif-maker.gif

用了地板的电路(就是10k+1k+1k那个)
再加上你的代码
只改了其中一句
if((P1&0xf0)!=0xf0)//有键按下//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
加了括号,不加的话会有警告:warning C294: unreachable code


回复

使用道具 举报

ID:777834 发表于 2021-9-17 21:11 来自手机 | 显示全部楼层
lkc8210 发表于 2021-9-17 17:39
用了地板的电路(就是10k+1k+1k那个)
再加上你的代码
只改了其中一句

大佬,昨天还是前天我也验证可以了,就是按键按下的那个判断语句少了括号,加上了就可以了,但是这个电路还有不足的地方,上电瞬间会亮一下,就算加下拉电阻可以消除,但对按键也有影响,只能折中吧,还有关了LED还会微亮,你实测中有没有发现
回复

使用道具 举报

ID:624769 发表于 2021-9-17 22:00 | 显示全部楼层

你电路设计不合理啊……

在按键设计中,一般都是避免和 强推挽共用的…… 按你的电路设计,其实你可以设计成 两个LED一头并联,连接到 P1.4, 另外一头分别接到 数码管的 A,B, 把数码管的本来 3 分频改成 4分频,就是把这两个 LED 拓展成数码管的第4个”数字“ 这样你最多可以接 8 个LED.
然后,把 按键一头并联,接到P1.5, 另一头接数码管的 8.9.12 中的任意两个, 在数码管的轮流点亮过程中 点亮哪个位的时候,P1.5 电平变了,就说明哪个按键被按下了,这样,你最多可以有 3个 + 刚才说的LED 新增加的 P1.4 的那个公共端,总共 4个按键,这样设计电路不是更合理可靠,还不用不停 切换IO状态么?
回复

使用道具 举报

ID:777834 发表于 2021-9-17 22:10 来自手机 | 显示全部楼层
188610329 发表于 2021-9-17 22:00
你电路设计不合理啊……

在按键设计中,一般都是避免和 强推挽共用的…… 按你的电路设计,其实你可以 ...

谢谢讲解,其实我是看到手册上有这样接法,也看到别人有这样用,所以也想学习下
回复

使用道具 举报

ID:777834 发表于 2021-9-17 23:45 来自手机 | 显示全部楼层
188610329 发表于 2021-9-17 22:00
你电路设计不合理啊……

在按键设计中,一般都是避免和 强推挽共用的…… 按你的电路设计,其实你可以 ...

比如有时仅剩一个IO口时,要做指示跟按键用,也可以这样用吧
回复

使用道具 举报

ID:624769 发表于 2021-9-18 00:29 | 显示全部楼层
jianuli 发表于 2021-9-17 23:45
比如有时仅剩一个IO口时,要做指示跟按键用,也可以这样用吧

如果仅仅剩一个IO, 而你的单片机,又没有别的按键,也没有别的LED,或者数码管连接,也没有其他长期周期性工作的元件的时候,又偏偏需要 一个按键,和一个LED的时候,作为下下策,可以这样接,但是,站在共用IO的角度来讲,LED和按键通过切换IO模式来,共用IO是最不推荐的共用方法, 而大多数时候,你的整个电路中,应该能找到,其他的IO口和LED或按键共用的IO的。LED和按键的共用,应该作为实在没办法的时候的最后办法。比如你单片机作为主机,SPI的 始能 引脚 只有单片机去拉低从机的 没有从机拉低主机的,你也可以接按键,只要被拉低了,就是按键被按下了。而即便这个时候,SPI在传输也没有所谓,因为始能引脚正在被拉低,完全不影响正在发生的传输。 等等,各种共用方法很多很多。
回复

使用道具 举报

ID:161164 发表于 2021-9-20 14:22 | 显示全部楼层
jianuli 发表于 2021-9-17 21:11
大佬,昨天还是前天我也验证可以了,就是按键按下的那个判断语句少了括号,加上了就可以了,但是这个电路 ...

有没有微亮没留意
试完就把电路拆了
回看我上传的gif
好像没有耶~
回复

使用道具 举报

ID:777834 发表于 2021-9-24 09:35 来自手机 | 显示全部楼层
lkc8210 发表于 2021-9-20 14:22
有没有微亮没留意
试完就把电路拆了
回看我上传的gif

有微亮
回复

使用道具 举报

ID:596446 发表于 2022-8-23 11:00 | 显示全部楼层

如果共用使用的端口有P1.1,P21,P32,P41呢?怎么写?
回复

使用道具 举报

ID:596446 发表于 2022-9-22 20:35 | 显示全部楼层
怎么做成呼吸灯?
回复

使用道具 举报

ID:735692 发表于 2023-3-31 07:08 来自手机 | 显示全部楼层
wulin 发表于 2020-8-15 07:36
LED灯、按键共用4个单片机IO示例



我要说一下此电路配合此程序是错误的,事实上此电路,在弱上拉下无法将接有正向的导通的LED端口拉向高电平,程序和电路都需要修改才能正常工作
回复

使用道具 举报

ID:161164 发表于 2023-3-31 10:26 | 显示全部楼层
jackyangjiali 发表于 2023-3-31 07:08
我要说一下此电路配合此程序是错误的,事实上此电路,在弱上拉下无法将接有正向的导通的LED端口拉向高电 ...

但我没改电路也成功也~
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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