STM32入门教程(PWR电源控制篇)

重要的内容写在前面:

  1. 该系列是以up主江协科技的STM32视频教程为基础写下去的,大部分内容都参考了老师的课件,对于一些个人认为比较重要但是老师仅口述的部分,笔者都有用文字的方式记录并标出了重点。
  2. 文中的图片基本都来源于老师的课件以及开发板和芯片的手册,粘贴过来是为了方便阅读。
  3. 如果有条件的可以先学习一些相关课程再去看STM32的教程,学起来会更加轻松(不太建议零基础开始直接STM32,听起来可能会有点困难,可以先学51单片机),相关课程有数字电路(强烈推荐先学数电,不然可能会有很多地方理解起来很困难)、模拟电路、计算机组成原理(像寄存器、存储器、中断等在这门课里有很详细的介绍)、计算机网络等。
  4. 如有错漏欢迎指出。

视频链接:[13-1] PWR电源控制_哔哩哔哩_bilibili

1、PWR(Power Control)电源控制:

(1)PWR负责管理STM32内部的电源供电部分,可以实现可编程电压监测器和低功耗模式的功能。

(2)可编程电压监测器(PVD)可以监控VDD电源电压,当VDD下降到PVD阀值以下或上升到PVD阀值之上时,PVD会触发中断,用于执行紧急关闭任务。

(3)低功耗模式包括睡眠模式(Sleep)、停机模式(Stop)和待机模式(Standby),可在系统空闲时,降低STM32的功耗,延长设备使用时间

2、电源框图:

(1)VDDA供电区域是模拟供电区域(其中A/D转换器还有两个提供参考电压的引脚VREF);VDD供电区域和1.8V供电区域是数字供电区域,cpu核心、存储器和内置数字外设属于1.8V供电区域,1.8V电压由电压调节器提供,提供较低电压的目的是为了降低功耗。

(2)后备供电区域前有一个低电压检测器控制VBAT的开关,当VDD通电时后备供电区域由VDD供电,当VDD没有通电时后备供电区域由VBAT供电(RTC时钟源选择LSE的话,当VDD掉电时,RTC和LSE由VBAT供电,RTC仍能正常工作)。

3、上电复位和掉电复位:

当VDD或者VDDA过低时,内部电路直接产生复位信号(低电平有效),是否产生复位信号的界限之间有40mV的迟滞电压,电压从低到高时需要高于上限POR(Power On Reset)才会解除复位,电压从高到低时需要低于下限PDR(Power Down Reset)才会复位,这是为了防止电压在某个阈值附近抖动从而造成复位信号的抖动。

4、可编程电压监测器:

PVD输出的上升沿或下降沿可以触发中断(通过外部中断实现),另外与“上电复位和掉电复位”不同的是,PVD阈值可以通过程序进行设定。

5、低功耗模式:

6、模式选择:执行WFI(Wait For Interrupt)或者WFE(Wait For Event)指令后,STM32进入低功耗模式

(1)睡眠模式:

如果SLEEPDEEP=0,执行完WFI/WFE指令后,STM32进入睡眠模式,程序暂停运行,唤醒后程序从暂停的地方继续运行

②SLEEPONEXIT位决定STM32执行完WFI或WFE后,是立刻进入睡眠,还是等STM32从最低优先级的中断处理程序中退出时进入睡眠。

③在睡眠模式下,所有的I/O引脚都保持它们在运行模式时的状态

WFI指令进入睡眠模式,可被任意一个NVIC响应的中断唤醒

WFE指令进入睡眠模式,可被唤醒事件唤醒

(2)停机模式:

如果SLEEPDEEP=1、PDDS=0,执行完WFI/WFE指令后,STM32进入停机模式,程序暂停运行,唤醒后程序从暂停的地方继续运行

②如果LPDS=0,停机模式下电压调节器开启;如果LPDS=1,停机模式下电压调节器处于低功耗状态(更省电,但是唤醒延迟更高)。

1.8V供电区域的所有时钟都被停止,PLL、HSI和HSE被禁止,SRAM和寄存器内容被保留下来

④在停机模式下,所有的I/O引脚都保持它们在运行模式时的状态

当一个中断或唤醒事件导致退出停机模式时,HSI被选为系统时钟(唤醒STM32后需要将系统时钟选择回HSE,以配置主频为原本的72MHz)

WFI指令进入停机模式,可被任意一个EXTI中断唤醒

WFE指令进入停止模式,可被任意一个EXTI事件唤醒

(3)待机模式:

如果SLEEPDEEP=1、PDDS=1,执行完WFI/WFE指令后,STM32进入待机模式,唤醒后程序从头开始运行

整个1.8V供电区域被断电,PLL、HSI和HSE也被断电,SRAM和寄存器内容丢失,只有备份的寄存器和待机电路维持供电

在待机模式下,所有的I/O引脚变为高阻态(浮空输入)

