一. 測試的平臺
環境 : win10,64位,MDK集成開發環境.
SDK :nRF5_SDK_15.2
協議棧:s132_nrf52_6.1_softdevice.hex.
使用例程:ble_app_uart
硬件平臺:pca10040開發板.
二. Uart概述
1、 類別
52832中串口分爲兩類,分別是UART和UARTE.
UART | UARTE | |
---|---|---|
模式 | 傳統串口模式 | easyDMA+串口 |
優點 | 功耗低 | 可接收大數據,減少CPU工作量 |
缺點 | 無法接收大數據 | 功耗高 |
2、 功耗
由於UART需要實時檢測RX線上有沒有下降沿,所以一旦UART初始化成功,高頻時鐘將一直處於打開狀態,從而導致UART模塊消耗的電流比較大,雖然UART模塊本身只需要55uA的工作電流,但是自動打開的高頻時鐘電路需要消耗250uA左右電流。如果使能了UARTE的easyDMA,那麼DMA還需要消耗額外的2mA電流。這樣UARTE工作總共需要消耗:55uA + 250uA + 2mA。因此在進入idle模式之前,強烈建議將UART關掉,以節省系統功耗。注:爲了達到低功耗和實時性雙重目的,在設計UART通信的時候,我們經常會額外再加2個GPIO口用來通知對方UART要傳送數據了。關閉uart的API爲:nrf_drv_uart_uninit或者app_uart_close。
三.Application修改
降低功耗需要關閉easyDMA.修改如下:
在不斷的開關Uart的時候,會導致NRF_DRV_UART_EVT_ERROR這個錯誤產生,這個時候需要重新使能RX就可以的。
在nrfx_uart.c的nrfx_uart_rx函數中,將rx_enable函數替換成nrfx_uart_rx_enable這個函數。
if ((!p_cb->rx_enabled) && (!second_buffer))
{
// rx_enable(p_instance);
nrfx_uart_rx_enable(p_instance);
}
我們可以看到,nrfx_uart_rx_enable函數對rx_enabled這個參數重新設置爲true.
void nrfx_uart_rx_enable(nrfx_uart_t const * p_instance)
{
if (!m_cb[p_instance->drv_inst_idx].rx_enabled)
{
rx_enable(p_instance);
m_cb[p_instance->drv_inst_idx].rx_enabled = true;
}
}
四. Sdk_config.h修改
在nrf_drv_uart.h中,我們可以看到NRF_DRV_UART_DEFAULT_CONFIG串口的默認配置參數(這個在串口初始化的時候會調用app_uart_init)
這裏面有一個關於easyDMA的配置選項,跟NRF_DRV_UART_WITH_UARTE和NRF_DRV_UART_WITH_UART這兩個宏定義有關係。
在nrf_drv_uart.h中,我找到了這兩個宏定義,如下所示
那麼我們只要讓NRFX_UARTE_ENABLED設置爲0就可以了。這個參數在sdk_config.h中能夠找到。事情並沒有那麼簡單,我們可以看下apply_old_config.h這個頭文件。
在apply_old_config.h中,可以看到Uart的相關配置,如下圖所示:
所以說要配合apply_old_config.h中的相關配置對sdk_config.h的參數進行相應的修改。
不要被UART0_CONFIG_USE_EASY_DMA這個宏定義給迷惑了,這個參數對Uart是否使用easyDMA沒任何影響。
對apply_old_config.h中的配置進行解析,我們可以知道只要將UART_ENABLED和UART_LEGACY_SUPPORT配置成1,將UART_EASY_DMA_SUPPORT配置成0就可以了。
五、串口開關
1、打開串口
① 外設上電;
② 初始化串口;
2、關閉串口
① 觸發串口停止接收事件;
②清空串口接收標誌;
nrf_uart_task_trigger(NRF_UART0,NRF_UART_TASK_STOPRX);
nrf_uart_event_clear(NRF_UART0,NRF_UART_EVENT_RXDRDY);
③關閉串口
err_code = app_uart_close();
APP_ERROR_CHECK(err_code);