最近调了一款耳机,客户要求做呼吸灯,在连接之后红蓝灯交替呼吸,具体实现如下:
首先,创建变量:
u16 count = 0; //控制PWM低电平值
u8 tick_flag = 0; //控制灯亮的模式(变亮阶段还是变暗阶段)
u8 test_flag = 0; //关断控制位,使每次只关一次
u8 flip_led_timer = 0; //呼吸灯动作标志位
之后需要将灯光控制的函数关掉:
Bsp_sys.c下usr_tmr5ms_isr()中:
if(!bt_nor_is_connected())
{
//这里会调用底层的中断,灯光就会由底层中断来控制
led_scan();
led_sync();
}
接下来就是呼吸灯的初始化:
//timer3 pwm(pwm0: PA6:1 , pwm1: PA7:2 , pwm2: PB3:3)
void timer3_pwm_init(void)
{
FUNCMCON2 = (1 << 8); //多个IO口时使用这个
// FUNCMCON2 = (3 << 8); //单个IO口时使用这个,即对应的数字,这里是PB3
CLKGAT1 |= BIT(8); //时钟
//相当于设置PWM低电平的值
//low level: TMR3DUTY0 + 1,
//high level: TMR3PR-TMR3DUTY0+1
TMR3CNT = 0; //初始值
TMR3PR = (1000*3)-1; //PWM的周期
TMR3DUTY0 = 3000 - 1; //pwm0 duty - PA6
TMR3DUTY1 = 3000 - 1; //pwm1 duty - PA7
TMR3DUTY2 = 3000 - 1; //pwm2 duty - PB3
//timer3 pwm0(bit9), pwm1(bit10), pwm2 enable(bit11)
TMR3CON |= BIT(9) | BIT(10) | BIT(11);
//timer increase clk, 1:select xosc26_div 1MHz, 0:select sysclk 26MHz
TMR3CON |= BIT(2); //时钟
TMR3CON |= BIT(0); //Timer enable;unable:‘TMR3CON &=~BIT(0);’
}
接下来就是呼吸灯的实现:
//呼吸灯的每次PWM复制,这里使用的IO口为PB3、PA7
void flip_led()
{
if(tick_flag == 0 || tick_flag == 1)//开PB3的呼吸灯,关PA7的使能
{
GPIOBDE |= BIT(3);
GPIOBDIR &= ~BIT(3);
GPIOBFEN |= BIT(3); //使能特殊功能
TMR3CON |= BIT(9)|BIT(10)|BIT(11);
if(test_flag == 0)//关一次即可
{
test_flag = 1;
GPIOADE |= BIT(7);
GPIOAFEN &= ~BIT(7);
GPIOADIR |= BIT(7);
GPIOACLR = BIT(7);
TMR3DUTY1 = 3000;
}
}
else//开PA7的呼吸灯,PB3关的使能
{
GPIOADE |= BIT(7);
GPIOADIR &= ~BIT(7);
GPIOAFEN |= BIT(7);
TMR3CON |= BIT(9)|BIT(10)|BIT(11);
if(test_flag == 1)//关一次即可
{
test_flag = 0;
GPIOBDE |= BIT(3);
GPIOBFEN &= ~BIT(3);
GPIOBDIR |= BIT(3);
GPIOBCLR = BIT(3);
TMR3DUTY2 = 3000;
}
}
if(tick_flag == 0)
{
if(count > 5)
{
count-=5;
TMR3DUTY2 = count;
}
else
{
count = 0;
TMR3DUTY2 = 0;
tick_flag = 1;
}
}
else if(tick_flag == 1)
{
if(count < 3000)
{
count+=5;
TMR3DUTY2 = count;
}
else
{
count = 3000;
TMR3DUTY2 = 3000;
tick_flag = 2;
}
}
else if(tick_flag == 2)
{
if(count > 5)
{
count-=5;
TMR3DUTY1 = count;
}
else
{
count = 0;
TMR3DUTY1 =0;
tick_flag = 3;
}
}
else if(tick_flag == 3)
{
if(count < 3000)
{
count+=5;
TMR3DUTY1 = count;
}
else
{
TMR3DUTY1 = 3000;
tick_flag = 0;
}
}
}
最后就是调用了:
普通蓝牙模式下:func_bt.c下func_bt()的while循环中:
//条件满足,呼吸灯动作
if(flip_led_timer == 1)
{
flip_led();
delay_ms(5);//控制呼吸的快慢
}
//控制初始化及呼吸灯条件
if(bt_nor_is_connected())
{
if(!flip_led_timer)
{
flip_led_timer = 1;
timer3_pwm_init();
}
}
else
{
flip_led_timer = 0;
}
蓝牙耳机通话的时候:sfunc_bt_call.c下sfunc_bt_call()的while循环中:
if(flip_led_timer == 1)
{
flip_led();
delay_ms(4);//控制呼吸的快慢
}
这里有一些需要注意的:
①:中断的底层调用需要在呼吸的时候屏蔽,不然的话会导致呼吸灯不起作用;
②:对寄存器的赋值必须去while循环中处理,不能在中断处理,会导致底层报错“ERROR ======> timer_thread miss: ”;