找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7362|回复: 9
收起左侧

51单片机按键点灯 求各位大神该怎么编程

[复制链接]
ID:227569 发表于 2017-8-22 15:28 | 显示全部楼层 |阅读模式
用一个按钮,按一下点亮一个灯,依次点亮八个,按键快速切换的状态下不闪烁,切换后闪烁三次后常亮,最后要断电保持,各位大神该怎么编程
回复

使用道具 举报

ID:228806 发表于 2017-8-22 15:57 | 显示全部楼层
写一个按键的函数,把点灯的代码块放在函数里面,按键就用扫描按键方式,这样就可以实现了
回复

使用道具 举报

ID:190832 发表于 2017-8-22 16:24 | 显示全部楼层
设置两个8位无符号变量temp和count,初始值都为0。每次检测到按键按下count++,如果count==24,结束所有判断;否则判断temp是否等于0,如果temp==0,temp=1,否则temp=<<1;单片机P口=temp。
回复

使用道具 举报

ID:213173 发表于 2017-8-22 17:12 | 显示全部楼层
你描述的不明晰,按字面理解:初次上电灯都不亮,每按一次键点亮一个灯,连续按键灯不闪烁,中途停顿灯闪烁三次后常亮。这里指所有灯闪还是最后一个灯闪?按满8次继续按键是什么状态?最后要断电保持是指断电后再次得电要保持断电前状态?
回复

使用道具 举报

ID:227569 发表于 2017-8-22 19:27 | 显示全部楼层
wulin 发表于 2017-8-22 17:12
你描述的不明晰,按字面理解:初次上电灯都不亮,每按一次键点亮一个灯,连续按键灯不闪烁,中途停顿灯闪烁 ...

每按一次点一个灯,不连续的话就那个灯闪烁三次后常亮,安满八次之后回到第一个灯,断电保持是保持断电前的状态
回复

使用道具 举报

ID:227569 发表于 2017-8-22 19:28 | 显示全部楼层
master9527 发表于 2017-8-22 15:57
写一个按键的函数,把点灯的代码块放在函数里面,按键就用扫描按键方式,这样就可以实现了

我知道用数组,但是闪烁怎么办
回复

使用道具 举报

ID:190832 发表于 2017-8-23 08:47 | 显示全部楼层
hange_v 发表于 2017-8-22 16:24
设置两个8位无符号变量temp和count,初始值都为0。每次检测到按键按下count++,如果count==24,结束所有判 ...

锁存器
回复

使用道具 举报

ID:228922 发表于 2017-8-23 11:21 | 显示全部楼层
可以用轮询或者中断,轮询的话就是一直读开关的IO口,中断的话要稍微配置一下
回复

使用道具 举报

ID:213173 发表于 2017-8-25 13:16 | 显示全部楼层
wangboyue 发表于 2017-8-22 19:27
每按一次点一个灯,不连续的话就那个灯闪烁三次后常亮,安满八次之后回到第一个灯,断电保持是保持断电前 ...

给你写了个程序,你想要的功能都有。已经过TX-1C实验板验证通过。不合意处你自己更改。
/*************************************************************
程序功能:加电待机,按键启动,LED1~LED8依次点亮,按键间隔大于
0.5秒LED闪烁,最多闪烁三次后常亮,第9次按键进入待机。每次操作
状态数据保存在EEPROM,失电或关机后再次得电保持之前工作状态。
*************************************************************/
#include <AT89X52.H>                                //单片机头文件
#include <intrins.h>                                //库头文件
#define uint unsigned int                 //宏定义无符号整型数据(0-65535)
#define uchar unsigned char         //宏定义无符号字符型数据(0-255)
/****定义ISP的操作命令*****/
#define RdCommand 0x01                                //读命令
#define PrgCommand 0x02                                //写命令
#define EraseCommand 0x03                        //擦除命令
#define WaitTime 0x01                                 //定义CPU的等待时间,写入硬件延时
/*STC89系列EEPROM寄存器声明*/
sfr ISP_DATA=0xe2;                                        //0000,0000 EEPROM数据寄存器
sfr ISP_ADDRH=0xe3;                                        //0000,0000 EEPROM地址高字节
sfr ISP_ADDRL=0xe4;                                        //0000,0000 EEPROM地址第字节
sfr ISP_CMD=0xe5;                                        //xxxx,xx00 EEPROM命令寄存器
sfr ISP_TRIG=0xe6;                                        //0000,0000 EEPRPM命令触发寄存器
sfr ISP_CONTR=0xe7;                                        //0000,x000 EEPROM控制寄存器
/********端口定义************/
sbit LED1=P1^0;                                        //发光管端口定义
sbit LED2=P1^1;
sbit LED3=P1^2;
sbit LED4=P1^3;
sbit LED5=P1^4;
sbit LED6=P1^5;
sbit LED7=P1^6;
sbit LED8=P1^7;
sbit key=P3^6;                                        //按键端口定义       
/********变量及函数声明************/
uchar num=0;                                        //键值
uchar count1=0,count2=0;        //中断计数
bit Twinkle=0;                                        //闪烁标志

void keyscan();                                        //按键扫描程序
void display();                                        //显示程序
void Timer0Init();                                //初始化定时器
void ISP_IAP_enable();                                //打开 ISP,IAP 功能
void ISP_IAP_disable();                                //关闭 ISP,IAP 功能
void ISPgoon();                                                //公用的触发代码
uchar byte_read(uint byte_addr);        //字节读
void SectorErase(uint sector_addr);        //扇区擦除
void byte_write(uint byte_addr, uchar original_data);        //字节写

