呼吸灯的实现

最近调了一款耳机,客户要求做呼吸灯,在连接之后红蓝灯交替呼吸,具体实现如下:

首先,创建变量:

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: ”;

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
关于呼吸灯的C语言编程Options 1,0,0 // Target 'Target 1' Device (AT89C51) Vendor (Atmel) Cpu (IRAM(0-0x7F) IROM(0-0xFFF) CLOCK(24000000)) FlashUt () StupF ("LIB\STARTUP.A51" ("Standard 8051 Startup Code")) FlashDR () DevID (2976) Rgf (REGX51.H) Mem () C () A () RL () OH () DBC_IFX () DBC_CMS () DBC_AMS () DBC_LMS () UseEnv=0 EnvBin () EnvInc () EnvLib () EnvReg (Atmel\) OrgReg (Atmel\) TgStat=16 OutDir (.\) OutName (a9) GenApp=1 GenLib=0 GenHex=1 Debug=1 Browse=1 LstDir (.\) HexSel=0 MG32K=0 TGMORE=0 RunUsr 0 0 RunUsr 1 0 BrunUsr 0 0 BrunUsr 1 0 SVCSID MODEL5=0 RTOS5=0 ROMSZ5=2 DHOLD5=0 XHOLD5=0 T51FL=80 XT51FL=0 CBANKS5=0 XBANKS5=0 RCB51 { 0,0,0,0,0,0,0,1,0 } RXB51 { 0,0,0,0,0,0,0,0,0 } OCM51 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } OCR51 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } IRO51 { 1,0,0,0,0,0,16,0,0 } IRA51 { 0,0,0,0,0,128,0,0,0 } XRA51 { 0,0,0,0,0,0,0,0,0 } XRA512 { 0,0,0,0,0,0,0,0,0 } IROM512 { 0,0,0,0,0,0,0,0,0 } C51FL=21630224 C51VA=0 C51MSC () C51DEF () C51UDF () INCC5 () AX51FL=4 AX51MSC () AX51SET () AX51RST () INCA5 () PropFld { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } IncBld=1 AlwaysBuild=0 GenAsm=0 AsmAsm=0 PublicsOnly=0 StopCode=3 CustArgs () LibMods () BankNo=65535 LX51FL=292 LX51OVL () LX51MSC () LX51DWN () LX51LFI () LX51ASN () LX51RES () LX51CCL () LX51UCL () LX51CSC () LX51UCS () LX51COB () LX51XDB () LX51PDB () LX51BIB () LX51DAB () LX51IDB () LX51PRC () LX51STK () LX51COS () LX51XDS () LX51BIS () LX51DAS () LX51IDS () OPTDL (S8051.DLL)()(DP51.DLL)(-p51)(S8051.DLL)()(TP51.DLL)(-p51) OPTDBG 48125,-1,()()()()()()()()()() ()()()() FLASH1 { 0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0 } FLASH2 () FLASH3 () FLASH4 () EndOpt
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值