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