WKUP引脚的上升沿、RTC闹钟事件的上升沿、NRST引脚上外部复位、IWDG复位,四个条件满足其中一个,退出待机模式

7、修改主频:

(1)按照下图所示接好电路,并将OLED显示屏的项目文件夹复制一份作为模板使用。

(2)system_stm32f10x.h文件和system_stm32f10x.c文件用于配置RCC时钟树,如果想要修改系统主频,可以在system_stm32f10x.c文件中找到红框所在位置,目前蓝框框选的就是配置系统主频为72MHz的宏定义,将该宏定义注释后解除橙框内的其中一个宏定义就可修改主频。(F103C8T6是MD、中容量、非超值系列,图中107、108两行代码在预编译的时候会被移除,不用理会)

(3)在main.c文件中粘贴以下代码,然后编译,将程序下载到开发板中观察OLED屏的显示。(需要更改系统主频,反复编译,对比修改主频前后的区别)

#include "stm32f10x.h"                  // Device headerCmd
#include "OLED.h"
#include "Delay.h"

int main()
{
	OLED_Init();
	
	OLED_ShowString(1,1,"SYSCLK:");
	OLED_ShowNum(1,8,SystemCoreClock,8);  //显示当前主频
	
	while(1)
	{
		//闪烁显示
		OLED_ShowString(2,1,"Running");
		Delay_ms(500);  //500个时间单位
		OLED_ShowString(2,1,"       ");
		Delay_ms(500);  //500个时间单位
	}
}

8、模式选择睡眠模式:

(1)按照下图所示接好电路,并将串口发送+接收的项目文件夹复制一份作为模板使用。

(2)在main.c文件中粘贴以下代码,然后编译,将程序下载到开发板中进行调试,使用串口助手向单片机发送数据,每发送一次数据,OLED屏闪烁显示一次“Running”。

#include "stm32f10x.h"                  // Device headerCmd
#include "OLED.h"
#include "Serial.h"
#include "Delay.h"

uint8_t RxData ;

int main()
{
	OLED_Init();
	Serial_Init();
	
	OLED_ShowString(1, 1, "RxData:");
	
	while(1)
	{
		if(Serial_GetRxFlag() == 1)  //判断是否有新数据到来
		{
			RxData = Serial_GetRxData();  //把接收的新数据拷贝到RxData中
			Serial_SendByte(RxData);      //把接收到的数据传给电脑
			//(调试时注意选择HEX模式进行发送和接收)
			OLED_ShowHexNum(1, 8, RxData, 2);
		}
		OLED_ShowString(2,1,"Running");
		Delay_ms(500);  //500个时间单位
		OLED_ShowString(2,1,"       ");
		Delay_ms(500);  //500个时间单位
		
		__WFI();   //进入睡眠模式(中断唤醒)
		//默认SLEEPDEEP=0(立刻睡眠)
	}
}

(3)程序解释:将程序下载到开发板后,程序很快来到“__WFI();”,这时STM32进入睡眠模式,程序停止运行,如果使用串口助手向STM32发送数据,那么就会触发一次中断,STM32从睡眠模式中被唤醒,首先会执行串口的中断函数完成数据的接收,接着程序从“__WFI();”语句的下一步——判断是否有新数据到来开始执行,本例中100%有新数据到来,所以OLED屏会显示刚刚发送的HEX格式数据,接着“Running”闪烁显示1次,程序来到“__WFI();”,再次进入睡眠模式。

9、模式选择停机模式:

(1)按照下图所示接好电路,并将对射式红外传感器计次的项目文件夹复制一份作为模板使用。

(2)在stm32f10x_pwr.h文件中有PWR模块相关的函数。

[1]PWR_DeInit函数:恢复缺省配置。

[2]PWR_BackupAccessCmd函数:使能对后备区域的访问。

[3]PWR_PVDCmd函数:使能PVD输出。

[4]PWR_PVDLevelConfig函数:配置PVD的阈值电压。

[5]PWR_WakeUpPinCmd函数:使能位于PA0位置的WKUP引脚(配合待机模式使用)。

[6]PWR_EnterSTOPMode函数:使STM32进入停止模式。

[7]PWR_EnterSTANDBYMode函数:使STM32进入待机模式。

[8]PWR_GetFlagStatus函数:获取标志位。

[9]PWR_ClearFlag函数:清除标志位。

(3)在main.c文件中粘贴以下代码,然后编译,将程序下载到开发板中进行调试。(每挡一次光就产生一次外部中断STM32就会从停机模式中被唤醒,处理完中断后程序从“SystemInit();”语句开始执行)

#include "stm32f10x.h"                  // Device headerCmd
#include "OLED.h"
#include "CountSensor.h"
#include "Delay.h"

