STM32-电源管理(实现低功耗)
电源管理
STM32 HAL库对电源管理提供了完善的函数和命令。
工作模式(高功耗->低功耗):运行、睡眠、停止、待机。
若备份域电源正常供电,备份域内的RTC都可以正常运行,备份域内的寄存器的数据会被保存,不受功耗模式影响。
上电复位(POR)和掉电复位(PDR)
当检测到VDD的电压低于阈值VPOR及VPDR时,无需外部电路辅助,STM32芯片会自动保持在复位状态,防止因电压不足强行工作而带来严重的后果。
在刚开始电压低于VPOR时(约1.92V),STM32保持在上电复位状态(POR,Power On Reset)。当VDD电压持续上升至大于VPOR时,芯片开始正常运行。
而在芯片开始正常运行的时候,当检测到VDD电压下降至低于VPDR阈值(约1.88V),会进入掉电复位状态(PDR,Power Down Reset)。
配置PVD监控功能
PVD可监控VDD的电压,当它低于阈值时可产生PVD中断以让系统进行紧急处理,这个阈值可以直接使用库函数PWR_PVDLevelConfig配置成某一个的阈值等级。
WFI和WFE命令
进入各种低功耗模式时都需要调用WFI或WFE命令,实质上都是内核指令,在库文件 core_cm3.h 或 cmsis_armcc.h 中把这些指令封装成了函数。
/* 等待中断。是一种暂停执行指令,暂停至任意中断产生后被唤醒 */
#define __WFI __wfi/* 等待事件。是一种暂停执行指令,暂停至任意事件产生后被唤醒 */
#define __WFE __wfe
这两个指令,调用后都能进入低功耗模式,需要使用__WFI();和__WFE();来调用(因为__wfi和__wfe是编译器内置的函数,函数内部调用了相对应的汇编指令)。
具体可查《cortex-CM3/CM4权威指南》。
进入停止模式
直接调用WFI和WFE指令可以进入睡眠模式,而进入停止模式这还需要在调用指令前设置一些寄存器位,STM32 HAL库把这部分的操作封装到HAL_PWR_EnterSTOPMode()。
/*** @brief 进入停止模式* @note 在停止模式下所有I/O都会保持在停止前的状态.* @note 当使用中断或唤醒事件退出停止模式时,HSI RC振荡器被选择为系统时钟。* @note 当稳压器在低功率模式下工作时,从停止模式唤醒时会产生额外的启动延迟。* 通过在停止模式中保持内部稳压器打开,虽然启动时间减少,但消耗更高。* @param Regulator: 在停止模式下指定稳压器状态。* @arg PWR_MAINREGULATOR_ON: 稳压器正常运行* @arg PWR_LOWPOWERREGULATOR_ON: 稳压器低功耗运行* @param STOPEntry: 指定是否使用WFI或WFE指令进入停止模式。* @arg PWR_STOPENTRY_WFI: 使用WFI指令进入停止模式* @arg PWR_STOPENTRY_WFE: 使用WFE指令进入停止模式* @retval None*/
void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
{/* 检查参数 */assert_param(IS_PWR_REGULATOR(Regulator));assert_param(IS_PWR_STOP_ENTRY(STOPEntry));/* 清除PWR寄存器中的PDDS位以指定当CPU进入深度睡眠时进入停止模式 */CLEAR_BIT(PWR->CR, PWR_CR_PDDS);/* 根据稳压参数值,通过在PWR寄存器中设置LPDS位来选择稳压模式 */MODIFY_REG(PWR->CR, PWR_CR_LPDS, Regulator);/* 设置内核系统控制寄存器的SLEEPDEEP位 */SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));/* 选择停止模式进入 */if (STOPEntry == PWR_STOPENTRY_WFI){/* 请求等待中断 */__WFI();}else{/* 请求等待事件 */__SEV();PWR_OverloadWfe(); /* 本地重新定义WFE */PWR_OverloadWfe(); /* 本地重新定义WFE */}/* 以下的程序是当重新唤醒时才执行的,清除内核系统控制寄存器的SLEEPDEEP位 */CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
}
进入停止模式后,STM32的所有I/O都保持在停止前的状态,而当它被唤醒时,STM32使用HSI作为系统时钟(8MHz)运行,由于系统是在会影响很多外设的工作状态,所以一般我们在唤醒后会重新开始HSE,把系统时钟设置成原来的状态。
进入待机模式
STM32 HAL库把这部分的操作封装到HAL_PWR_EnterSTANDBYMode()。
/*** @brief 进入待机模式* @note 待机模式下,除以下情况外,所有I/O引脚均为高阻抗::* - 复位引脚(仍然有效)* - TAMPER pin if configured for tamper or calibration out.* - WKUP pin (PA0) (如果使能WKUP唤醒功能).* @retval None*/
void HAL_PWR_EnterSTANDBYMode(void)
{/* 选择待机模式 */SET_BIT(PWR->CR, PWR_CR_PDDS);/* 设置内核系统控制寄存器的SLEEPDEEP位*/SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));/* 存储操作完毕时才能进入待机模式,使用以下语句确保存储操作执行完毕 */
#if defined ( __CC_ARM)__force_stores();
#endif/* 请求等待中断 */__WFI();
}
待机模式也可以使用WFE指令进入的,如果有需要可以自行修改。
在进入待机模式后,除了被使能用于唤醒的I/O,其余I/O都进入高阻态,而从待机模式唤醒后,想防御复位STM32芯片,程序重新从头开始执行。
实验环节1:PWR_PVD监控
实验操作
使用外部可调电源,调节成5V输出,连接到开发板5V和GND排针给板子进行供电;
复位开发板,电压正常时LED为绿色;
向下调节可调电源的电压,大约降到4V时,LED为红色。(程序中控制PVD监控电压约为2.8V,当5V降到4V时,连接STM32的VDD电源会降于2.8V,产生PVD事件,在中断中控制亮红灯)。
注意:其他电源线都拔掉(包括下载器、USB线)。不能远高于5V而导致烧坏开发板。
PVD配置
void PVD_Config(void)
{PWR_PVDTypeDef sConfigPVD;/*使能 PWR 时钟 */__HAL_RCC_PWR_CLK_ENABLE();/* 配置 PVD 中断 */HAL_NVIC_SetPriority(PVD_IRQn, 0 ,0);HAL_NVIC_EnableIRQ(PVD_IRQn); /* 配置PVD级别6 (PVD检测电压的阈值为2.8V,VDD电压低于2.8V时产生PVD中断,具体数据可查询数据手册获知) 具体级别根据自己的实际应用要求配置*/sConfigPVD.PVDLevel = PWR_PVDLEVEL_6;sConfigPVD.Mode = PWR_PVD_MODE_IT_RISING_FALLING;HAL_PWR_ConfigPVD(&sConfigPVD);/* 使能PVD输出 */HAL_PWR_EnablePVD();
}
测试环节
void PVD_IRQHandler(void)
{HAL_PWR_PVD_IRQHandler();
}void HAL_PWR_PVDCallback(void)
{LED红灯
}void test(void)
{初始化LED绿灯// 配置PVD,当电压过低时,会进入中断服务函数,亮红灯PVD_Config();while(1){}
}
实验环节2:PWR睡眠模式
实验操作
LED:绿灯正常运行,红灯睡眠状态,蓝灯刚被唤醒。
KEY:key1和key2配置成IO中断模式。
运行一段时间后自动进入睡眠时间,通过按键(key1或key2)唤醒。
睡眠状态下,DAP下载器无法给STM32下载程序,可唤醒后再下载或按复位键使芯片处于复位状态下下载后松开复位键。
测试环节
int main(void)
{初始化while (1){LED绿灯HAL_Delay(2000);LED红灯HAL_SuspendTick(); //暂停滴答时钟,防止通过滴答时钟中断唤醒//进入睡眠模式HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);//等待中断唤醒 K1或K2按键中断LED蓝灯HAL_ResumeTick(); //被唤醒后,恢复滴答时钟HAL_Delay(2000);//继续执行while循环}
}
实验环节3:PWR待机模式
实验操作
LED:绿灯表示本次复位是上电或引脚复位,红灯待机状态,蓝灯刚被唤醒。
KEY:key2配置成输入模式。
长按KEY2按键会进入待机模式,待机模式下KEY1按键可唤醒,唤醒后系统会复位。可通过检测PWR_CSR:WUF标志确定复位来源。
待机模式下,DAP下载器无法给STM32下载程序,可唤醒后再下载。
注意:由于WKUP引脚(PA0)必须使用上升沿才能唤醒待机状态的系统,所以硬件设计PA0引脚连接到KEY1,且按下KEY1时会在PA0引脚产生上升沿,从而可实现唤醒的功能。
测试环节
/*** @brief 用于检测按键是否被长时间按下* @param 无* @retval 1 :按键被长时间按下 0 :按键没有被长时间按下*/
static uint8_t KEY2_LongPress(void)
{uint8_t downCnt = 0; //记录按下的次数uint8_t upCnt = 0; //记录松开的次数while (1) //死循环,由return结束{ HAL_Delay(20); //延迟一段时间再检测if (HAL_GPIO_ReadPin(KEY2_GPIO_PORT, KEY2_PIN) == SET) //检测到按下按键{downCnt++; //记录按下次数upCnt = 0; //清除按键释放记录if (downCnt >= 100) //按下时间足够{return 1; //检测到按键被时间长按下}}else{upCnt++; //记录释放次数if (upCnt > 5) //连续检测到释放超过5次{return 0; //按下时间太短,不是按键长按操作}}}
}int main(void)
{初始化/* 使能电源管理单元的时钟,必须要使能时钟才能进入待机模式 */__HAL_RCC_PWR_CLK_ENABLE();//检测复位来源if (__HAL_PWR_GET_FLAG(PWR_FLAG_WU) == SET){ // 复位前为待机模式__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);LED蓝灯}else{// 复位前为正常运行LED绿灯}while (1){// K2 按键长按进入待机模式if (KEY2_LongPress()){LED红灯HAL_Delay(1000);/*清除WU状态位*/__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);/* 使能WKUP引脚的唤醒功能,使能PA0*/HAL_PWR_EnableWakeUpPin(0x00000100U);//暂停滴答时钟,防止通过滴答时钟中断唤醒HAL_SuspendTick();/* 进入待机模式 */HAL_PWR_EnterSTANDBYMode();}}
}
实验现象
开机正常运行绿灯。长按KEY2按键,显红灯,过1s后进入待机模式LED灭。按下KEY1按键退出待机模式自动复位,显蓝灯。按下复位键,重新运行绿灯。
实验环节4:PWR停止模式
实验操作
LED:绿灯正常运行,红灯停止状态,蓝灯刚被唤醒。
KEY:key1和key2配置成IO中断模式。
运行一段时间后自动进入停止时间,通过按键(key1或key2)唤醒。
待机模式下,DAP下载器无法给STM32下载程序,可唤醒后再下载。
注意:由于WKUP引脚(PA0)必须使用上升沿才能唤醒待机状态的系统,所以硬件设计PA0引脚连接到KEY1,且按下KEY1时会在PA0引脚产生上升沿,从而可实现唤醒的功能。
测试环节
/*** @brief 从停止模式唤醒后配置系统时钟:启用HSE、PLL并选择PLL作为系统时钟源。* @param 无* @retval 无*/
static void SYSCLKConfig_STOP(void)
{RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};RCC_OscInitTypeDef RCC_OscInitStruct = {0};uint32_t pFLatency = 0;/* 启用电源控制时钟 */__HAL_RCC_PWR_CLK_ENABLE();/* 根据内部RCC寄存器获取振荡器配置 */HAL_RCC_GetOscConfig(&RCC_OscInitStruct);/* 从停止模式唤醒后重新配置系统时钟: 启用HSE和PLL */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){while(1) { ; }}/* 根据内部RCC寄存器获取时钟配置 */HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);/* 选择 PLL 作为系统时钟源, 并配置 HCLK、PCLK1 和 PCLK2时钟分频系数 */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK){while(1) { ; }}
}int main(void)
{uint32_t SYSCLK_Frequency = 0; uint32_t HCLK_Frequency = 0;uint32_t PCLK1_Frequency = 0;uint32_t PCLK2_Frequency = 0;uint32_t SYSCLK_Source = 0;初始化while(1){ LED绿灯HAL_Delay(2000); // 进入停止模式,亮红灯,按KEY1或KEY2按键可唤醒LED_RED;HAL_SuspendTick(); //暂停滴答时钟,防止通过滴答时钟中断唤醒/* 进入停止模式,设置电压调节器为低功耗模式,等待中断唤醒 */HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);// 等待中断唤醒 K1或K2按键中断 // 被唤醒,亮蓝灯指示LED蓝灯SystemCoreClockUpdate(); //根据时钟寄存器的值更新SystemCoreClock变量//获取唤醒后的时钟状态 SYSCLK_Frequency = HAL_RCC_GetSysClockFreq(); HCLK_Frequency = HAL_RCC_GetHCLKFreq();PCLK1_Frequency = HAL_RCC_GetPCLK1Freq();PCLK2_Frequency = HAL_RCC_GetPCLK2Freq();SYSCLK_Source = __HAL_RCC_GET_SYSCLK_SOURCE();/* 从停止模式唤醒后配置系统时钟:启用HSE、PLL*//* 选择PLL作为系统时钟源(HSE和PLL在停止模式下被禁用)*/SYSCLKConfig_STOP();HAL_ResumeTick(); //被唤醒后,恢复滴答时钟//获取重新配置后的时钟状态SYSCLK_Frequency = HAL_RCC_GetSysClockFreq(); HCLK_Frequency = HAL_RCC_GetHCLKFreq();PCLK1_Frequency = HAL_RCC_GetPCLK1Freq();PCLK2_Frequency = HAL_RCC_GetPCLK2Freq();SYSCLK_Source = __HAL_RCC_GET_SYSCLK_SOURCE();HAL_Delay(2000); //继续执行while循环}
}
相关文章:

STM32-电源管理(实现低功耗)
电源管理 STM32 HAL库对电源管理提供了完善的函数和命令。 工作模式(高功耗->低功耗):运行、睡眠、停止、待机。 若备份域电源正常供电,备份域内的RTC都可以正常运行,备份域内的寄存器的数据会被保存,不…...

vue 自己捣鼓周日程日历组件
需求:想要一个周日程表,记录每天的计划,点击可查看详情。可自定义时间段通过后台获取时间段显示 分析: 通过需求,超级课程表app这款软件其中课表和这个需求很像,只不过这个需求第一列的时间段是自定义的,不是上午下午两个,但是原理都差不多 原本想找一些第三方插件使…...

【力扣】2127. (分类讨论 + 拓扑排序)参加会议的最多员工数
【力扣】2127. (分类讨论 拓扑排序)参加会议的最多员工数 文章目录 【力扣】2127. (分类讨论 拓扑排序)参加会议的最多员工数1. 题目介绍2. 思路(**分类讨论 拓扑排序**)3. 解题代码4. Danger参考 1. 题…...
Flutter——最详细(Map)使用教程
Map简介 键值对的集合,您可以使用其关联的键从中检索值。 普通的 HashMap是无序的(不保证顺序),LinkedHashMap 按键插入顺序迭代,而像 SplayTreeMap 这样的排序映射按排序顺序迭代键。 1,添加元素 addEntri…...
vue的入门第一课
Vue.js是一款流行的JavaScript框架,用于构建交互式Web应用程序。本文将详细介绍Vue.js的基础知识,包括Vue.js的历史、设计模式、构造函数参数、el、data、computed、method、watch以及差值的使用。 Vue.js是什么? Vue.js是一款用于构建用户…...
已解决:conda找不到对应版本的cudnn如何解决?
1.解决方法 配置深度学习环境时,打算安装cudatoolkit11.2和cudnn8.1,当使用conda install cudnn8.0时,却搜索不到这个版本的包,解决方法如下: conda search cudnn -c conda-forge然后就可以使用如下命令进行安装对应…...
大语言模型的学习路线和开源模型的学习材料《二》
第三层 LLMs to Artifact 第一重 langchain 【LLMs 入门实战 —— 十二 】基于 本地知识库 的高效 🤖langchain-ChatGLM 介绍:langchain-ChatGLM是一个基于本地知识的问答机器人,使用者可以自由配置本地知识,用户问题的答案也是基于本地知识生成的。【LLMs 入门实战 ——…...

Flask-SQLAlchemy事件钩子介绍
一、前言 前几天在搜资料的时候无意中看到有介绍SQLAlchemy触发器,当时感觉挺奇怪的,触发器不是数据库层面的概念吗,怎么flask-SQLAlchemy这个ORM框架会有这玩意。 二、SQLAlchemy触发器一个简单例子 考虑到效率博客表中有两个字段…...

C++——list
目录 list介绍 list的函数接口 构造函数 push_front和pop_front push_back和pop_back insert erase 迭代器 front和back size resize empty clear list::sort unique reverse 迭代器的实现 list介绍 list是一种可以在常数范围内在任意位置进行插入和删除的序列…...

【Linux】第九站:make和makefile
文章目录 一、 Linux项目自动化构建工具make/Makefile1.make/makefile工作现象2.依赖关系与依赖方法3.如何清理4.为什么这里我们需要带上clean5.连续的make6.特殊符号 二、Linux下实现一个简单的进度条1.回车换行2.缓冲区3.倒计时的实现 一、 Linux项目自动化构建工具make/Make…...
一文了解什么是WebSocket
WebSocket 允许我们创建“实时”应用程序,与传统 API 协议相比,该应用程序速度更快且开销更少。 一、WebSocket 是如何工作的 按照传统的定义,WebSocket是一种双工协议,主要用于客户端-服务器通信通道。它本质上是双向的&…...
redis是什么
redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。和Memcached类似。redis支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。 一、 基本…...

基于深度学习的人脸专注度检测计算系统 - opencv python cnn 计算机竞赛
文章目录 1 前言2 相关技术2.1CNN简介2.2 人脸识别算法2.3专注检测原理2.4 OpenCV 3 功能介绍3.1人脸录入功能3.2 人脸识别3.3 人脸专注度检测3.4 识别记录 4 最后 1 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于深度学习的人脸专注度…...

跨境电商的新引擎:崛起的网红经济
随着全球数字化时代的崛起,跨境电商成为了国际贸易的新引擎,而在这个巨大的变革浪潮中,网红经济正在崭露头角,成为这一引擎的有力推动者。在这篇文章中,我们将深入探讨网红经济如何催生跨境电商的新动力,以…...
P2006 赵神牛的游戏 python解法
赵神牛的游戏 题目描述 在 DNF 中,赵神牛有一个缔造者,他一共有 k k k 点法力值,一共有 m m m 个技能,每个技能耗费的法力值为 a i a_i ai,可以造成的伤害为 b i b_i bi,而 boss 的体力值为 n n…...

Unity的碰撞检测(六)
温馨提示:本文基于前一篇“Unity的碰撞检测(五)”继续探讨两个游戏对象具备刚体的BodyType均为Dynamic,但是Collision Detection属性不同的碰撞检测,阅读本文则默认已阅读前文。 (一)测试说明 在基于两个游戏对象都具…...

从前序与中序遍历序列构造二叉树
代码如下,开袋即食 class Solution {private Map<Integer,Integer> map;public TreeNode buildTree(int[] preorder, int[] inorder) {map new HashMap<>();for(int i 0;i<preorder.length;i){map.put(inorder[i],i);}return build(preorder,inord…...

antd5上传图片显示405解决
antd5上传图片,默认使用上传方式会调用本地的接口。 405 Method Not Allowed 状态码 405 Method Not Allowed 表明服务器禁止了使用当前 HTTP 方法的请求。 Upload {...props}beforeUpload{(file) > {//自定义上传图片的逻辑//最后返回falsereturn false }} &…...

生成瑞利信道(Python and Matlab)
channel h k h_k hk is modeled as independent Rayleigh fading with average power loss set as 10^−3 Python import numpy as np# Set the parameters average_power_loss 1e-3 # Average power loss (10^(-3)) num_samples 1000 # Number of fading samples to …...

数据结构Demo——简单计算器
简单计算器 一、项目介绍二、技术使用三、具体代码实现1.前端部分2.后端部分 一、项目介绍 本项目实现了一个通过网页访问的简单计算器,它可以对带括号的加减乘除表达式进行计算并将计算结果返回给用户,并且可以对用户输入的表达式进行合法性判断&#…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...