FM33G0系列之低功耗

五、FM33G0系列之低功耗
复旦微芯片,低功耗模式有两种,一种是只内核休眠,一种是芯片完全休眠(内核+外设)。前者运行状态和进入低功耗状态的电流,差别不是很大,1mA以内,使用12v电压,总体不到10mW。其好处是,在唤醒时可以使用普通串口发送字节唤醒。芯片完全休眠,在deepsleep模式下,普通串口无法使用,仅低功耗串口可使用,所以可通过低功耗串口进行单字节唤醒。芯片完全休眠的电流应该会比只内核休眠低很多,但缺陷是低功耗串口在该模式下只能支持到最高 9600 波特率的数据接收。如果使用115200波特率进行通讯,有两种方法,其一是休眠模式为仅内核休眠,使用普通串口进行唤醒;其二是在休眠前将低功耗串口的波特率修改为9600,唤醒之后,再改为115200波特率。当然这是针对使用串口发送字节的方式进行唤醒,还有其他的方式进行唤醒,比如外部中断按键等,官方手册上也有说明。
这一节,主要针对内核休眠+普通串口唤醒,以及低功耗串口来说明。至于修改波特率方法,理论上是可行的,但我没测试过。

1、仅内核休眠,我将休眠函数和中断中唤醒字节的相关代码贴上来

void Core_Sleep(void)
{
	//配置秒中断进行清狗操作
	RCC_PERCLK_SetableEx(RTCCLK, ENABLE);		//RTC总线使能
	RTC_RTCIE_SetableEx(DISABLE, 0xFFFFFFFF);//关闭所有RTC中断
	RTC_RTCIE_SetableEx(ENABLE, RTC_RTCIE_SEC_IE_Msk);//打开RTC秒中断
	RTC_RTCIF_ClrEx(RTC_RTCIE_SEC_IE_Msk);	//清除RTC秒中断标志	
	
	NVIC_ClearPendingIRQ(RTC_IRQn);	
	NVIC_DisableIRQ(RTC_IRQn);
	NVIC_SetPriority(RTC_IRQn,1);        //休眠期间RCC的中断优先级低于唤醒排第二。
	NVIC_EnableIRQ(RTC_IRQn);
	
	RCC_SYSCLKSEL_LPM_RCLP_OFF_Setable(ENABLE);      //休眠前关闭 RCLP
	RCC_PERCLK_SetableEx( PDCCLK, 		DISABLE );		//IO控制时钟寄存器使能关闭
	ANAC_ADCCON_ADC_EN_Setable(DISABLE);           //关闭ADC使能
	ANAC_ADCINSEL_BUFEN_Setable(DISABLE);         //关闭ADC buffer 
	while(1)
	{
	   SCB->SCR=0;     //Sleep/deepsleep;  RTCBKP: SCB->SCR=0x04(1<<2);
	   IWDT_Clr();
	   __WFI();
     IWDT_Clr();
		if(WakeFlag==1)
		{
			Enter_LowpowerMs=0;                             //进入低功耗计数清零			
			RTC_RTCIE_SetableEx(DISABLE, 0xFFFFFFFF);       //关闭所有RTC中断		
			RCC_PERCLK_SetableEx(RTCCLK, DISABLE);          //关闭RTC总线使能	
			RCC_PERCLK_SetableEx( PDCCLK, 		ENABLE );		  //IO控制时钟寄存器使能
    //      IWDT_IWDTCFG_IWDTOVP_Set(IWDT_IWDTCFG_IWDTOVP_2s);//配置IWDT溢出周期			                           //重新设置系统看门狗		其实唤醒之后清狗溢出周期会自动设置			                              		
		    break;
		}
	}		
}

//串口0进行休眠唤醒
void UART0_IRQHandler(void)
{
	uint08 tmp08;
	//接收中断处理
	if((ENABLE == UART_UARTIE_RxTxIE_GetableEx(UART0, RxInt))
		&&(SET == UART_UARTIF_RxTxIF_ChkEx(UART0, RxInt)))
	{
		//中断转发接收到的数据
		ReadUart0_char = UARTx_RXREG_Read(UART0);//接收中断标志仅可通过读取rxreg寄存器清除
		if((ReadUart0_char==0xA5)&&( Enter_LowpowerMs == TIME_MS_ENTERLOWPOWER ))
		{
			WakeFlag=1;
		}
		Uart0RcvFlag = 1;	
	}
	
	//发送中断处理
	if((ENABLE == UART_UARTIE_RxTxIE_GetableEx(UART0, TxInt))
		&&(SET == UART_UARTIF_RxTxIF_ChkEx(UART0, TxInt)))
	{
		//发送中断标志可通过写txreg寄存器清除或txif写1清除
		//发送指定长度的数据
		if(UARTxOp[0].TxOpc < UARTxOp[0].TxLen)
		{
			UARTx_TXREG_Write(UART0, UARTxOp[0].TxBuf[UARTxOp[0].TxOpc]); //发送一个数据
			UARTxOp[0].TxOpc++;
		}
		else
		{
			UART_UARTIE_RxTxIE_SetableEx(UART0, TxInt, DISABLE);       //接收 发送 中断失能配置函数   
		}
		UART_UARTIF_RxTxIF_ClrEx(UART0);	                          //清除发送中断标志
	}
}

当外部发送单字节数据时会进入到串口中断中,中断跳出来后会在休眠函数里面的while循环继续运行,遇到break,跳出休眠函数,回到主函数,或者执行其外部操作。

2、外设休眠+内核休眠,需低功耗串口唤醒

void Sleep(void)
{
	PMU_SleepCfg_InitTypeDef SleepCfg_InitStruct;	
	 __disable_irq();		//关闭全局中断使能
	 IWDT_Clr();	
	
	//设置休眠相关配置
	SWD_IO_PullUp(ENABLE);		                    //打开SWDTCK,SWDTDO上拉使能
	ANAC_SVDCON_SVDEN_Setable(DISABLE);
	ANAC_BORCON_OFF_BOR_Setable(ENABLE);
	RCC_SYSCLKSEL_LPM_RCLP_OFF_Setable(ENABLE);   	//关闭rclp 0.2uA
  ANAC_ADCCON_ADC_EN_Setable(DISABLE);              //关闭ADC
	ANAC_ADCINSEL_BUFEN_Setable(DISABLE);

	SleepCfg_InitStruct.PMOD = PMU_LPMCFG_PMOD_SLEEP;			//功耗模式配置
	SleepCfg_InitStruct.SLPDP = PMU_LPMCFG_SLPDP_DEEPSLEEP;			//DeepSleep控制
	SleepCfg_InitStruct.CVS = DISABLE;							//内核电压降低控制
	SleepCfg_InitStruct.XTOFF = PMU_LPMCFG_XTOFF_DIS;			//保持XTLF
	SleepCfg_InitStruct.SCR = 0;								//M0系统控制寄存器
	
	PMU_SleepCfg_Init(&SleepCfg_InitStruct);//休眠配置
	
	IWDT_Clr();	
	__WFI();//进入休眠
	IWDT_Clr();
	__enable_irq();
}

下一节我把低功耗串口也总结了吧,顺便说一说我在使用低功耗串口的时候遇到的问题。

你可能感兴趣的:(复旦微国产化FMG0系列开发板,单片机,嵌入式)