1、TM3定时器初始化寄存器
由图可知,计数时钟位选择了系统时钟/4。
2、时钟选择
由图可知,系统时钟选择了内部高速RC振荡器。
分析:
综上可知,计数时钟位为20MHz / 4 = 5MHz。
1/5000000Hz=0.0000002s=200ns = 0.2 μs
(1GHz=1000MHz,1MHz=1000kHz,1kHz=1000Hz)
(1s=1000ms,1ms=1000μs,1μs=1000ns。)
接下来就是cnt,cnt数到规定值以后出现中断。
cnt的高位是2,低位是240,因为是16bit的寄存器,那么前面这里的2,实际上要乘以256,低位是240,2×256+240 = 752, 752×0.2us = 150.4us。
每150us进一次中断。
中断函数里面包含呼吸灯函数
void __attribute ((interrupt(0x38))) ISR_TM3()
{
_mf6f = 0;
_ptm3pf = 0;
_ptm3af = 0;
fun_led_breathe();
}
2、呼吸灯代码
void fun_led_breathe()
{
static unsigned int LIGHTCNT;
static unsigned int PWMCNT = 0;
static unsigned char flag = 0;
if(gWorkMode == Em_Dev_PowerOn_Mode)
return;
if(bVoltageUnder) //workmode + chargemode <6.5V shutdown
gWorkMode = Em_Dev_ShutDown;
if((gWorkMode == Em_Dev_Charge_Mode) && (bCharge == Em_CHARGE_FULL)){ //chargemode >= 8.1V blue always
LED15_light();//blue
}
else if((gWorkMode != Em_Dev_Charge_Mode) && (bVoltageUnder == 0) && (bVoltageLowWarn == 0)){//has power workmode >= 7V blue always
LED15_light();//blue
}
else{
LIGHTCNT ++;
if(LIGHTCNT < PWMCNT)
{
if((gWorkMode == Em_Dev_Charge_Mode) && (bCharge == Em_CHARGE_NOT_FULL)) //chargemode >=7V~<8.1 blue breath
LED15_light();//blue
else //workmode
LED16_light();//orange
}
else
{
LED_battery_off();
}
if(LIGHTCNT > 70)
{
LIGHTCNT = 0;
if(!flag)
{
PWMCNT++;
if(PWMCNT > 70)
flag = 1;
}
else
{
PWMCNT --;
if(!PWMCNT)
flag = 0;
}
//if(PWMCNT > 120)
// {
// PWMCNT = 0;
// flag = 1;
// PWMCNT--;
// }
// else if(PWMCNT == 0)
// {
// // flag = 0;
// PWMCNT++;
// }
}
}
}
分析:
进来这个中断之后,这个中断每次150us进来,进来以后LIGHTCNT++,加到70的时候,这个PWMCNT也++,所以每进70次,你的这个PWMCN才会++, PWM会影响呼吸灯的亮度,所以这个PWM从0开始,灯就是灭的,PWM到70就是最亮的,所以从最暗到最亮就是0~70, 70×70 = 4900次出发中断,4900×150us = 736960us = 0.73696 s,从最暗到最亮是0.74s左右,再从最亮到最暗也是这么多,那么灯的一次呼吸大概就是1.5s。