下面的代码用了一个二维数组来实现led定时间隔闪烁,复用很简单,直接把ledstate函数放进定时器中断就行,可以用外部函数改变ledmode,进而调整到不同的模式。想要修改间隔,就改数组值或者改定时器中断的频率,改间隔的话,可以改数组的值,也可以增加数组的行数或者列数(同时修改计数器循环值)
具体原理很简单,就是通过ledmode和currentbit这两个数值在二维数组中选值,然后与计数器做比较,定时器每次中断都会对计数器+1,于是就有了时间基础,每个1都是定时器中断的间隔。直到计数器的值大于从数组中读取到的值,才会切换读取数组的下一位。通过&运算让位数在0到3的范围里循环。
根据你的定时器中断间隔与与想要实现的闪烁,调整数组数值就行。
const unsigned char ledform[][4] = {//二维数组
//每次125ms定时器1中断ledcounter++,将ledcounter与数组做比较
{0,0,0,0}, //mode0,常亮(vcc>4200mv),数组中的0表示立即切换到下一位
{16,4,16,4}, //mode1,2000ms亮,500ms灭 (3800<vcc<=4000)
{8,4,8,4}, //mode2,1000ms亮,500ms灭 (3400<vcc<=3800)
{4,4,4,4}, //mode3,500ms亮,500ms灭 (2750=<vcc<=3400)
{1,1,1,1}, //mode4,125ms亮,125ms灭(vcc<2750)
{12,1,1,1}, //mode5,1500ms亮,125ms灭亮灭,charging
};
void LED_STATE(void){
static unsigned char ledcounter = 0;//局部变量声明
//用于从ledform中选值,比如ledmode=1,currentbit=2,segtimes=4
static unsigned char currentbit = 0;//当前位
unsigned char bitvalue = ledform[ledmode][currentbit];//读取当前位值
if(ledmode == 0){//对常亮的特殊情况单独设置
P30 = 0;
ledcounter = 0;
return;//不继续执行下面的语句
}
//状态切换判断
if(ledcounter >= bitvalue){
currentbit = (currentbit + 1) & 0X03;//0~3循环,改了列数修改这里,可以改成%N,N就是数组列数
ledcounter = 0;
}
//如果位值为0,位数+1,并退出函数,实现常亮,与下面的状态切换判断不能调换先后位置
//定义位数对应LED亮灭
if (currentbit == 0 || currentbit == 2) {
P30 = 0; // 亮
} else {
P30 = 1; // 灭
}
ledcounter++;//led计数器加1
}
|