单键实现无极调光程序案例
最近在用FC系列单片机写了一个单键实现无极调光冷暖光可控的程序案例
用的是FC2720系列,是一款8位的单片机,带4路8bit PWM,
功能:有冷光和暖光可调节,一档暖光100%亮度;二档冷光与暖光各50%亮度;三档冷光100%。第一次长按默认向上调节,第二次向下调,到最值不在变化
下面展示一下案例代码:
pwm控制部分源文件
#include "FC2720.h"
#include "time.h"
#include "global.h"
#include "key.h"
#include "delay.h"
uint16_t PWM_TEMP=0;
uint8_t u8led1Status=0;
void ledmode_ctr(void)
{
switch(u8led1Status)
{
case 0:
pwm12_disable();
pwm13_disable();
break;
//可能单片机的PWM存在bug,当我给占空比寄存器赋值255时,定时器直接溢出了
//所以我下面我是赋值253,为了防止它溢出
case 1:
pwm13_disable();
TM1D2=PWM_TEMP;
break;
case 2:
TM1D2=PWM_TEMP;
TM1D3=PWM_TEMP;
break;
case 3:
pwm12_disable();
TM1D3=PWM_TEMP;
break;
}
}
/*按键服务函数*/
void key_service(void)
{
if(bitKey[K1].bitShortClick)
{
pwm12_init();
pwm13_init();
bitKey[K1].bitShortClick=0;
u8led1Status++;
if(u8led1Status==1)
{
PWM_TEMP=253; //暖光 100%
DirFlag=0;
}
else if(u8led1Status==2)
{
PWM_TEMP=205; //冷光 暖光 各50%
DirFlag=0;
}
else if(u8led1Status==3)
{
PWM_TEMP=253; //冷光 100%
DirFlag=0;
}
else
{
u8led1Status=0;
}
}
if(bitKey[K1].bitLongClick)
{
if(bit20ms)
{
bit20ms=0;
if(DirFlag==1) //up
{
if(PWM_TEMP>=254)
{
PWM_TEMP=254;
}
else
{
PWM_TEMP++;
}
}
else //down
{
if(PWM_TEMP<=161)
{
PWM_TEMP=161;
}
else
{
PWM_TEMP--;
}
}
}
}
}
/*睡眠控制--当检测到关机进入睡眠模式 -- 睡眠功耗 0uA*/
void sleep_ctr(void)
{
uint8_t u8flag=0;
if(u8led1Status==0)
{
system_init();
bitKey[K1].bitLock=1;
for(u8flag=0;u8flag<100;u8flag++)
{
WDTR=0X5A;
delay_1ms(10);
key_scan();
if(bitKey[K1].bitLock==0)
break;
}
INTEN=0x20;
do{
INTRQ=0;
__asm{SleepMode};
}while(P_K1);
INTEN=0;
INTRQ=0;
INTRQ1=0;
if(P_K1==0)
bitKey[K1].bitShortClick=1;
bitKey[K1].bitLock=1;
t0_enable();
}
}
/*系统寄存器初始化*/
void system_init(void)
{
P1 =0x00;
P1M =0xF7; //P13 为输入 0 = 输入模式 1 = 输出模式
P1W =0x08; //P13唤醒使能 0 = 屏蔽 1 = 使能
P1UR =0x08; //P13上拉
P1PD =0x00;
P3 =0x00; //
P3M =0xFF; //
P3W =0x00; //
P3UR =0x00; //0 = 无上拉 1 = 有上拉
P3PD =0x00; //0 = 无下拉 1 = 有下拉
ADPCON=0x00;
ADR =0x00; //
VREFH =0x00; //内部参考电压: VDD:0x03 4.0V:0x02 3.0V:0x01 2.0V:0x00
ADM =0x00; //
T0M=0x00;
T0IE=0;
TM1M =0x00;
TM2M =0x00;
PWM1E=0x00;
PWM2E=0x00;
FGIE=0;
}
头文件
#ifndef __GLOBAL_H_
#define __GLOBAL_H_
extern uint16_t PWM_TEMP;
extern uint8_t u8led1Status;
extern void key_service(void);
extern void system_init(void);
extern void sleep_ctr(void);
extern void ledmode_ctr(void);
#endif
按键检测部分源文件
#include "FC2720.h"
#include "key.h"
bit DirFlag=0; //调整方向
struct KEY_STRUCT bitKey[KEY_MAX];
void key_scan(void)
{
if(P_K1)
{
bitKey[K1].u8cnt=0;
bitKey[K1].bitLock=0;
bitKey[K1].bitLongClick=0;
if(bitKey[K1].bitShortClickTmp)
{
bitKey[K1].bitShortClick=1;
bitKey[K1].bitShortClickTmp=0;
}
}
else if(bitKey[K1].bitLock==0)
{
bitKey[K1].u8cnt++;
if(bitKey[K1].u8cnt==5)
{
bitKey[K1].bitShortClickTmp=1;
}
if(bitKey[K1].u8cnt>99)
{
DirFlag^=1;
bitKey[K1].u8cnt=0;
bitKey[K1].bitLock=1;
bitKey[K1].bitShortClickTmp=0;
bitKey[K1].bitLongClick=1;
}
}
}
按键扫描头文件部分
#ifndef __KEY_H
#define __KEY_H
#define P_K1 FP13
struct KEY_STRUCT
{
uint8_t bitShortClick;
uint8_t bitShortClickTmp;
uint8_t bitLongClick;
uint8_t bitLock;
uint8_t u8cnt;
};
#define KEY_MAX 1
#define K1 0
extern bit DirFlag;
extern struct KEY_STRUCT bitKey[KEY_MAX];
extern void key_scan(void);
void key_service(void);
#endif
定时器及硬件PWM部分
#include "FC2720.h"
#include "time.h"
#define PWM_INIT_VALUE 156
bit bit250us=0;
bit bit1ms=0;
bit bit5ms=0;
bit bit10ms=0;
bit bit100ms=0;
bit bit20ms=0;
bit bit50ms=0;
//中断函数
void __interrupt[0x8] isr(void)
{
static uint8_t i=0,j=0,x=0,t=0,k=0,cont_20ms=0;
if(T0IF)
{
T0C=68; //装初值
j++;
bit250us=1;
if(j>3)
{
j=0;
bit1ms=1;
i++;
t++;
x++;
k++;
}
if(i>4)
{
i=0;
bit5ms=1;
}
if(t>9)
{
t=0;
bit10ms=1;
cont_20ms++;
}
if(cont_20ms>2)
{
cont_20ms=0;
bit20ms=1;
}
if(k>49)
{
k=0;
bit50ms=1;
}
if(x>99)
{
x=0;
bit100ms=1;
}
T0IF=0; //中断标志位需要软件清零
}
}
//T0 定时器初始化
void t0_enable(void)
{
T0M=0XE0; //110:Fcpu/4 12M/4/4=750KHz 750kHz/188=4khz 256-188=68
T0C=68; //250us
T0IE=1; //开启T0中断
FGIE=1; //开总中断
}
//关T0 定时器
void t0_disable(void)
{
T0M=0x00;
T0IE=0;
FGIE=0;
}
//PWM12、13初始化 初值156
//12M/1/100=120KHz 256-100=156
void pwm12_init(void)
{
TM1M |=0XF6;
PWM1E|=0X42;
TM1C =PWM_INIT_VALUE;
TM1D2=PWM_INIT_VALUE;
}
void pwm13_init(void)
{
TM1M |=0XF6;
PWM1E|=0X84;
TM1C =PWM_INIT_VALUE;
TM1D3=PWM_INIT_VALUE;
}
//关PWM
void pwm12_disable(void)
{
if(PWM1E&0X42)
{
PWM1E&=0XBD; //禁止P32输出PWM12信号
FP32=0;
}
}
void pwm13_disable(void)
{
if(PWM1E&0X84)
{
PWM1E&=0X7B; //禁止P31输出PWM13信号
FP31=0;
}
}
定时器头文件
#ifndef __TIME_H__
#define __TIME_H__
extern bit bit250us;
extern bit bit1ms;
extern bit bit5ms;
extern bit bit10ms;
extern bit bit20ms;
extern bit bit100ms;
extern bit bit50ms;
extern void t0_enable(void);
extern void t0_disable(void);
extern void pwm12_init(void);
extern void pwm13_init(void);
extern void pwm12_disable(void);
extern void pwm13_disable(void);
#endif
延时源文件
#include "FC2720.h"
#include "delay.h"
void delay_1ms(uint8_t x_1ms)
{
uint8_t i=0;
for(;x_1ms>0;x_1ms--)
{
for(i=249;i>0;i--)
{
__asm{nop};
__asm{nop};
__asm{nop};
__asm{nop};
__asm{nop};
__asm{nop};
}
}
}
延时头文件
#ifndef __DELAY_H__
#define __DELAY_H__
extern void delay_1ms(uint8_t x_ms);
#endif
主函数
/******************************************************************
* FC2720 程序案例 单键两路无极调光
*******************************************************************/
#include "FC2720.h"
#include "time.h"
#include "global.h"
#include "key.h"
void main(void)
{
system_init();
t0_enable();
pwm12_init();
pwm13_init();
while(1)
{
if(bit1ms)
{
bit1ms=0;
}
if(bit10ms)
{
bit10ms=0;
WDTR=0X5A; //喂狗
key_scan();
key_service();
ledmode_ctr();
}
if(bit50ms)
{
bit50ms=0;
sleep_ctr();
}
if(bit100ms)
{
bit100ms=0;
}
}
}