MM32W無線MCU系列產(chǎn)品應(yīng)用筆記 —— 低功耗BLE藍(lán)牙應(yīng)用
在上一章節(jié),我們了解了MM32W0系列藍(lán)牙模塊的軟件架構(gòu),下面我們來看一下低功耗模式下用到的休眠和時鐘配置函數(shù)。
目前MM32W0系列有n4和q1兩個版本,n4主要針對需要大容量的應(yīng)用方案,q1針對超低功耗精簡型的應(yīng)用方案,兩個型號的低功耗編程操作方式相同,不同的只是MCU的時鐘系統(tǒng)控制方式,在參考程序已經(jīng)提供不同的模式下功能,用戶只要改變相對應(yīng)的宏定義即可實現(xiàn)對應(yīng)的低功耗功能。
休眠函數(shù)
對于低功耗應(yīng)用來說,休眠是非常關(guān)鍵的一個功能。開啟藍(lán)牙廣播時MM32W0的控制模塊有三種工作模式:正常模式、睡眠模式和停機(jī)模式。在stop模式下,射頻模塊都會通過IRQ引腳定時觸發(fā)一個外部中斷,可以借此喚醒STOP模式中的控制模塊。
在阻塞模式中,休眠是藍(lán)牙服務(wù)通過調(diào)用void McuGotoSleepAndWakeup(void) 函數(shù)實現(xiàn)的,對于中斷模式,則是用戶在代碼中主動調(diào)用IrqMcuGotoSleepAndWakeup()函數(shù)來實現(xiàn)。
void McuGotoSleepAndWakeup(void) // auto goto sleep AND wakeup, porting api
{
if ((SleepStop)&& //開啟休眠功能
(TxTimeout < SysTick_Count)&&
(RxTimeout < SysTick_Count)) //UART無收發(fā)數(shù)據(jù)
{
if(SleepStop == 1){ //SLEEP
SCB->SCR &= 0xfb;
__WFE();
}else{ //STOP
SysClk48to8(); //HSI 6分頻
SCB->SCR |= 0x4;
__WFI(); //進(jìn)入STOP模式
RCC->CR|=RCC_CR_HSION; //從STOP模式喚醒,使能時鐘
SysClk8to48(); //PLL倍頻至48MHz
}
}
}
void IrqMcuGotoSleepAndWakeup(void) // auto goto sleep AND wakeup, porting api
{
if(ble_run_interrupt_McuCanSleep() == 0) return;
#ifdef USE_UART
if ((SleepStop)&&
(TxTimeout < SysTick_Count)&&
(RxTimeout < SysTick_Count))
{
if(SleepStop == 1){ //sleep
SleepStatus = 1;
SCB->SCR &= 0xfb;
__WFE(); //控制模塊進(jìn)入睡眠模式
}else{ //stop
SleepStatus = 2;
SysClk8M();
SCB->SCR |= 0x4;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
__WFI();
}
}
#endif
}
在中斷方式中,需要在中斷處理函數(shù)中重新配置時鐘:
void EXTI4_15_IRQHandler(void)
{
EXTI_ClearITPendingBit(EXTI_Line8);
if(2 == SleepStatus){ //stop
RCC->CR|=RCC_CR_HSION; //HSI使能
RCC->CR |= RCC_CR_PLLON; //PLL使能
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
SysTick_Config(48000);
}
SleepStatus = 0;
ble_run(0);
}
時鐘配置
進(jìn)入低功耗前后需要配置時鐘,從低功耗模式恢復(fù)時,時鐘默認(rèn)設(shè)置為HSI6分頻,需要重新配置系統(tǒng)時鐘。
注意:下面函數(shù)屬于藍(lán)牙庫接口,沒有用到也不要刪除。
相關(guān)時鐘配置:
void SysClk48to8(void)1
{
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);//selecting PLL clock as sys clock
while (RCC_GetSYSCLKSource() != 0x0)
{}
RCC->CR &=~(RCC_CR_PLLON); //clear PLL
SysTick_Config(8000);
}
void SysClk8to48(void) //從STOP模式中恢復(fù)
{
SetSysClock_HSI(4);//HSI:12*4=48M
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//selecting PLL clock as sys clock
while (RCC_GetSYSCLKSource() != 0x08)
{}
SysTick_Config(48000);
}
void SetSysClock_HSI(u8 PLL) //重新配置HSI和PLL
{
unsigned char temp=0;
RCC->CR|=RCC_CR_HSION;
while(!(RCC->CR&RCC_CR_HSIRDY));
RCC->CFGR=RCC_CFGR_PPRE1_2; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
RCC->CFGR&=~RCC_CFGR_PLLSRC; //PLLSRC ON
RCC->CR &=~(RCC_CR_PLLON);
RCC->CR &=~(0x1f<<26); //clear PLL
RCC->CR|=(PLL - 1) << 26; //setting PLL value 2~16
FLASH->ACR=FLASH_ACR_LATENCY_1|FLASH_ACR_PRFTBE; //FLASH 2 delay clk cycles
RCC->CR|=RCC_CR_PLLON; //PLLON
while(!(RCC->CR&RCC_CR_PLLRDY));//waiting for PLL locked
RCC->CFGR&=~RCC_CFGR_SW;
RCC->CFGR|=RCC_CFGR_SW_PLL;//PLL to be the sys clock
while(temp!=0x02) //waiting PLL become the sys clock
{
temp=RCC->CFGR>>2;
temp&=0x03;
}
}
以上時鐘配置只是針對MM32W0系列的n4版本,在q1版不需要以上時鐘操作。MM32W051PFB(q1)藍(lán)牙功耗參數(shù):
在SleepStop設(shè)置成0x02,MCU將會進(jìn)入STOP模式,在保持 SRAM 和寄存器內(nèi)容不丟失的情況下,停機(jī)模式可以達(dá)到最低的電能消耗。在停機(jī)模式下,HSI 的振蕩器和 HSE 晶體振蕩器被關(guān)閉?梢酝ㄟ^任一配置成 EXTI 的信號或者看門狗不復(fù)位方式把微控制器從停機(jī)模式中喚醒,EXTI 信號可以是 16 個外部 I/O 口之一、 PVD 的輸出的喚醒信號。。STOP模式下無法下載調(diào)試程序。為了方便調(diào)試,可以在程序開始時加入一個延時,這樣每次復(fù)位都有一段時間可以下載程序。
編輯:admin 最后修改時間:2019-06-15