一、实验前信息储备
1、模式切换程序框架
(1)每个模式都可整体划分三种行为------进入模式的准备工作、模式激活的循环工作和退出模式的收尾工作,可以将这三种行为分别封装为三个函数:
①Init:进入模式前,执行一遍Init函数,用于模式初始化工作。
②Loop:执行完Init函数后,不断循环执行Loop函数,用于模式主体功能。
③Exit:退出模式前,执行一遍Exit函数,用于收尾工作。
(2)下图所示的是由模式1切换到模式2的程序流示意图。

(3)当处于某个模式时,可能需要定期执行某些动作(比如LED状态翻转),由于要控制时间间隔,所以不适合放在Loop函数中,对此可以使用定时中断,在定时器中断函数中判断当前模式,然后执行当前模式对应的周期性动作。

2、模式切换管理
(1)可以使用CurrMode和NextMode两个变量来处理模式切换,CurrMode表示当前所处的模式,NextMode表示下一时刻希望切换的目标模式。
(2)CurrMode与NextMode相等时,说明下一时刻不需要切换目标模式,执行当前模式的Loop函数即可;CurrMode与NextMode不相等时,说明下一时刻需要切换目标模式,执行当前模式的Exit函数和目标模式的Init函数,然后将CurrMode改为目标模式,即可完成模式切换。

二、实验步骤
1、准备工作
(1)拷贝一份STM32教程中"使用OLED屏进行显示"的工程文件夹,并更名为"模式切换程序模板",同时按下图所示接好电路(OLED屏未示出,按照第一章的实验电路连接即可)。

(2)在STM32教程中"定时器定时中断"的工程文件夹中找到Timer.c和Timer.h文件,将其添加进本工程中,并将TIM2的定时时间配置为1ms。

cpp
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10 - 1; //重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; //预分频系数(TIM2的频率是72MHz)
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}