STM32F429(ucosiii)低功耗停止模式(TFT屏及4按键唤醒)

STM32F429(ucosIII)-低功耗停止模式下系列问题记录

1. 需解决的目标:

a. 将手持设备在不使用的情况下从200ma降低到40ma左右,从而提高手持设备的使用时长,超过24小时

2. 实现方式

a.查看stm32的电气手册,看在最大的168M主频下能达到多小的理论电流(详细见文章最底下),并进行实验。
b.通过ucosiii起一个任务进行设备状态的监测,当监测到设备出现熄屏的状态,进入低功耗模式-停止模式,降低使用功耗。
c.进入低功耗前关闭ADC(用的AD1),唤醒后初始化ADC,大概节省了3MA左右.
d.其他的GPIO优化,这个优化之后发现,基本没什么变化。存疑:这个可能对于MA级别的。

3. 调试验证的方式

a.如何知道进入了停止模式:
进入debug模式下
查看PWR的标志位状态,如下两图已进入停止模式
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200717162850924.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200717162916801.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xzaDEzNzI2Mjk2NTg3,size_16,color_FFFFFF,t_70#pic_center)
查看调试断点如下跑到函数
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
的下面,如果跑到下面说明被唤醒了。如果没有基本说明MCU处于停止模式。需要注意的是需要添加以下函数进行调试,否则有时会出现调试过程断开的现象。DBGMCU_Config(DBGMCU_STOP,ENABLE);


b.低功耗模式-停止模式-TFT(ILI9341)唤醒
可以通过23个EXTI的外部中断进行唤醒,我使用4个外部的按键GPIO,并配置成外部中断进行处理
***注意: 要进入停止模式,所有 EXTI 线挂起位(在挂起寄存器 (EXTI_PR)
中)、 RTC 闹钟(闹钟 A 和闹钟 B)、 RTC 唤醒、 RTC 入侵和 RTC 时间
戳标志必须复位。否则将忽略进入停止模式这一过程,继续执行程序。(来自于手册)***

4. 代码

(1)ucosIII起一个任务进行守护,未标明的均用的STM库的函数

/*
********************************************************************************
* @function : static void AppTaskLowPower(void *p_arg)
* @brief    : 低功耗模式
* @param    : p_arg 是在创建该任务时传递的形参
* @return   : 0
********************************************************************************
*/
static void AppTaskUserLowPower(void *p_arg){

	
	(void)p_arg;
	OS_ERR p_err;
	OS_ERR err;


	while(1){
		//KEY_DEBUG(getDebugLever(), DBG_WARN, "AppTaskUserLowPower线程");
		if(LcdOffFlag == 1 && getComStatus() == FALSE ){
			OSSchedLock(&p_err);//禁止任务调度
			
			//关闭滴答计数器
			SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
			RTC_AlarmCmd(RTC_Alarm_A,DISABLE);
			RTC_AlarmCmd(RTC_Alarm_B,DISABLE);
			RTC_WakeUpCmd(DISABLE);
			RTC_TimeStampCmd(RTC_TimeStampEdge_Rising,DISABLE);
			RTC_TimeStampCmd(RTC_TimeStampEdge_Falling,DISABLE);
			RTC_TamperCmd(RTC_Tamper_1,DISABLE);
			//关闭ADC,和DAC
			ADC_Cmd(ELE_QUANTITY_ADC, DISABLE);  
			//控制FLASH是进入掉电状态还是正常供电状态
			PWR_FlashPowerDownCmd(ENABLE);

			LCD_SLEEP_Mode(TRUE);//ILI9341进入睡眠模式
			
			//进入低功耗停止模式
			PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
			
			//重新初始化系统时钟及GPIO
			SystemInit();
			
			SystemCoreClockUpdate();	                                                //根据PLL配置更新系统时钟频率变量 SystemCoreClock
			LcdOffFlag = 0;
			
			TFTLCD_Init_after_stop();                                                  //初始化LCD
			
			TIM_SetTIM3Compare4(systemParam[backlightLevel].value);                    	//背光占空比调节
			ADC_Cmd(ELE_QUANTITY_ADC, ENABLE);
			BSP_Tick_Init();                                                            //初始化系统滴答时钟做为uCOS-II的系统时钟节拍,1ms一次

			bsp_DelayUS(200000);       //Delay 200ms
			OSSchedUnlock(&p_err);//允许任务调度 
		}
		OSTimeDly(500, OS_OPT_TIME_DLY, &err);
	}
}

(2)外设TFT屏驱动芯片ILI9341进入睡眠模式。

void LCD_SLEEP_Mode(BOOLEAN state){
	if(state){
		LCD_WriteCommand(LCD_SLEEP_IN);
		delay_ms(20);
		LCD_WriteCommand(LCD_DISPLAY_OFF);
	}
	else{
		LCD_WriteCommand(LCD_SLEEP_OUT);
		delay_ms(120);
		LCD_WriteCommand(LCD_DISPLAY_ON);
	}
}

