想学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;
}
}
}
}
|