在嵌入式系統(tǒng)的設(shè)計中,低功耗設(shè)計(Low-Power Design)是許多設(shè)計人員必須面對的問題,其原因在于嵌入式系統(tǒng)被廣泛應(yīng)用于便攜式和移動性較強的產(chǎn)品中去,而這些產(chǎn)品不是一直都有充足的電源供應(yīng),往往是靠電池來供電,所以設(shè)計人員從每一個細節(jié)來考慮降低功率消耗,從而盡可能地延長電池使用時間。因此,大部分芯片都會有低功耗模式,以CW32L083為例,它就是一個32位低功耗微控制器。
一、芯片模式介紹
1.CW32L083工作模式
CW32L083 支持三種工作模式,由內(nèi)嵌的電源管理模塊自動完成電源的統(tǒng)一管理。三種工作模式是:
? 休眠模式(Sleep mode)
? 深度休眠模式(DeepSleep mode)
電源上電后,系統(tǒng)自動進入運行模式。用戶可通過軟件程序,進入休眠或深度休眠兩種低功耗運行狀態(tài);在低功耗運行狀態(tài)時,可通過硬件中斷觸發(fā)喚醒機制,使系統(tǒng)返回到運行模式。
2.進入休眠模式或深度休眠模式
使用 M0+ 內(nèi)核的 ARM 等待中斷專用指令,WFI(Wait for Interrupt),配合 M0+ 內(nèi)核的系統(tǒng)控制寄存器(SCR, System Control Register)的 SLEEPONEXIT 和 SLEEPDEEP 位域,可實現(xiàn)立即進入或退出(中斷服務(wù)程序)時進 入休眠模式或深度休眠模式。
? 立即進入
執(zhí)行 WFI 指令,MCU 將立即進入休眠模式(SLEEPDEEP 為 0 時)或深度休眠模式(SLEEPDEEP 為 1 時)
? 退出時進入
將 SLEEPONEXIT 位置 1,當(dāng)退出最低優(yōu)先級的中斷服務(wù)程序后,MCU 會進入休眠模式(SLEEPDEEP 為 0 時) 或深度休眠模式(SLEEPDEEP 為 1 時),而不需執(zhí)行 WFI 指令 。
在深度休眠模式下,系統(tǒng)將自動關(guān)閉高速時鐘。如用戶需要在深度休眠模式下使部分外設(shè)仍保持運行,則須在進入深度休眠模式前,啟動相應(yīng)的低速時鐘并將該外設(shè)時鐘設(shè)置為此低速時鐘。
3.退出休眠模式或深度休眠模式
在休眠模式或深度休眠模式下,均可通過中斷來喚醒 CPU,返回到運行模式。但是,值得注意的是,如果用戶在中斷服務(wù)程序中執(zhí)行 WFI 命令進入休眠(包括深度休眠),則需要比此中斷更高優(yōu)先級的中斷才能喚醒 CPU,因此,我們強烈建議用戶在準備進入休眠前,應(yīng)先處理完所有中斷服務(wù)程序,并且清除所有中斷請求和中斷標志。
使用中斷退出休眠模式,用戶必須在進入休眠(包括深度休眠)前使能此中斷的允許位。
中斷喚醒退出深度休眠模式時,CPU 運行狀態(tài)與退出休眠模式相同。
4.UART控制深度休眠模式
UART控制器工作在雙時鐘域下,支持在深度休眠模式下進行正常的數(shù)據(jù)收發(fā),并通過接收完成中斷喚醒 MCU回到運行模式。
如果設(shè)置了傳輸時鐘 UCLK來源為低速時鐘,當(dāng)系統(tǒng)進入深度休眠模式后,高速時鐘將停止,低速時鐘保持運行,UART仍可以進行正常的數(shù)據(jù)收發(fā)(波特率僅支持 2400 bps、4800 bps 和 9600 bps)。 要實現(xiàn)深度休眠模式下使用 UART 喚醒功能,需在進入深度休眠模式之前使能 UART 接收完成中斷(即設(shè)置 UARTx_IER.RC 為 1),數(shù)據(jù)接收完成時,接收完成中斷將喚醒MCU恢復(fù)到運行模式。
如果設(shè)置了傳輸時鐘 UCLK 來源為高速時鐘,當(dāng)系統(tǒng)進入深度休眠模式后,高速時鐘會停止運行,UAR不會接收數(shù)據(jù)。此時,仍可通過GPIO中斷喚醒 MCU,實現(xiàn)在深度休眠模式下接收數(shù)據(jù),參考配置步驟如下:
步驟 1:使能 UARTx_RXD 對應(yīng)引腳的 GPIO 下降沿中斷;
步驟 2:設(shè)置 UARTx_CR1.START 為 1,選擇 RXD 信號起始位判定方式為低電平;
步驟 3:使能 UART 接收(即設(shè)置 UARTx_CR1.RXEN 為 1);
步驟 4:進入深度休眠模式;
步驟 5:等待主機發(fā)送數(shù)據(jù),產(chǎn)生 GPIO 下降沿中斷,喚醒 MCU;
步驟 6:關(guān)閉 RXD 對應(yīng)引腳的 GPIO 中斷功能,等待 RXD 接收完成。
二、實例演示
UART深度休眠模式示例(傳輸時鐘為LSI)
程序運行一段時間后進入深度休眠模式,PC發(fā)送數(shù)據(jù)可喚醒MCU,喚醒后UART輪詢接收數(shù)據(jù),并存儲到TxRxBuffer緩沖區(qū),UART接收到'n'后不再接收數(shù)據(jù),然后將TxRxBuffer緩沖區(qū)中的數(shù)據(jù)回傳至PC。傳輸結(jié)束后,LED1閃爍5s,并再次進入深度休眠模式。
1.外設(shè)時鐘使能
void RCC_Configuration(void)
{
InitTick(8000000); //復(fù)位后延時
SysTickDelay(1000);
RCC_HSI_Enable(RCC_HSIOSC_DIV6); //SYSCLK = HSI = 8MHz = HCLK = PCLK
RCC_LSI_Enable();
RCC_AHBPeriphClk_Enable(DEBUG_UART_GPIO_CLK | RCC_AHB_PERIPH_GPIOC, ENABLE);
DEBUG_UART_APBClkENx(DEBUG_UART_CLK, ENABLE); //外設(shè)時鐘使能
}
2.配置GPIO
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
DEBUG_UART_AFTX; //UART TX RX 復(fù)用
DEBUG_UART_AFRX;
GPIO_InitStructure.Pins = DEBUG_UART_TX_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(DEBUG_UART_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pins = DEBUG_UART_RX_GPIO_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
GPIO_Init(DEBUG_UART_RX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pins = GPIO_PIN_3; //PC3 LED1
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init(CW_GPIOC, &GPIO_InitStructure);
PC03_SETLOW();
}
3.配置UART
void UART_Configuration(void)
{
UART_InitTypeDef UART_InitStructure = {0};
UART_InitStructure.UART_BaudRate = UARTyz_BaudRate; // 波特率
UART_InitStructure.UART_Over = UART_Over_sp; // 專用采樣
UART_InitStructure.UART_Source = UART_Source_LSI; // 傳輸時鐘源LSI
UART_InitStructure.UART_UclkFreq = UARTyz_UclkFreq; // 傳輸時鐘UCLK頻率
UART_InitStructure.UART_StartBit = UART_StartBit_FE; // 起始位判定方式
UART_InitStructure.UART_StopBits = UART_StopBits_1; // 停止位長度
UART_InitStructure.UART_Parity = UART_Parity_No ; // 校驗方式
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; // 發(fā)送/接收使能
UART_Init(DEBUG_UARTx, &UART_InitStructure);
}
4.配置低功耗模式
void PWR_Configuration(void)
{
PWR_InitTypeDef PWR_InitStructure = {0};//低功耗模式配置結(jié)構(gòu)體指針
PWR_InitStructure.PWR_Sevonpend = PWR_Sevonpend_Disable;
PWR_InitStructure.PWR_SleepDeep = PWR_SleepDeep_Enable; //Deep Sleep使能
PWR_InitStructure.PWR_SleepOnExit = PWR_SleepOnExit_Disable;
PWR_Config(&PWR_InitStructure);// 低功耗模式配置
}
void PWR_GotoLpmMode(void)//進入睡眠模式
{
__WFI();
}
5.配置NVIC中斷
void NVIC_Configuration(void)
{
NVIC_SetPriority(DEBUG_UART_IRQ, 0); //優(yōu)先級,無優(yōu)先級分組
NVIC_EnableIRQ(DEBUG_UART_IRQ); //UARTx中斷使能
}
void UART2_UART5_IRQHandler(void)
{
if(UART_GetITStatus(CW_UART5, UART_IT_RC) != RESET)
{
UART_ClearITPendingBit(CW_UART5, UART_IT_RC);
}
}
6.發(fā)送8位數(shù)組
void UART_SendBuf_Polling(UART_TypeDef* UARTx, uint8_t *TxBuf, uint8_t TxCnt)
{
while(TxCnt)
{
UART_SendData_8bit(UARTx, *TxBuf);
while(UART_GetFlagStatus(UARTx, UART_FLAG_TXE) == RESET);
TxBuf++;
TxCnt--;
}
while(UART_GetFlagStatus(UARTx, UART_FLAG_TXBUSY) == SET);
}
7.接收8位數(shù)組
uint8_t UART_RecvBuf_Polling(UART_TypeDef* UARTx, uint8_t *RxBuf)
{
uint8_t RxCnt = 0;
RxBuf[RxCnt] = UART_ReceiveData_8bit(UARTx);
RxCnt++;
do
{
while(UART_GetFlagStatus(UARTx, UART_FLAG_RC) == RESET); //等待RC
UART_ClearFlag(UARTx, UART_FLAG_RC); //清RC
if(UART_GetFlagStatus(UARTx, UART_FLAG_PE|UART_FLAG_FE)) //ERROR: PE or FE
{
UART_ClearFlag(UARTx, UART_FLAG_PE|UART_FLAG_FE);
RxCnt = 0x00;
}
else
{
RxBuf[RxCnt] = UART_ReceiveData_8bit(UARTx);
RxCnt++;
}
}
while(RxBuf[RxCnt-1] != 'n');
return RxCnt;
}
8.主程序
int32_t main(void)
{
RCC_Configuration();//配置RCC
GPIO_Configuration();//配置GPIO
UART_Configuration();//配置UART
PWR_Configuration();//配置低功耗模式
NVIC_Configuration();//配置NVIC
InitTick(HCLKFREQ); //初始化SysTick
RCC_WAKEUPCLK_Config(RCC_SYSCTRL_WAKEUPCLKDIS); //DeepSleep喚醒時,保持原系統(tǒng)時鐘來源
UART_SendString(DEBUG_UARTx, "rnCW32L083 UART DeepSleep mode LSE/LSIrn");
while(1)
{
//進入深度休眠模式
UART_SendString(DEBUG_UARTx, "rnEnter DeepSleep modern");
UART_SendString(DEBUG_UARTx, "rnPC send data to wake up MCUrn");
UART_ITConfig(DEBUG_UARTx, UART_IT_RC, ENABLE); //使能UARTx RC中斷
PWR_GotoLpmMode();
UART_ITConfig(CW_UART5, UART_IT_RC, DISABLE); //失能UARTx RC中斷
//喚醒后輪詢收發(fā)
TxRxBufferSize = UART_RecvBuf_Polling(DEBUG_UARTx, TxRxBuffer);
UART_SendBuf_Polling(DEBUG_UARTx, TxRxBuffer, TxRxBufferSize);
for(int i = 0; i10; i++) //閃燈
{
PC03_TOG();
SysTickDelay(500);
}
}
}
9.測試結(jié)果
結(jié)果顯示,通過PC發(fā)送123456后喚醒MCU, 喚醒后UART輪詢接收數(shù)據(jù),并存儲到TxRxBuffer緩沖區(qū),UART接收到'n'后不再接收數(shù)據(jù),然后將TxRxBuffer緩沖區(qū)中的數(shù)據(jù)回傳至PC收到123456。傳輸結(jié)束后,LED1閃爍5s,并再次進入深度休眠模式。
-
嵌入式
+關(guān)注
關(guān)注
5186文章
20153瀏覽量
328942 -
uart
+關(guān)注
關(guān)注
22文章
1304瀏覽量
106122 -
CW32
+關(guān)注
關(guān)注
1文章
281瀏覽量
1678
發(fā)布評論請先 登錄
CW32 UART低功耗模式詳解
CW32單片機UART低功耗模式的介紹
使用芯源CW32 MCU來實現(xiàn)低功耗模式下的RTC定時喚醒功能
【應(yīng)用筆記】CW32 自舉程序中使用的 ISP 協(xié)議
CW32單片機在智能馬桶的應(yīng)用介紹
基于低功耗32位MCU CW32系列的智能溫控器的應(yīng)用

CW32 UART低功耗模式介紹
評論