找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10183|回复: 28
收起左侧

单片机LED调光程序,状态机按键处理,效果比较好

  [复制链接]
ID:140489 发表于 2017-4-21 13:38 | 显示全部楼层 |阅读模式
用状态机处理按键,终于把这个功能实现了;实验板上测试通过。
/* ********************************************************************************************* */
// 处理器   : STC89C52RC
// 编译环境 : Keil4 C51
// 系统时钟 : 11.0592MHZ
// 简单描述 : 1个独立按键,短按开关LED灯,长按调光,如果按住按键不放,LED亮度从 亮-->暗,暗-->亮,循环。
/* ********************************************************************************************* */
#include<reg52.h>
typedef unsigned char uChar8;
typedef unsigned int  uInt16;
                                         /*初始状态  确认状态   单击状态    连发状态 */
typedef enum KeyState{StateInit,StateAffirm,StateSingle,StateRepeat};//键值状态值
uChar8 pwm_led_val = 0;         //LED占空比值 0-20 0最亮
uChar8 pwm_t;                                 //周期
sbit KEY1 = P3^0;                        //定义按键端口
sbit LED = P1^0;                        //定义LED灯端口

void Timer0Init(void)
{
        TMOD |= 0x02;                        //设置定时器0工作模式2,8位自动重装
        TH0 = 240;                                //定时器装初值
        TL0 = 240;                                //11.0592M晶振下占空比最大比值是20,输出2880HZ
        EA = 1;                                        //开总中断
        ET0 = 1;                                //开定时器0中断
        TR0 = 1;                                //启动定时器0
}
void Timer1Init(void)
{
        TMOD |= 0x10;                        // 设置定时器1工作模式1,16位计数器
        TH1 = 0xDC;                                // 赋初始值
        TL1 = 0x00;                                // 11.0592M晶振下,定时10ms
        TR1 = 1;                                // 启动定时器1
}

/* ***************************************************** */
// 函数名称:        Init()
// 函数功能:   初始化
// 入口参数:        无
// 出口参数:         无
/* ***************************************************** */
void Init()                                        //初始化
{
        Timer0Init();
        Timer1Init();
               
}

//定时器0中断
void timer0() interrupt 1
{
        pwm_t++;
        if(pwm_t == 20)
        {
                pwm_t = 0; LED = 1;
        }
        if(pwm_led_val == pwm_t)
                LED = 0;                                         
}


/* ***************************************************** */
// 函数名称:KeyScan(void)
// 函数功能:扫描按键
// 入口参数:无
// 出口参数:键值(num)
/* ***************************************************** */
void KeyScan(void)
{
        static uChar8 KeyStateTemp1 = 0;                        //按键状态临时存储值1
        static uChar8 KeyTime = 0;                                        //按键延时时间
        bit KeyPressTemp1;                                                        //按键是否按下存储值1
        bit falg;                                                                        //亮度标志

        KeyPressTemp1 = KEY1;                                                //读取I/O口的键值
        switch(KeyStateTemp1)
        {       
                case StateInit:                                                        //按键初始状态
                        if(!KeyPressTemp1)                                        //当按键按下,状态切换到确认态
                                KeyStateTemp1 = StateAffirm;
                        break;
               
                case StateAffirm:                                                //按键确认态
                        if(!KeyPressTemp1)
                        {
                                KeyTime = 0;
                                KeyStateTemp1 = StateSingle;        //切换到单次触发态       
                        }
                        else KeyStateTemp1 = StateInit;         //按键已抬起,切换到初始态
                        break;
       
                case StateSingle:                                                //按键单发态
                        if(KeyPressTemp1)                                        //按下时间小于1s
                        {
                                KeyStateTemp1 = StateInit;          //按键释放,则回到初始态
                                                TR0 = !TR0;
                                                LED = 1;                                //关闭LED
               
                        }
                        else if(++KeyTime > 100)                        //按下时间大于1s(100*10ms)
                        {
                                KeyStateTemp1 = StateRepeat;        //状态切换到连发态
                                KeyTime = 0;       
                        }
                        break;
               
                case StateRepeat:                                                //按键连发态               
                        if(KeyPressTemp1)
                                KeyStateTemp1 = StateInit;                //按键释放,则进初始态
                        else                                                                //按键未释放
                        {
                                if(++KeyTime > 10)                                //按键计时值大于100ms(10*10ms)
                                {
                                        KeyTime = 0;       
                                                if(falg == 0)
                                                {
                                                        if(pwm_led_val < 20)
                                                        {
                                                                pwm_led_val++;        //亮度变暗
                                                                if(pwm_led_val==20)
                                                                        falg = 1;
                                                        }
                                                }

                                                if( falg ==1 )
                                                {
                                                        if(pwm_led_val > 0)
                                                        {
                                                                pwm_led_val--;        //亮度变亮
                                                                if(pwm_led_val==0)
                                                                        falg = 0;
                                                        }
                                                }
                                }
                                break;
                        }
                        break;
               
                default: KeyStateTemp1 = KeyStateTemp1 = StateInit; break;
        }
}


