找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 718|回复: 6
收起左侧

stc8g单片机通过pwm调节led亮度,通电的时候会亮起再灭下

[复制链接]
ID:1076567 发表于 2024-6-6 09:26 | 显示全部楼层 |阅读模式
想学pwm,所以在网上下了一个台灯的代码自己修改了一下,按键key是负责led亮灭,key1短按可以增加led亮度,key2短按减少亮度,长按都可以无极调光,LIGHT是p33口输出,我设置了通电会自动亮起,亮度为50,但是它通电会亮起再灭掉再亮起,设置成通电不亮起,也会亮一下,在主函数最开始的时候加过LIGHT=0,也还是不行嘞,我试过原来的代码也会亮一下,但是不知道哪里有问题,有没有大佬看一下
main.c文件
#include        "config.h"
#include        "gpio.h"
#include        "UART.h"
#include        "delay.h"
#include         "stdio.h"
#include        "STC8xxxx.H"
#include        "stdio.h"
#include        "string.h"
#include         "light.h"
#include        "my_uart.h"
#include        "key.h"

void main(void)
{
        light_init();                //使用定时器0作pwm功能
        key_init();
        EA = 1;
        
        delay_ms(5000);
        light_open();

        while (1)
        {
                delay_ms(1);
               
                if(key_open())
                {
                        light_key_open();
                }
                if(scan_key())
                {
                        //按键按下
                        light_task();
                }
        }
}


key.c文件

#include "key.h"

#define KEY    P32
#define Key2   P30
#define Key1   P31

bit ShortTouchFlag1=0;      //按键1短按按键有效标志
bit LongTouchFlag1=0;       //按键1长按按键有效标志
bit LongTouchRelease1=1;    //按键1长按释放过的标志
bit ShortTouchFlag2=0;      //按键2短按按键有效标志
bit LongTouchFlag2=0;       //按键2长按按键有效标志
bit LongTouchRelease2=1;    //按键2长按释放过的标志
bit Flag_1s=1;              //秒任务标志位
bit HFlag = 0;               
bit ON_OFF_Flag = 0;   

unsigned int uiKeyTimeCnt1; //按键1计数
unsigned int uiKeyTimeCnt2; //按键2计数


//P54作io输入口
void key_init(void)
{
        GPIO_InitTypeDef        GPIO_InitStructure;                //结构定义
        GPIO_InitStructure.Pin  = GPIO_Pin_5;                //指定要初始化的IO,
        GPIO_InitStructure.Mode = GPIO_HighZ;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(GPIO_P5,&GPIO_InitStructure);        //初始化

        // GPIO_InitStructure.Pin  = GPIO_Pin_All;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
        // GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        // GPIO_Inilize(GPIO_P6,&GPIO_InitStructure);        //初始化
}

unsigned char key_open(void)   //扫描开关按键
{
        if(KEY==0)
        {
                delay_ms(15);
                if(KEY==0)
                {
                          while(KEY==0);
                                ON_OFF_Flag = 1;
                                return 1;
                }               
        }               
        return 0;
}

