标题: 单片机LED调光程序,状态机按键处理,效果比较好 [打印本页]

作者: lids    时间: 2017-4-21 13:38
标题: 单片机LED调光程序,状态机按键处理,效果比较好
用状态机处理按键,终于把这个功能实现了;实验板上测试通过。
/* ********************************************************************************************* */
// 处理器   : 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();        //不停的检测按键是否被按下
        }

}


作者: nnlibing    时间: 2017-4-24 06:46
学习              了
作者: comer    时间: 2017-9-7 11:05
刚接触单片机,请多多关照
作者: 3760609865    时间: 2017-9-9 11:33
学习学习状态机按键,感谢楼主的分享。
作者: nanning321    时间: 2017-12-26 16:04
再加上掉电模式就完美了 ,谁改好我10RMB以上
作者: faridzled    时间: 2017-12-26 18:09
thanks for sharing
作者: wuxishun    时间: 2017-12-30 21:26
楼主可以提供下程序包吗
作者: 高低都不调    时间: 2017-12-31 23:00
这个不错,正想做个调光台灯
作者: lids    时间: 2018-1-2 10:08
wuxishun 发表于 2017-12-30 21:26
楼主可以提供下程序包吗

完整程序就帖子里面的,你自己复制就可以
作者: lin07555    时间: 2018-1-31 18:05
不错,我什么时候才达到这样的水平
作者: 都市郎    时间: 2018-2-2 04:24
好资料,有实用价值!
作者: lwz08    时间: 2018-2-2 15:38
不错。学习中。
作者: daiya    时间: 2018-2-16 19:45
大哥,好厉害!
作者: chaoself    时间: 2018-2-17 11:15
谢谢楼主分享
作者: zhangmos    时间: 2018-2-17 14:54
很好用,谢谢楼主,辛苦了!
作者: lijunn1    时间: 2019-1-14 19:56
状态机处理好
作者: qxdqx    时间: 2019-2-22 12:57
今天测试了一下.效果很好!谢谢分享!
作者: 迷恋520冬天    时间: 2019-4-8 10:51
这个确实好
作者: jldqc    时间: 2019-4-20 20:15
学习学习
作者: ASDZXCAS    时间: 2019-5-25 10:39
请问有原理图吗
作者: myfff    时间: 2019-6-25 11:15
老哥有没有仿真图,求发到2621904761@qq.com邮箱,谢谢
作者: 川蜀浪子    时间: 2020-11-21 17:35
学习了,想做LED灯的PWM调光,但不知道怎样编程。
作者: 15256089239    时间: 2020-11-22 15:23
为什么我复制代码,在keil4中编译失败?
作者: bhjyqjs    时间: 2020-11-24 15:33

IO口操作仿真.rar (15.05 KB, 下载次数: 14)


作者: zhangleixbyl    时间: 2020-12-16 16:30
刚试验了好用,感谢。
作者: zhangleixbyl    时间: 2021-2-17 17:53
这个可以控制可控硅吗
作者: zhangleixbyl    时间: 2021-2-27 04:07
这个能控制可控硅调压吗
作者: xiaobing0522    时间: 2021-2-27 22:14
好,好好学习了,学习了 。这个资料非常实用
作者: 我会想你的    时间: 2021-6-3 21:41
一直找类似的按键
作者: dj3365191    时间: 2024-11-22 17:36
这个程序我搭建电路试了一下,功能正常,但是LED一上电就亮,没有使用价值,怎样改成一上电是不亮的就好了,哪位高手指导一下,谢谢!
作者: ydq2015ok    时间: 2024-12-24 23:06
一直找类似的按键;;这个资料非常实用




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1