/* ***************************************************** */
// 函数名称:ExecuteKeyNum(void)
// 函数功能:按键值来执行相应的动作
// 入口参数:无
// 出口参数:无
/* ***************************************************** */
void ExecuteKeyNum(void)
{
        if(TF1)                                        //定时器1溢出
        {
                TF1 = 0;
                TH1 = 0xDC;
                TL1 = 0x00;
                KeyScan();
        }
}


void main()
{
        Init();                                        //首先初始化各数据
        while(1)                                //进入主程序大循环
        {
                ExecuteKeyNum();        //不停的检测按键是否被按下
        }

}

评分

参与人数 2黑币 +58 收起 理由
zkele + 8 很给力!这个复制一份来学习一下!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:192911 发表于 2017-4-24 06:46 | 显示全部楼层
学习              了
回复

使用道具 举报

ID:231147 发表于 2017-9-7 11:05 | 显示全部楼层
刚接触单片机,请多多关照
回复

使用道具 举报

ID:159139 发表于 2017-9-9 11:33 来自手机 | 显示全部楼层
学习学习状态机按键,感谢楼主的分享。
回复

使用道具 举报

ID:254251 发表于 2017-12-26 16:04 | 显示全部楼层
再加上掉电模式就完美了 ,谁改好我10RMB以上
回复

使用道具 举报

ID:89286 发表于 2017-12-26 18:09 | 显示全部楼层
thanks for sharing
回复

使用道具 举报

ID:243748 发表于 2017-12-30 21:26 来自手机 | 显示全部楼层
楼主可以提供下程序包吗
回复

使用道具 举报

ID:190152 发表于 2017-12-31 23:00 | 显示全部楼层
这个不错,正想做个调光台灯
回复

使用道具 举报

ID:140489 发表于 2018-1-2 10:08 | 显示全部楼层
wuxishun 发表于 2017-12-30 21:26
楼主可以提供下程序包吗

完整程序就帖子里面的,你自己复制就可以
回复

使用道具 举报

ID:135735 发表于 2018-1-31 18:05 | 显示全部楼层
不错,我什么时候才达到这样的水平
回复

使用道具 举报

ID:272625 发表于 2018-2-2 04:24 来自手机 | 显示全部楼层
好资料,有实用价值!
回复

使用道具 举报

ID:280434 发表于 2018-2-2 15:38 | 显示全部楼层
不错。学习中。
回复

使用道具 举报

ID:91521 发表于 2018-2-16 19:45 | 显示全部楼层
大哥,好厉害!
回复

使用道具 举报

ID:269211 发表于 2018-2-17 11:15 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:284003 发表于 2018-2-17 14:54 | 显示全部楼层
很好用,谢谢楼主,辛苦了!
回复

使用道具 举报

ID:36328 发表于 2019-1-14 19:56 | 显示全部楼层
状态机处理好
回复

使用道具 举报

ID:140183 发表于 2019-2-22 12:57 | 显示全部楼层
今天测试了一下.效果很好!谢谢分享!
回复

使用道具 举报

ID:74145 发表于 2019-4-8 10:51 | 显示全部楼层
这个确实好
回复

使用道具 举报

ID:14052 发表于 2019-4-20 20:15 | 显示全部楼层
学习学习
回复

使用道具 举报

ID:543809 发表于 2019-5-25 10:39 | 显示全部楼层
请问有原理图吗
回复

使用道具 举报

ID:571570 发表于 2019-6-25 11:15 来自手机 | 显示全部楼层
老哥有没有仿真图,求发到2621904761@qq.com邮箱,谢谢
回复

使用道具 举报

ID:826754 发表于 2020-11-21 17:35 | 显示全部楼层
学习了,想做LED灯的PWM调光,但不知道怎样编程。
回复

使用道具 举报

ID:577329 发表于 2020-11-22 15:23 | 显示全部楼层
为什么我复制代码,在keil4中编译失败?
回复

使用道具 举报

ID:66287 发表于 2020-11-24 15:33 | 显示全部楼层
无标题.jpg
IO口操作仿真.rar (15.05 KB, 下载次数: 10)
回复

使用道具 举报

ID:848824 发表于 2020-12-16 16:30 | 显示全部楼层
刚试验了好用,感谢。
回复

使用道具 举报

ID:848824 发表于 2021-2-17 17:53 | 显示全部楼层
这个可以控制可控硅吗
回复

使用道具 举报

ID:848824 发表于 2021-2-27 04:07 来自手机 | 显示全部楼层
这个能控制可控硅调压吗
回复

使用道具 举报

ID:859852 发表于 2021-2-27 22:14 来自手机 | 显示全部楼层
好,好好学习了,学习了 。这个资料非常实用
回复

使用道具 举报

ID:839438 发表于 2021-6-3 21:41 | 显示全部楼层
一直找类似的按键
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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