STC15W101芯片五档调光程序求助!!!

2019-07-15 18:44发布

设计要求:

STC15W101芯片,1脚按键接地,5脚PWM输出用于调光,6脚接红LED,7脚接绿LED,8脚接蓝LED,三个自检灯负极接地(高电平亮)
通电时,芯片自检,三个灯闪亮一下。
开机时,按住按键,达到1秒钟时,三个指示灯按8绿→7红→6蓝的顺序依次点亮一下,一次只亮一个灯,每个灯亮的时间约1秒,这期间5脚无输出。
三个自检灯依次亮完后,蓝灯熄灭,返回到绿灯长亮,此时5脚有输出,是最小档(即1档,占空比20%)。
点一下按键(要求是按下去的时刻),会增加一档PWM,指示灯点亮的组合也不同(此时是绿+蓝,2档),依次点击按钮,共有五档,5脚占空比逐档变大,第五档最大(100%),再按一下又回到最低档(绿灯亮,占空比20%),继续按又增加一档,指示灯的组合也
同步变化……点击按钮可以反复循环……12345档的PWM宽度依次加大(20%,40%,60%,80%,100%),每档对应点亮的指示灯是:1、绿。2、绿+蓝。3、蓝。4、蓝+红。5、红。
不管在哪个档位工作时,按住按键达到1秒时就关机,三个指示灯和负载全灭。芯片进入掉电状态。
PWM频率500Hz。




程序部分:



/*************        功能说明        **************

使用timer0模拟16通道PWM驱动程序。

定时器中断频率一般不要超过100KHZ, 留足够的时间给别的程序运行.

本例子使用33.1776MHZ时钟, 50K的中断频率, 100级PWM, 周期为2ms.

中断里处理的时间不超过4us, 占CPU时间大约为25%.
pwm 频率为500HZ

******************************************/

#include        <reg52.h>

#define MAIN_Fosc                33177600UL        //定义主时钟
#define        Timer0_Rate                50000                //中断频率


typedef         unsigned char        u8;
typedef         unsigned int        u16;
typedef         unsigned long        u32;

//sfr        AUXR = 0x8E;

#define        Timer0_Reload        (65536UL -(MAIN_Fosc / Timer0_Rate))                //Timer 0 重装值

//************** PWM8 变量和常量以及IO口定义 ***************
//********************        8通道8 bit 软PWM        ********************

#define                PWM_DUTY_MAX        100        // 0~255        PWM周期, 最大255
#define                PWM_ON                        1        // 定义占空比的电平, 1 或 0

#define                PWM_OFF                        (!PWM_ON)
#define                PWM_ALL_ON                (0xff * PWM_ON)
///
#define                LAMP_ON                1
#define                LAMP_OFF        0

//I/O设置
sbit  pwm_out=P3^0;
sbit  red_lamp=P3^1;
sbit  green_lamp=P3^2;
sbit  blue_lamp=P3^3;
sbit  key_in=P3^4;
//
//档位占空比设置
#define one_dang          20                //一档
#define two_dang          40                //二档
#define three_dang  60                //三档
#define four_dang          80                //四档
#define five_dang          100                //五档  six seven eight nine ten


#define dianan                2000        //点按
#define duanan                4000        //短按
#define changan                8000        //长按

u8  dangshu;                //在某个档,存某个档的占空比数
u8  dangcount;                //档位存储


u8        pwm_duty;                //周期计数值

u16     key_jishu;
bit   key_down;
bit          kaiji_f;                //标志开机
bit   huandang;                //档位记录

