找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 780|回复: 7
收起左侧

一个单片机i/o口驱动发光二极管并扫描按键

[复制链接]
ID:47445 发表于 2024-4-16 19:40 | 显示全部楼层 |阅读模式
小弟学习51单片机,根据网上资料试验了用STC15W204S做 一个i/o口驱动发光二极管并扫描按键的电路,程序烧入后按键没反应,请各位大侠不吝赐教程序有何问题,谢谢。

无标题ss.png


#include <STC15.H>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

sbit LED1 = P1^0;        //LED端口声明
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;

uchar 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 uchar count=0;//静态计数变量
        static bit sign_key=0;                        //静态标志位
       uchar time_key,time_LED;//临时变量

    //    P1M0=0x00;//P1.0~3设置弱上拉
     //   P1M1=0x00;//P1.0~3设置弱上拉

        time_LED=P1&0x0f;//保存4个LED状态

        P1M0=0x00;//P1.0~3设置弱上拉
        P1M1=0x00;//P1.0~3设置弱上拉
        P1|=0x0f; //P1.0~3置高电平      
        if(P1&0x0f!=0x0f)//有键按下
        {
                if(++count>=10 && sign_key==0)//消抖
                {
                        sign_key=1;//自锁
                        time_key=P1&0x0f;//保存P1.0~3状态
                        switch(time_key)
                        {
                                case 0x0e: KeySec=1; break;//输出键值
                                case 0x0d: KeySec=2; break;
                                case 0x0b: KeySec=3; break;
                                case 0x07: KeySec=4; break;
                        }
                }
        }
        else //抬起
        {
                count=0;//计数变量清0
                sign_key=0;//键态标志清0
        }
        P1&=0xf0;    //P1.0~3清0
        P1|=time_LED;//还原4个LED状态
        P1M0=0x0f;   //还原P1.0~3推挽设置
        P1M1=0x00;   //还原P1.0~3推挽设置
}
/*********************************
        按键服务程序
*********************************/
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=0x0f;//P1.0~3设置推挽
        P1M1=0x00;//P1.0~0设置推挽

                LED1=0;
                LED2=0;
                LED3=0;
                LED4=0;
        while(1)
        {
                key_scan();
                key_service();
                Delay1ms();//控制主循环周期约1ms
        }
}




回复

使用道具 举报

ID:1109793 发表于 2024-4-16 21:00 | 显示全部楼层
按键是输入,LED是输出,怎样用一个脚完成?原理说说呗。按键按下去时灯会灭还是不会?LED完全熄灭时还能读按键吗?
回复

使用道具 举报

ID:47445 发表于 2024-4-16 21:28 | 显示全部楼层
xiaobendan001 发表于 2024-4-16 21:00
按键是输入,LED是输出,怎样用一个脚完成?原理说说呗。按键按下去时灯会灭还是不会?LED完全熄灭时还能读 ...

ddfghj.png STC15 PDF资料有这种电路
回复

使用道具 举报

ID:1109793 发表于 2024-4-17 08:41 | 显示全部楼层
jl48q 发表于 2024-4-16 21:28
STC15 PDF资料有这种电路

即使弱上拉,也有电流会流过LED,一样会亮,虽然比较弱。况且电路中还有一个10K的上拉电阻。即使你的弱上拉时间非常短,也有亮度的。而且要保证LED的限流电阻在弱上拉时能够为IO扣提供至少电源电压一半以上的电压。我是觉得研究这个没啥用。要扩展不如直接使用比如1638这样的芯片更有效。这STC的人也是脑洞比较大
回复

使用道具 举报

ID:879348 发表于 2024-4-17 09:23 | 显示全部楼层
分时复用,在极短时间内,把输出口变为输入,读取后马上变为输出,因为这个时间是us级别,LED失控亮起时间极短,亮度几乎没有

评分

参与人数 1黑币 +5 收起 理由
橙子不洒脱 + 5 说的很对!跟我想的一样

查看全部评分

回复

使用道具 举报

ID:1110945 发表于 2024-4-17 10:00 | 显示全部楼层
如果我做这样的电路,不会画成这个样子。
Vcc接限流电阻接发光管接按键到地(串起来),IO口接按键就好了。
设置成准双向口模式弱上拉。
如果用adc功能读按键,则一个IO口可以挂10个甚至30个按键。
回复

使用道具 举报

ID:1109793 发表于 2024-4-17 10:57 | 显示全部楼层
wufa1986 发表于 2024-4-17 09:23
分时复用,在极短时间内,把输出口变为输入,读取后马上变为输出,因为这个时间是us级别,LED失控亮起时间 ...

是不是可以尝试在LED上并一个电容,这样就完全没有亮度了,有空试试效果咋样
回复

使用道具 举报

ID:47445 发表于 2024-4-18 11:32 | 显示全部楼层
程序修改了2天,弄好了
bae0e19c4568bf74cebc36b1e39ed1a.jpg

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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