(3)外设TFT屏驱动芯片ILI9341退出睡眠模式

/**
 * @brief  Initializes the LCD after stop.
 * @param  None
 * @retval None
 */
void TFTLCD_Init_after_stop(void)
{
	LTDC_InitTypeDef LTDC_InitStruct;
	
	LCD_SLEEP_Mode(FALSE);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_LTDC, ENABLE); /* Enable the LTDC Clock */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE); /* Enable the DMA2D Clock */

	LCD_GPIO_Config();	/* Configure the LCD Control pins */

    g_LcdHeight = LCD_PIXEL_HEIGHT;
    g_LcdWidth  = LCD_PIXEL_WIDTH;
    HSYNC_W     = LCD_HSW;
    VSYNC_W     = LCD_VSW;
    HBP         = LCD_HBP;
    HFP         = LCD_HFP;
    VBP         = LCD_VBP;
    VFP         = LCD_VFP;

	//LTDC配置
	LTDC_InitStruct.LTDC_HSPolarity = LTDC_HSPolarity_AL;									//水平同步极性
	LTDC_InitStruct.LTDC_VSPolarity = LTDC_VSPolarity_AL;									//垂直同步极性
	LTDC_InitStruct.LTDC_DEPolarity = LTDC_DEPolarity_AL;									//数据使能极性
	LTDC_InitStruct.LTDC_PCPolarity = LTDC_PCPolarity_IPC;									//像素时钟极性
	#if 0
	LTDC_InitStruct.LTDC_HorizontalSync = HSYNC_W - 1;											//水平同步宽度
	LTDC_InitStruct.LTDC_VerticalSync   = VSYNC_W - 1;											//垂直同步宽度
	LTDC_InitStruct.LTDC_AccumulatedHBP = HSYNC_W + HBP - 1;										//水平同步后沿宽度
	LTDC_InitStruct.LTDC_AccumulatedVBP = VSYNC_W + VBP - 1;										//垂直同步后沿高度
	LTDC_InitStruct.LTDC_AccumulatedActiveW = HSYNC_W + HBP + g_LcdWidth - 1;					//有效宽度
	LTDC_InitStruct.LTDC_AccumulatedActiveH = VSYNC_W + VBP + g_LcdHeight - 1;					//有效高度
	LTDC_InitStruct.LTDC_TotalWidth = HSYNC_W + HBP + LCD_PIXEL_WIDTH + HFP - 1; 					//总宽度
	LTDC_InitStruct.LTDC_TotalHeigh = VSYNC_W + VBP + LCD_PIXEL_HEIGHT + VFP - 1;					//总高度
	LTDC_InitStruct.LTDC_BackgroundRedValue   = 0;							//屏幕背景层红色部分
	LTDC_InitStruct.LTDC_BackgroundGreenValue = 0;							//屏幕背景层绿色部分
	LTDC_InitStruct.LTDC_BackgroundBlueValue  = 0;							//屏幕背景色蓝色部分
    #else
    LTDC_InitStruct.LTDC_HorizontalSync = HSYNC_W;
	LTDC_InitStruct.LTDC_VerticalSync = VSYNC_W;
	LTDC_InitStruct.LTDC_AccumulatedHBP = LTDC_InitStruct.LTDC_HorizontalSync + HBP;
	LTDC_InitStruct.LTDC_AccumulatedVBP = LTDC_InitStruct.LTDC_VerticalSync + VBP;
	LTDC_InitStruct.LTDC_AccumulatedActiveW = g_LcdWidth + LTDC_InitStruct.LTDC_AccumulatedHBP;
	LTDC_InitStruct.LTDC_AccumulatedActiveH = g_LcdHeight + LTDC_InitStruct.LTDC_AccumulatedVBP;
	LTDC_InitStruct.LTDC_TotalWidth = LTDC_InitStruct.LTDC_AccumulatedActiveW + HFP;
	LTDC_InitStruct.LTDC_TotalHeigh = LTDC_InitStruct.LTDC_AccumulatedActiveH + VFP;
	/* 背景色 */
	LTDC_InitStruct.LTDC_BackgroundRedValue = 0xff;
	LTDC_InitStruct.LTDC_BackgroundGreenValue = 0;
	LTDC_InitStruct.LTDC_BackgroundBlueValue = 0;
    #endif
	/* 配置 PLLSAI 分频器,它的输出作为像素同步时钟CLK*/
	/* PLLSAI_VCO 输入时钟 = HSE_VALUE/PLL_M = 1 Mhz */
	/* PLLSAI_VCO 输出时钟 = PLLSAI_VCO输入 * PLLSAI_N = 384 Mhz */
	/* PLLLCDCLK = PLLSAI_VCO 输出/PLLSAI_R = 384/4  Mhz */
	/* LTDC 时钟频率 = PLLLCDCLK / DIV = 384/4/4 = 24 Mhz */
	/* LTDC时钟太高会导花屏,若对刷屏速度要求不高,降低时钟频率可减少花屏现象*/
	/* 以下函数三个参数分别为:PLLSAIN,PLLSAIQ,PLLSAIR,其中PLLSAIQ与LTDC无关*/
	//设置像素时钟 6.35Mhz 
	//CLK=1M*288/4/2/4
	RCC_PLLSAIConfig(192, 7, 4);
 	/*以下函数的参数为DIV值*/
	RCC_LTDCCLKDivConfig(RCC_PLLSAIDivR_Div8);
	/* Enable PLLSAI Clock */
	RCC_PLLSAICmd(ENABLE);
	/* Wait for PLLSAI activation */
	while(RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) == RESET)
	{
	}

	LTDC_Init(&LTDC_InitStruct);
	LTDC_ReloadConfig(LTDC_SRCR_IMR);
}	

