使用基础版SYD8811 Smart EVK测量SYD8811芯片功耗的说明

本文介绍了如何使用SYD8811开发板测量芯片功耗,并通过修改广播超时时间和利用射频睡眠功能降低功耗。在广播超时20秒后,芯片功耗降至约7uA。此外,还展示了按键唤醒射频的实现方式,以便在休眠后重新启动广播。
摘要由CSDN通过智能技术生成

1 准备工作

本文采用SYD8811 Smart EVK 基础版开发板测量SYD8811芯片的功耗,按以下三个步骤做准备。
在这里插入图片描述

1.1 取出UART排针的两个跳线帽,即断开P0.15和P0.16和USB-TTL芯片的连接。

1.2 用烙铁断开JP1,即将SYD8811的VDD引脚和LDO芯片VR1(3.3V)断开。如果JP2是连接的,也要先断开。

1.3 测量电源(一般为3V或3.3V)分别板上【+3.3V】和【GND】排针,如果是用万用表测量,则按上图所示,将电流表(万用表)串接到3.3V电源线中。

2 测试程序设计

2.1 将广播超时设置为20秒

static void setup_adv_data()
{
	struct gap_adv_params adv_params;	
	struct gap_ble_addr dev_addr;
	
	adv_params.type = ADV_IND;
	adv_params.channel = 0x07;  // advertising channel : 37 & 38 & 39
	adv_params.interval = 1600; // advertising interval : 1000ms (1600 * 0.625ms)
	adv_params.timeout = 0x14;  // 广播超时timeout的值配置为20s			

	SetAdvParams(&adv_params);	
	
	/*get bluetooth address */
	GetDevAddr(&dev_addr);
	ADV_DATA[11] = dev_addr.addr[0];
	ADV_DATA[12] = dev_addr.addr[1];
	ADV_DATA[13] = dev_addr.addr[2];
	ADV_DATA[14] = dev_addr.addr[3];
	ADV_DATA[15] = dev_addr.addr[4];
	ADV_DATA[16] = dev_addr.addr[5];
	
	
	SCAN_DATA[4] = dev_addr.addr[0];
	SCAN_DATA[5] = dev_addr.addr[1];
	SCAN_DATA[6] = dev_addr.addr[2];
	SCAN_DATA[7] = dev_addr.addr[3];
	SCAN_DATA[8] = dev_addr.addr[4];
	SCAN_DATA[9] = dev_addr.addr[5];
	
	SetAdvData(ADV_DATA, sizeof(ADV_DATA), SCAN_DATA, sizeof(SCAN_DATA));

	*(uint8_t *)0x40020014 = 0x01;		//设置ADV_PITV为1,降低功耗
}

2.2 在广播结束中断事件GAP_EVT_ADV_END判断将原来的StartAdv()函数去掉,用射频睡眠标识代替,这样每次广播20秒后,芯片的射频都会自动进入休眠状态。

