Nordic NRF52832串口功耗优化

NRF52832串口功耗优化

NRF52832串口作为NRF52832的一个重要外设,经常被用于与外部设备进行通信,但是,作为低功耗应用的场景,开启串口意味着设备功耗的大幅增加。于是一个大胆的猜想便引发出来,如何能使串口在使用的时候才打开,不使用的时候关闭从而实现低功耗呢?这个猜想的主要问题是我们串口的使用是不能人为的预测的(这里说的是串口接收,串口发送可以知道)。要解决这个问题,关键是解决串口接收时才打开串口这个问题。进一步分析,串口接收数据时,串口RX引脚电平会变化,于是,一个方案便应运而生,我们把串口RX引脚配置成中断引脚,当有接收数据来时,我们打开串口外设,当没有数据了,我们关闭串口外设,经过反复尝试和优化,证明了这个方案的可行,实现了串口的低功耗。主要源码分享如下:

系统复位时只初始化串口RX引脚为中断引脚,RX引脚中断配置如下:

void bsp_uart_rx_pin_init(void)
{ 
	ret_code_t err_code;
	
	err_code = nrf_drv_gpiote_init();  /*初始化GPIOTE模块*/
	APP_ERROR_CHECK(err_code);
	
	/*RX 任意电平事件*/
	nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
	in_config.pull = NRF_GPIO_PIN_NOPULL;
	
	err_code = nrf_drv_gpiote_in_init(RX_PIN_NUMBER,&in_config,in_pin_handler);
	NRF_LOG_INFO("err_code:%d\r\n",err_code);
	APP_ERROR_CHECK(err_code);
	
	/*使能事件触发*/
	nrf_drv_gpiote_in_event_enable(RX_PIN_NUMBER,true);
}

接着当RX引脚上有接收数据来时,触发RX中断回调函数 in_pin_handler,回调中主要是RX引脚中断失能,初始化串口,然后开始RX定时器,这个定时器是一个单次定时器,定时时间到后关闭串口外设,这个定时器的定时时间我这里设置的是100ms,

static void in_pin_handler(nrf_drv_gpiote_pin_t pin,nrf_gpiote_polarity_t action)
{
	ret_code_t err_code;
	
	NRF_LOG_INFO("rx gpiote.\r\n");
	nrf_drv_gpiote_in_event_disable(RX_PIN_NUMBER);   /*失能RX引脚中断*/
	bsp_uart_init();  /*初始化串口*/

	uart_rx_timers_stop();
	uart_rx_timers_start();
}

串口初始化程序跟平时使用的一样:

void bsp_uart_init(void)
{
    uint32_t err_code;

		const app_uart_comm_params_t comm_params =
		{
				.rx_pin_no    = RX_PIN_NUMBER,
				.tx_pin_no    = TX_PIN_NUMBER,
				.rts_pin_no   = RTS_PIN_NUMBER,
				.cts_pin_no   = CTS_PIN_NUMBER,
				.flow_control = APP_UART_FLOW_CONTROL_DISABLED,
				.use_parity   = false,
				.baud_rate    = UART_BAUDRATE_BAUDRATE_Baud115200
				//.baud_rate    = UART_BAUDRATE_BAUDRATE_Baud9600
		};
		
    APP_UART_FIFO_INIT(&comm_params,
                       UART_RX_BUF_SIZE,
                       UART_TX_BUF_SIZE,
                       uart_event_handle,
                       APP_IRQ_PRIORITY_LOWEST,
                       err_code);
    APP_ERROR_CHECK(err_code);
}

如下是定时器回调函数,主要实现功能是关闭串口外设,然后从新使能串口rx引脚为中断引脚,

void uart_rx_timeout_handler(void * p_context)
{
	app_uart_close();
	nrf_drv_gpiote_in_event_enable(RX_PIN_NUMBER,true);
}

如此便实现了串口接收数据才打开外设,没使用时关闭外设,关于发送,这个就很easy了发送时初始化一遍串口,发送完重新配置RX引脚为中断引脚即可。

你可能感兴趣的:(NRF52832)