/********主函数************/
void main()       
{
        Timer0Init();                                        //定时器初始化
        num=byte_read(0x2000);                //程序开始时读取EEPROM中数据
        if(num>=9)                                                //如果num>=9
        {
                num=0;                                                //num=0
        }
        while(1)       
        {
                keyscan();                                //按键识别子程序
                display();                                //显示子程序
        }
}
/**********按键扫描程序*********/
void keyscan()
{
        static bit key_sign=0;                //按键有效标志
        static uchar count=0;                //计数变量                       
        if(key==0)                                        //检测按键如果为0
        {
                count++;                                //消抖计数
                if(count>=100)                        //100次检测按键如果为0
                {                       
                        count=100;                        //最大数限制
                        if(key_sign==0)                //按键有效标志为0
                        {
                                key_sign=1;                //按键有效标志置1
                                num++;                        //
                                if(num>=9)
                                        num=0;
                                SectorErase(0x2000);//擦除EEPROM扇区中的数据
                                byte_write(0x2000,num); //重新写入数据
                                count1=0;                                        //中断计数1清0
                                count2=0;                                        //中断计数2清0
                                Twinkle=0;                                        //闪烁标志清0
                        }
                }
        }
        else
        {
                if(key_sign==1)
                {
                        if(num>0)
                                TR0 = 1;                                        //开定时器
                        else
                                TR0 = 0;                                        //关定时器
                        key_sign=0;                                //按键有效标志清0
                }
                count=0;                                                //消抖计数清0
        }
}
/**********显示程序*********/
void display()       
{
        switch(num)                                        //多重分支
        {
                case 0: P1=0XFF;
                break;

                case 1:
                        P1=0XFF;
                        if(Twinkle==1) LED1=1;
                        else LED1=0;
                break;

                case 2:
                        P1=0XFE;
                        if(Twinkle==1) LED2=1;
                        else LED2=0;
                break;

                case 3:
                        P1=0XFC;
                        if(Twinkle==1) LED3=1;
                        else LED3=0;
                break;

                case 4:
                        P1=0XF8;
                        if(Twinkle==1) LED4=1;
                        else LED4=0;
                break;

                case 5:
                        P1=0XF0;
                        if(Twinkle==1) LED5=1;
                        else LED5=0;
                break;

                case 6:
                        P1=0XE0;
                        if(Twinkle==1) LED6=1;
                        else LED6=0;
                break;

                case 7:  
                        P1=0XC0;
                        if(Twinkle==1) LED7=1;
                        else LED7=0;
                break;

                case 8:
                        P1=0X80;
                        if(Twinkle==1) LED8=1;
                        else LED8=0;
                break;
        }
}
/*********定时器0初始化**************/
void Timer0Init(void)                //50毫秒@12.000MHz
{
        TMOD= 0x01;                                //设置定时器模式
        TL0 = 0xB0;                                //设置定时初值
        TH0 = 0x3C;                                //设置定时初值
//        TR0 = 1;                                //定时器0开始计时
        EA=1;                                        //开总中断
        ET0=1;                                        //开定时器0中断       
}
/*********中断服务程序**************/
void timer0() interrupt        1
{
        TL0 = 0xB0;                                //设置定时初值
        TH0 = 0x3C;                                //设置定时初值
        count1++;
        if(count1>=10)                        //0.5秒
        {
                count1=0;
                Twinkle=~Twinkle;        //闪烁标志取反
                count2++;
                if(count2>=6)                //闪烁三次
                {
                        count2=0;
                        TR0 = 0;                //关定时器
                }
        }
}
/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable()
{
        EA = 0;       /* 关中断   */
        ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
        ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */
        ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
}
/* =============== 关闭 ISP,IAP 功能 ================== */
void ISP_IAP_disable()
{
        ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
        ISP_TRIG = 0x00;
        EA   =   1;   /* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
void ISPgoon()
{
        ISP_IAP_enable();   /* 打开 ISP,IAP 功能 */
        ISP_TRIG = 0x46;  /* 触发ISP_IAP命令字节1 */
        ISP_TRIG = 0xb9;  /* 触发ISP_IAP命令字节2 */
        _nop_();
}
/* ==================== 字节读 ======================== */
uchar byte_read(uint byte_addr)
{
        ISP_ADDRH = (uchar)(byte_addr >> 8);/* 地址赋值 */
        ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
        ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
        ISP_CMD   = ISP_CMD | RdCommand; /* 写入读命令 */
        ISPgoon();       /* 触发执行  */
        ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
        return (ISP_DATA);    /* 返回读到的数据 */
}
/* ================== 扇区擦除 ======================== */
void SectorErase(uint sector_addr)
{
        uint iSectorAddr;
        iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
        ISP_ADDRH = (uchar)(iSectorAddr >> 8);
        ISP_ADDRL = 0x00;
        ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
        ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3  */
        ISPgoon();       /* 触发执行  */
        ISP_IAP_disable();    /* 关闭ISP,IAP功能 */
}
/* ==================== 字节写 ======================== */
void byte_write(uint byte_addr, uchar original_data)
{
        ISP_ADDRH = (uchar)(byte_addr >> 8);  /* 取地址  */
        ISP_ADDRL = (uchar)(byte_addr & 0x00ff);
        ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
        ISP_CMD  = ISP_CMD | PrgCommand;  /* 写命令2 */
        ISP_DATA = original_data;   /* 写入数据准备 */
        ISPgoon();       /* 触发执行  */
        ISP_IAP_disable();     /* 关闭IAP功能 */
}

评分

参与人数 1黑币 +5 收起 理由
wangboyue + 5 很给力!

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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