//扫面按键
//返回 1 按下  0 没有
unsigned char scan_key(void)
{
        if(Key1==0)                     //如果按键1按下
        {
            uiKeyTimeCnt1++;            //累加按键计时
        }
        if(uiKeyTimeCnt1>100 && LongTouchRelease1==1)   //当按键超过2秒且此前释放过一次时
        {
                LongTouchFlag1 = 1;         //长按标志位置1,用于长按2秒后立即处理长按动作
                LongTouchRelease1 = 0;                 //长按释放标志置0,表示长按未释放
                HFlag = 1;
        }
        if(Key1==1)                     //当按键松开(也可能是抖动弹开)
        {
                if(uiKeyTimeCnt1>2 && uiKeyTimeCnt1<=100)   //只有大于20mS,且小于2秒,才判为短按
                {
                        uiKeyTimeCnt1 = 0;      //清零按键计时
                        ShortTouchFlag1 = 1;        //短按标志位置1
                        LongTouchFlag1 = 0;     //长按标志位置0        
                        HFlag = 1;
                }
                if(uiKeyTimeCnt1>100)       //如果松开按键时按键超过2秒,则为长按释放
                {
                        uiKeyTimeCnt1 = 0;      //清零按键计时
                        LongTouchRelease1 = 1;  //长按释放标志位置1,表示长按已释放
                }        
        }

        if(Key2==0)                     //如果按键2按下
        {
            uiKeyTimeCnt2++;            //累加按键计时
        }
        if(uiKeyTimeCnt2>100 && LongTouchRelease2==1)   //当按键超过2秒且此前释放过一次时                          
        {
                LongTouchFlag2 = 1;         //长按标志位置1,用于长按2秒后立即处理长按动作
                LongTouchRelease2 = 0;      //长按释放标志置0,表示长按未释放
                HFlag = 1;
        }
        if(Key2==1)                     //当按键松开(也可能是抖动弹开)
        {
                if(uiKeyTimeCnt2>=2 && uiKeyTimeCnt2<=100)  //只有大于等于20mS,且小于2秒,才判为短按
                {
                        uiKeyTimeCnt2 = 0;      //清零按键计时
                        ShortTouchFlag2 = 1;    //短按标志位置1
                        LongTouchFlag2 = 0;     //长按标志位置0        
                        HFlag = 1;
                }
                if(uiKeyTimeCnt2>100)       //如果松开按键时按键超过2秒,则为长按释放
                {
                        uiKeyTimeCnt2 = 0;      //清零按键计时
                        LongTouchRelease2 = 1;  //长按释放标志位置1,表示长按已释放
                }        
        }
        if(HFlag==1)
        {
                return 1;
        }
        else
        {
                return 0;
        }
}


light.c文件

#include "light.h"

#include        "timer.h"
#include        "GPIO.h"
#include  "key.h"

extern bit ShortTouchFlag1;      //按键1短按按键有效标志
extern bit LongTouchFlag1;       //按键1长按按键有效标志
extern bit LongTouchRelease1;    //按键1长按释放过的标志
extern bit ShortTouchFlag2;      //按键2短按按键有效标志
extern bit LongTouchFlag2;       //按键2长按按键有效标志
extern bit LongTouchRelease2;    //按键2长按释放过的标志
extern bit ON_OFF_Flag;          //按键开关标志

unsigned long timer0_count = 0;
unsigned char PWM_T = 0;   //0-250占空比控制变
unsigned char current_brightness = 0;        //当前亮度
unsigned char light_switch_state = 0;        //灯开关状态
signed int    brightness = 0;
        
#define IT_HZ        100000        //中断频率
#define TIM0_VALUE        65536UL - (MAIN_Fosc / IT_HZ)


void        light_init(void)
{
        GPIO_InitTypeDef        GPIO_InitStructure;                                //结构定义
        TIM_InitTypeDef                TIM_InitStructure;                                                //结构定义
/************************ P33 IO口配置 ****************************/
        GPIO_InitStructure.Pin  = LIGHT_PIN;                                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
        GPIO_InitStructure.Mode = GPIO_PullUp;                        //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
        GPIO_Inilize(LIGHT_PORT,&GPIO_InitStructure);        //初始化

/************************ 定时器配置 ****************************/
        TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;        //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
        TIM_InitStructure.TIM_Priority    = Priority_0;                        //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
        TIM_InitStructure.TIM_Interrupt = ENABLE;                                        //中断是否允许,   ENABLE或DISABLE
        TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                //指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
        TIM_InitStructure.TIM_ClkOut    = DISABLE;                                //是否输出高速脉冲, ENABLE或DISABLE
        // TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 100000UL);                //初值,
        TIM_InitStructure.TIM_Value     = TIM0_VALUE;                //初值,
        TIM_InitStructure.TIM_Run       = ENABLE;                                        //是否初始化后启动定时器, ENABLE或DISABLE
        Timer_Inilize(Timer0,&TIM_InitStructure);                                        //初始化Timer0          Timer0,Timer1,Timer2,Timer3,Timer4

}


//设置高电平占空比
//num: 0-100%
void set_duty_cycle(unsigned char num)
{
        current_brightness = num;
        if(num > 0)
        {
                light_switch_state = 1;
        }
        else
        {
                light_switch_state = 0;
        }
        PWM_T = (float)(num / 100.0)*250;
}