int main()
{
	OLED_Init();
	CountSensor_Init();
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);  //开启PWR的时钟
	
	OLED_ShowString(1,3,"Count:"); 
	
	while(1)
	{
		OLED_ShowNum(2,3,CountSensor_Get(),3);  //显示挡光次数
		
		OLED_ShowString(3,1,"Running");
		Delay_ms(500);  //500个时间单位
		OLED_ShowString(3,1,"       ");
		
		PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI);  //进入停机模式
		//PWR_Regulator_ON:电压调节器开启
		//PWR_STOPEntry_WFI:可被任意一个EXTI中断唤醒
		
		//唤醒STM32后需要将系统时钟选择回HSE
		SystemInit();
	}
}

10、模式选择待机模式:

(1)按照下图所示接好电路,并将实时时钟的项目文件夹复制一份作为模板使用。

(2)在main.c文件中粘贴以下代码,然后编译,将程序下载到开发板中进行调试。

闹钟事件会在程序下载完成后的第10秒发生,这时STM32从待机模式中被唤醒,由于RTC在程序刚下载完成时已经初始化过一次,所以不会再进行初始化,计时不会被重置,但是闹钟会被重新设定为当前时间戳的后10秒,然后再次进入待机模式,以此往复,也就是说每隔10秒STM32就会被唤醒一次

使用导线给PA0提供上升沿,WKUP引脚的上升沿可以使STM32退出待机模式,这跟闹钟事件无关,不过闹钟还是会被重新设定为当前时间戳的后10秒,然后再次进入待机模式。

#include "stm32f10x.h"                  // Device headerCmd
#include "OLED.h"
#include "MyRTC.h"
#include "Delay.h"

int main()
{
	OLED_Init();
	MyRTC_Init();
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);  //开启PWR的时钟
	
	OLED_ShowString(1, 1, "CNT:");
	OLED_ShowString(2, 1, "ALR:");
	OLED_ShowString(3, 1, "ALRF:");
	
	PWR_WakeUpPinCmd(ENABLE);  //使能位于PA0位置的WKUP引脚(本例需要WKUP引脚产生上升沿)
	
	//闹钟定时在当前时间戳后10秒
	uint32_t Alarm = RTC_GetCounter() + 10;
	RTC_SetAlarm(Alarm);
	
	while(1)
	{		
		OLED_ShowNum(1,6,RTC_GetCounter(),10);
		OLED_ShowNum(2,6,Alarm,10);
		OLED_ShowNum(3,6,RTC_GetFlagStatus(RTC_FLAG_ALR),1);  //闹钟标志位:闹钟响时该位置1
		
		OLED_ShowString(4,1,"Running");
		Delay_ms(500);  //500个时间单位
		OLED_ShowString(4,1,"       ");
		Delay_ms(500);  //500个时间单位
		
		OLED_ShowString(4,9,"STANDBY");
		Delay_ms(1000);  //500个时间单位
		OLED_ShowString(4,9,"       ");
		Delay_ms(100);  //500个时间单位
		
		OLED_Clear();  //清屏
		
		PWR_EnterSTANDBYMode();   //进入待机模式
		//(本例中闹钟事件上升沿/WKUP引脚的上升沿可以退出待机模式,程序从头开始执行)
	}
}
  • 16
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
本教程将介绍如何使用STM32CubeIDE开发环境来控制STM32控制器上的LED灯,通过按键输入来切换LED的状态。 步骤1:准备硬件 我们将使用STM32F4 Discovery开发板,其中包含一个STM32F407微控制器和一些LED灯和按键。将开发板与计算机连接,然后在STM32CubeIDE中创建新的项目。 步骤2:配置GPIO 在STM32CubeIDE中,打开“CubeMX”工具,并按照以下步骤配置GPIO: 1. 选择“Pinout & Configuration”标签页。 2. 在左侧窗格中,选择“GPIO”并将其拖动到右侧窗格中。 3. 在右侧窗格中,选择“GPIO Input”或“GPIO Output”模式,然后将其分配给相应的引脚。 4. 配置GPIO的其他属性,例如速度、上拉或下拉等。 5. 点击“Generate Code”按钮生成配置代码。 步骤3:编写代码 打开生成的代码并编写以下代码: #include "stm32f4xx_hal.h" GPIO_InitTypeDef GPIO_InitStruct; void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); while (1) { if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_SET) { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); } } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 25; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } if (HAL_PWREx_EnableOverDrive() != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); } 在主函数中,我们使用HAL_GPIO_ReadPin函数读取PA0引脚的状态。如果它处于SET状态(按下按键),则使用HAL_GPIO_WritePin函数将PD12引脚设置为SET状态(点亮LED灯)。否则,将PD12引脚设置为RESET状态(关闭LED)。 步骤4:构建和调试 构建代码并将其加载到STM32F4 Discovery板上。按下按键时,LED灯应该点亮。松开按键时,LED灯应该关闭。 结论 本教程介绍了如何使用STM32CubeIDE开发环境来控制STM32控制器上的LED灯,通过按键输入来切换LED的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zevalin爱灰灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值