/**********************************************/
void delay(u16 x)
{
        do{x=x-1;WDT_CONTR=0x3c;}while(x>0);
}
//
//开机自检
void kaiji_lamp_out(void)
{       
        u8  i;
        //绿红兰依次点亮一下,每次只亮一个灯,每个亮灯时间约0.4秒(0.2~0.4秒)
        green_lamp=LAMP_ON;
        for(i=0;i<100;i++){delay(15000);}
        green_lamp=LAMP_OFF;
        red_lamp=LAMP_ON;
        for(i=0;i<100;i++){delay(15000);}
        red_lamp=LAMP_OFF;
        blue_lamp=LAMP_ON;
        for(i=0;i<100;i++){delay(15000);}
        blue_lamp=LAMP_OFF;
        for(i=0;i<100;i++){delay(15000);}
        green_lamp=LAMP_ON;
        pwm_out=PWM_ON;
        for(i=0;i<100;i++){delay(15000);}
    pwm_out=PWM_OFF;
}
/////按键
void  int2() interrupt 10
{       
        INT_CLKO&=0xef;                        //先关中断,系统会自动清除中断标志       
}
/////
void huandang_chuli()
{
        if(huandang)
                {
                        huandang=0;
                        green_lamp=blue_lamp=red_lamp=LAMP_OFF;
                        switch(dangcount)
                        {
                                case 0:        dangshu=one_dang;        green_lamp=LAMP_ON;                                break;
                                case 1:        dangshu=two_dang;        green_lamp=blue_lamp=LAMP_ON;        break;
                                case 2:        dangshu=three_dang;        blue_lamp=LAMP_ON;                                break;
                                case 3:        dangshu=four_dang;        blue_lamp=red_lamp=LAMP_ON;                break;
                                case 4:        dangshu=five_dang;        red_lamp=LAMP_ON;                                break;
                                default:    dangshu=one_dang;        green_lamp=LAMP_ON;                                break;
                        }
                }
}
void main(void)
{
        //char i;

        green_lamp=blue_lamp=red_lamp=LAMP_OFF;
        dangshu=one_dang;
        dangcount=0;
        key_jishu=0;
        pwm_out=PWM_OFF;
        key_down=0;
        kaiji_f=0;
        huandang=0;
        pwm_duty=0;

        //INT_CLKO|=0x10;                //打开按键唤醒功能
        AUXR |=  (1<<7);        // Timer0 set as 1T mode
        TMOD &= ~(1<<2);        // Timer0 set as Timer
        TMOD &= ~0x03;                // Timer0 set as 16 bits Auto Reload
        TH0 = Timer0_Reload / 256;        //Timer0 Load
        TL0 = Timer0_Reload % 256;
        ET0 = 1;                //Timer0 Interrupt Enable
        PT0 = 1;                //高优先级
        //TR0 = 1;                //Timer0 Run
        EA = 1;                        //打开总中断       
       
        while(1)
        {
                if(!key_in){        if(key_jishu<60000){key_jishu++;}

                                                if(!kaiji_f)        //若是关机时,长按则开机
                                                {
                                                        if(key_jishu>duanan)
                                                        {kaiji_f=1;kaiji_lamp_out();pwm_out=PWM_ON; dangshu=one_dang;TR0 = 1;key_jishu=0;do{delay(1000);}while(!key_in);}
                                                        else
                                                        {
                                                                delay(200);
                                                                if(key_in){key_jishu=0;}
                                                        }
                                                }
                                                else                //开机时
                                                {key_down=1;
                                                        delay(200);                               
                                                        if(!key_in)
                                                                {               
                                                                        if((key_jishu>(dianan-2000))&&(key_jishu<(dianan+1000))&&(kaiji_f))        //换档
                                                                                {huandang=1;if(dangcount<4)dangcount++;else{dangcount=0;}}       
                                                                                huandang_chuli();
                                                                        key_jishu=0;
                                                                        do{delay(1000);
                                                                                if(key_jishu<60000){key_jishu++;}
                                                                                if((key_jishu>changan)&&(kaiji_f))                //按1秒关机
                                                                                        {key_down=0;kaiji_f=0;        key_jishu=0;TR0 = 0;pwm_out=PWM_OFF;green_lamp=blue_lamp=red_lamp=LAMP_OFF;INT_CLKO|=0x10;PCON|=0x02;}
                                                                                }while(!key_in);
                                                                        key_down=0;
                                                                        key_jishu=0;
                                                                }
                                               
                                                }
                                   }               
                delay(200);                //假如10000次延时200US,如果不是需要调整
        }
}


/********************** Timer0 40us中断函数 ************************/
void timer0 (void) interrupt 1
{               
        if(++pwm_duty == PWM_DUTY_MAX)                //PWM周期结束,重新开始新的周期
        {
                pwm_duty = 0;
                pwm_out=PWM_ON;       
        }
        if(pwm_duty>=dangshu){pwm_out=PWM_OFF;}
}


现在的问题是:
一直不断电工作,长按按键1秒关机后可以掉电,再开机,按第一下无反应,但已经重新上电了(此时灯不亮,但有十几mA电流,电池会耗尽哦!!!),松手再长按一次才可以开机成功(亮灯开始自检),为什么要按两下?怎么解决?
另外,按键有点跳档的状况(就像连续按了两次一样),如何改善?特别是自检完后,1档转2档时,按一下很容易到3档(按键没问题)
如何精简程序?(现在编译后是530字节,如何小于500字节,这样可以选择STC15W100芯片)
恳请各位高手帮忙分析改善程序,小弟感激不尽。。。


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。