/********************* Timer0中断函数************************/
void timer0_int (void) interrupt TIMER0_VECTOR
{
         timer0_count++;    //每次定时器溢出加1
         
         if(timer0_count==250)   //PWM周期 100个单位
                 {
                        timer0_count=0;  //使t=0,开始新的PWM周期
                        LIGHT = 1;        //开灯
                 }
         
         if(PWM_T==timer0_count)  //按照当前占空比切换输出为高电平
                 {  
                        LIGHT = 0;        //关灯
                 }

}

//获取灯光占空比
//返回值: 0-100
int get_light_pwm(void)
{
        return PWM_T*100/250;
        // return 0;
}

void light_open(void)             //通电的时候自动亮起
{
                light_switch_state = 1;
                set_duty_cycle(50);                //设置占空比
          brightness = 50;
}

void light_key_open(void)      //开关key操作
{
                if(ON_OFF_Flag==1)
                        {
                                ON_OFF_Flag = 0;
                                if(light_switch_state==1)
                                {
                                        light_switch_state=0;
                                        EA = 0;
                                        set_duty_cycle(0);
                                        LIGHT = 0;                        
                                }
                                else
                                {
                                        EA = 1;
                                        light_switch_state=1;
                                        set_duty_cycle(brightness);                //设置占空比
                                }
                        }
}

void light_task(void)     //调节亮度
{
        if(ShortTouchFlag1==1)
                {
                        ShortTouchFlag1 = 0;
                        brightness = current_brightness + 20;
                        if(brightness > 70)        //防止超过100
                        {
                                brightness = 100;                                
                        }
                        if(brightness == 20)
                        {
                                brightness = 10;
                        }
                        set_duty_cycle(brightness);
                }
               
                if(LongTouchFlag1==1)
                {
                        LongTouchFlag1 = 0;
      while(brightness<100)               
                        {
        brightness = current_brightness + 1;
                                set_duty_cycle(brightness);
                                delay_ms(10);
                                scan_key();
                                if(LongTouchRelease1==1)
                                {
                                  break;
                                }
                        }                        
                }               
               
                if(ShortTouchFlag2==1)
                        {
                                ShortTouchFlag2 = 0;
                                brightness = current_brightness - 20;
        if(brightness >70)
                                {                                       
                                        brightness = 70;
                                }
                                if(brightness <10)
                                {
                                        brightness = 0;
                                        light_switch_state = 0;
                                }
                                set_duty_cycle(brightness);
                        }
               
                        if(LongTouchFlag2==1)
                        {
                                LongTouchFlag2 = 0;
                                while(brightness>6&&LongTouchRelease2==0)
                                {
                                        brightness = current_brightness - 1;
                                        set_duty_cycle(brightness);
                                        delay_ms(10);
                                        scan_key();
                                        if(LongTouchRelease2==1)
                                        {
                                                break;
                                        }
                                }
                        }
}


回复

使用道具 举报

ID:879348 发表于 2024-6-6 14:44 | 显示全部楼层
有没有可能这个亮起是不受代码控制的,你的硬件没有下拉电阻
回复

使用道具 举报

ID:1080935 发表于 2024-6-6 14:51 | 显示全部楼层
1、初始化最开始把LED管脚设为灭掉状态(可以单独用此程序,后续程序不要,判断是否能在开始关闭LED)。
2、确认电路问题,复位是LED是否亮起,如果亮起可能要调整电路。
回复

使用道具 举报

ID:961114 发表于 2024-6-6 15:23 | 显示全部楼层
学会这个 基本上都懂了 51hei截图20240606152323.png
回复

使用道具 举报

ID:1076567 发表于 2024-6-6 15:55 | 显示全部楼层
wufa1986 发表于 2024-6-6 14:44
有没有可能这个亮起是不受代码控制的,你的硬件没有下拉电阻

有下拉电阻的,应该是代码的问题,后面我把主函数里的EA=0,然后在light_open()函数里加了EA=1,就可以了
回复

使用道具 举报

ID:1076567 发表于 2024-6-6 15:56 | 显示全部楼层
STC庄伟 发表于 2024-6-6 15:23
学会这个 基本上都懂了

好的感谢
回复

使用道具 举报

ID:1076567 发表于 2024-6-6 15:59 | 显示全部楼层
LaoYuTou 发表于 2024-6-6 14:51
1、初始化最开始把LED管脚设为灭掉状态(可以单独用此程序,后续程序不要,判断是否能在开始关闭LED)。
2 ...

好的感谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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