下面的代碼用了一個二維數組來實現led定時間隔閃爍,復用很簡單,直接把ledstate函數放進定時器中斷就行,可以用外部函數改變ledmode,進而調整到不同的模式。想要修改間隔,就改數組值或者改定時器中斷的頻率,改間隔的話,可以改數組的值,也可以增加數組的行數或者列數(同時修改計數器循環(huán)值)
具體原理很簡單,就是通過ledmode和currentbit這兩個數值在二維數組中選值,然后與計數器做比較,定時器每次中斷都會對計數器+1,于是就有了時間基礎,每個1都是定時器中斷的間隔。直到計數器的值大于從數組中讀取到的值,才會切換讀取數組的下一位。通過&運算讓位數在0到3的范圍里循環(huán)。
根據你的定時器中斷間隔與與想要實現的閃爍,調整數組數值就行。
const unsigned char ledform[][4] = {//二維數組
//每次125ms定時器1中斷l(xiāng)edcounter++,將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;//不繼續(xù)執(zhí)行下面的語句
}
//狀態(tài)切換判斷
if(ledcounter >= bitvalue){
currentbit = (currentbit + 1) & 0X03;//0~3循環(huán),改了列數修改這里,可以改成%N,N就是數組列數
ledcounter = 0;
}
//如果位值為0,位數+1,并退出函數,實現常亮,與下面的狀態(tài)切換判斷不能調換先后位置
//定義位數對應LED亮滅
if (currentbit == 0 || currentbit == 2) {
P30 = 0; // 亮
} else {
P30 = 1; // 滅
}
ledcounter++;//led計數器加1
}
|