(4)4个按键外部中断配置(PF6,PF7,PF8,PF9)

void EXTI9_5_IRQHandler(void)
{
	OSIntEnter();
    if (EXTI_GetITStatus(EXTI_Line6) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line6);//清除标志
    }
	if (EXTI_GetITStatus(EXTI_Line7) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line7);//清除标志
    }
	if (EXTI_GetITStatus(EXTI_Line8) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line8);//清除标志
    }
	if (EXTI_GetITStatus(EXTI_Line9) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_Line9);//清除标志
    }
	OSIntExit();
}

5. 参考资料

a.《dm00287603-lcdtft-display-controller-ltdc-on-stm32-mcus-stmicroelectronics.pdf》这个是中文版的,来源于ST官网
b.《DM00031020_ENV18.pdf》来源于ST官网
c.参考的链接:
[https://www.cnblogs.com/firege/p/9435593.html](https://www.cnblogs.com/firege/p/9435593.html)-----强烈推荐,从原理到源码扫盲
[https://www.cnblogs.com/firege/p/5806040.html](https://www.cnblogs.com/firege/p/5806040.html)-----同上
[https://www.st.com/content/st_com/zh/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f4-series/stm32f429-439.html#products](https://www.st.com/content/st_com/zh/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-high-performance-mcus/stm32f4-series/stm32f429-439.html#products)官网F429提供的各种库和资料
d.《datasheet-STM32F429.pdf》来源于datasheet网站

6. 调试问题及回顾

a.低功耗模式-停止模式MDK5.22下的调试。

b.低功耗模式-停止模式,TFT屏(ILI9341)唤醒后随机性出现屏幕裂纹。
在唤醒的初始化过程中,由于对ILI9341不太熟悉,因此直接使用了开机的初始化过程(复位LCD→初始化SPI→发送ILI9341的所有配置相关参数→PWM初始化→通过PWM控制背光打开)。直接在唤醒时调用,导致出现TFT存在屏幕裂纹(并非撕裂现象),该裂纹在设备断电的状态下依然存在,但慢慢地会消失。咨询相关厂家后,答复液晶有可能被极化,最后也没解决,有这方面的牛人交流交流。最后曲线救国,深入了解ILI9341的指令集,发现有熄屏和睡眠的模式,详细见上面代码。通过不用初始化的方式进行控制(F429进入停止模式之前通过SPI关闭TFT:ILI9341关屏→ILI9341进行睡眠模式;F429唤醒之后,通过SPI退出ILI9341睡眠模式→ILI9341开屏 )

c.通过第1和第2个连接并结合MDK进行数据的监测,通过逻辑分析仪监测ILI9341的同步时序判断。

d.实测的电流45ma,与官网的电气手册在低功耗停止模式下的电量有差距,这估计也是因为我们的STM32F429各个引脚的电路有关系,这部分未进行实测,待进行深入实验。

7. 手册截图

a.运行模式的电流大小:
STM32F429(ucosiii)低功耗停止模式(TFT屏及4按键唤醒)_第1张图片
STM32F429(ucosiii)低功耗停止模式(TFT屏及4按键唤醒)_第2张图片
b.低功耗睡眠模式下的功耗
STM32F429(ucosiii)低功耗停止模式(TFT屏及4按键唤醒)_第3张图片
c.低功耗停止模式下的功耗
STM32F429(ucosiii)低功耗停止模式(TFT屏及4按键唤醒)_第4张图片
d.低功耗待机模式下的功耗
STM32F429(ucosiii)低功耗停止模式(TFT屏及4按键唤醒)_第5张图片

你可能感兴趣的:(嵌入式,stm32,嵌入式)