void ble_evt_callback(struct gap_ble_evt *p_evt)
{	
	if(p_evt->evt_code == GAP_EVT_ATT_WRITE)
	{
		#ifdef _GPIO_LED_CONTROL_
//			GPIO_Pin_Toggle(U32BIT(GPIO_LED_WRITEING));
		#endif
		
		ble_gatt_write(p_evt->evt.att_write_evt);
	}
	else if(p_evt->evt_code == GAP_EVT_ATT_READ)
	{
		#ifdef _GPIO_LED_CONTROL_
//			GPIO_Pin_Toggle(U32BIT(GPIO_LED_READING));
		#endif
		
		ble_gatt_read(p_evt->evt.att_read_evt);
	}
	else if(p_evt->evt_code == GAP_EVT_CONNECTED)
	{
		connect_flag = 1;								 //连接状态
		update_latency_mode=0;
		
		Timer_Evt_Start(EVT_2S);
		
		#ifdef _GPIO_LED_CONTROL_
//			GPIO_Pin_Toggle(U32BIT(GPIO_LED_CONNECT));
		#endif
		
		DBGHEXDUMP("Connected addr:",p_evt->evt.bond_dev_evt.addr,sizeof(p_evt->evt.bond_dev_evt.addr));
	}
	else if(p_evt->evt_code == GAP_EVT_DISCONNECTED)
	{		
		DBGPRINTF("Disconnected,reson:0x%02x\r\n", p_evt->evt.disconn_evt.reason);

		start_tx = 0;
		connect_flag = 0;
		
		//clr uart rx fifo
		uart_rx_buf.header = uart_rx_buf.tail;		
		Timer_Evt_Stop(EVT_1S_OTA);
		setup_adv_data();		//断开连接之后功耗大10uA
		StartAdv();	

		UartEn(false);	//不允许RF sleep时关闭XO
		DBGPRINTF(("start adv @ disc!\r\n")); 
	}
	else if(p_evt->evt_code == GAP_EVT_ATT_HANDLE_CONFIGURE)
	{
		if(p_evt->evt.att_handle_config_evt.uuid == BLE_UART)
		{
			if(p_evt->evt.att_handle_config_evt.value == BLE_GATT_NOTIFICATION)
			{
				start_tx |= 0x01;
				UartEn(true);	//不允许RF sleep时关闭XO,休眠的时候因为32Mhz晶振还在,所以功耗很高
				uart_0_ClrFiFo();
				
				//clr uart rx fifo
				uart_rx_buf.header = uart_rx_buf.tail;
				
				#ifdef _GPIO_LED_CONTROL_
//				GPIO_Set_Bits(U32BIT(GPIO_LED_NOTIFYEN));
				#endif
				
				DBGPRINTF(("UART notify Enabled!\r\n"));
			}
			else
			{
				start_tx &= ~0x01;
				UartEn(false);	//允许硬件自由控制32Mhz晶振,休眠的时候功耗很低
				
				#ifdef _GPIO_LED_CONTROL_
//				GPIO_Clear_Bits(U32BIT(GPIO_LED_NOTIFYEN));
				#endif
				DBGPRINTF(("UART notify Disabled!\r\n"));
			}
		}
	}
	else if(p_evt->evt_code == GAP_EVT_L2CAP_UPDATE_RSP)
	{
		switch(p_evt->evt.l2cap_update_rsp_evt.result)
		{
			case CONN_PARAMS_ACCEPTED:
				#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_) 
				DBGPRINTF(("update rsp ACCEPTED\r\n"));
				{
					struct gap_link_params  link_app;
					GetLinkParameters(&link_app);
					#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
					dbg_printf("interval:%x latency:%x\r\n",link_app.interval,link_app.latency);
					#endif
				}
				#endif
				break;
			case CONN_PARAMS_REJECTED:
				#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
				DBGPRINTF(("update rsp REJECTED\r\n"));
				#endif
				break;
			case CONN_PARAM_SMART_TIMEROUT:
				#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
				DBGPRINTF(("update rsp TIMEROUT\r\n"));
				#endif
				break;
			case CONN_PARAM_SMART_SUCCEED:
				#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
				DBGPRINTF(("update rsp SUCCEED\r\n"));
				#endif
				break;
			case CONN_PARAM_LATENCY_ENABLE:
				#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
				DBGPRINTF(("Enable latency\r\n"));
				#endif
				break;
			case CONN_PARAM_LATENCY_DISABLE:
				#if defined(_DEBUG_) || defined(_SYD_RTT_DEBUG_)
				DBGPRINTF(("Disable latency\r\n"));
				#endif
				break;
		}
	}
	else if(p_evt->evt_code == GAP_EVT_CONN_UPDATE_COMP)
	{
		struct gap_link_params link;
		GetLinkParameters(&link);
		DBGPRINTF("CONN_UPDATE_COMP: %d, %d, %d\r\n", link.interval, link.latency, link.svto);
	}
	else if(p_evt->evt_code == GAP_EVT_ADV_END)
	{
//		StartAdv();							
		dbg_printf("20s ADV timerout, RF sleep.\r\n");			
		RF_Status = false;
		RFSleep();
	}
}

我们使用EFM32 Energy Profiler测量芯片的功耗,该测量工具的测量范围0.1uA到 50mA。在开发板上电20秒内可以测量出SYD8811的一秒广播一次的功耗,下面是实测值,大概为22uA。
在这里插入图片描述
20秒后,芯片的射频进入休眠,而芯片也处于浅睡状态,此时的功耗约为7uA。
在这里插入图片描述
如果觉得广播时间过短可以配置adv_params.timeout 的值为想要的时间,或者广播结束中断事件里面重启广播。

2.3 按键唤醒射频
首先是初始化按键IO口。

void KEY_LED_Init(void)
{
	PIN_Set_GPIO(U32BIT(LED1) | U32BIT(LED2) | U32BIT(LED3) | U32BIT(LED4)| U32BIT(KEY1) | U32BIT(KEY2) | U32BIT(KEY3) | U32BIT(KEY4)/* | U32BIT(KEY5)*/ ,PIN_SEL_GPIO);
	GPIO_Set_Input(U32BIT(KEY1) | U32BIT(KEY2) | U32BIT(KEY3) | U32BIT(KEY4), U32BIT(KEY1) | U32BIT(KEY2) | U32BIT(KEY3) | U32BIT(KEY4));				//设置输入反相
	PIN_Pullup_Enable(T_QFN_48, U32BIT(KEY1) | U32BIT(KEY2) | U32BIT(KEY3) | U32BIT(KEY4));
	GPIO_Input_Enable( U32BIT(KEY1) | U32BIT(KEY2) | U32BIT(KEY3) | U32BIT(KEY4));	
		
	GPIO_Set_Output(U32BIT(LED1) | U32BIT(LED2) | U32BIT(LED3) | U32BIT(LED4));
	GPIO_Set_Bits(U32BIT(LED1) | U32BIT(LED2) | U32BIT(LED3) | U32BIT(LED4));

}

接着配置按键KEY2为外部中断触发。

	io_irq_enable(U32BIT(KEY2), &GPIO_callback);

按键外部中断处理函数如下,即重新配置广播参数,开始广播。

void  GPIO_callback(void)
{
	uint32_t SW;
	
	SW=GPIO_IRQ_CTRL->GPIO_INT;	
	if(SW&U32BIT(KEY2))
	{
		if(RF_Status == false)
		{
			RF_Status = true;		
			RFWakeup();
			DelayMS(100);			
			UartEn(true);
			ble_init();
			UartEn(false);
			DelayMS(100);
			StartAdv();		
			dbg_printf("ADV restart 20s.\r\n");			
		}
	}	
}

当射频休眠后,按下开发板上的按键KEY2,即可重启广播。

为了方便测试,我将代码上传到这里。欢迎下载测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值