一、实验内容
1. 之前作业中的延时功能都是通过循环、delay/Hal_delay函数等实现,本次作业通过定时器Timer方式实现时间的精准控制,相当于给CPU上了一个闹钟,CPU平时处理其它任务,当定时时间到了以后,处理定时相关的任务。请设置一个5秒的定时器,每隔5秒从串口发送“hello windows!”;同时设置一个2秒的定时器,让LED等周期性地闪烁,实现一个多任务并发运行的功能。思考,如果不采用定时器,如何同时完成上面两个周期性任务?
2. 使用TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动你外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。
二、代码实现
(一)第1个任务
1.利用TIM2设置一个5秒的定时器:
void Timer_Init_TIM2(void)
{
//开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //TIM2、TIM3是APB1总线的外设
//选择时基单元的时钟--内部时钟
TIM_InternalClockConfig(TIM2);
//配置时基单元的三部分:计数器CNT、自动重装器ARR、预分频器PSC
//配置参数结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV2; //配置分频系数
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //配置计数器模式为向上计数计数模式
//定时频率(计数器溢出频率)CK_CNT_OV = 72MHz(PSC+1)/(ARR+1)
//我们设置定时器周期位5s,则频率为0.2Hz,再根据上面的公式即可得出该如何设置值
TIM_TimeBaseInitStructure.TIM_Period = 50000 - 1; //配置周期 --即自动重装器的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; //配置预分频器的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //配置重复计数器的值,这是高级计数器会用到的,这里用不到,置为0
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//配置时钟的使能中断 --开启使能中断到NVIC的通路
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
//配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //NVIC优先级分组,分组2
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //配置中断通道---定时器2
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;//配置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //配置响应优先级
NVIC_Init(&NVIC_InitStructure);
//启动定时器
TIM_Cmd(TIM2, ENABLE);
//以上配置所产生的功能:当产生更新时,就触发中断
}
2.编写TIM2中断事件函数:
//编写中断函数,当定时器产生中断时,这个函数会被自动执行
void TIM2_IRQHandler(void)
{
//检查中断标志位
if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
//编写中断触发后,我们想要完成的操作
Serial_SendString("Hello Windows!\r\n");
//清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
3.利用TIM3设置一个2秒的定时器:
void Timer_Init_TIM3(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
//选择时基单元的时钟--内部时钟
TIM_InternalClockConfig(TIM3);
//配置TIM3参数结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV2;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;