一、函数学习
二、代码、
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
uint16_t Num;
int main(void)
{
OLED_Init();
Timer_Init();
OLED_ShowString(1,1,"Num:");
while(1)
{
OLED_ShowNum(1,5,Num,5);
OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);
}
}
//下面是第二种写法,把中断函数拉到主函数中,这样就不用再Timer中extern了
/*void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//因为如果触发了中断,中断标志位会置为1,所以这里是对中断标志位进行判断 如果是SET就是1,那么就是确定产生中断了
{
Num++;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
*/
Timer.c
#include "stm32f10x.h" // Device header
extern uint16_t Num;//跨文件使用变量
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 = 10000 - 1;//Period是ARR的值--> 共同决定定时频率
--> TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1 ;//PSC----------->
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器(高级计数器才有)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//手动清除更新中断标志位,避免刚初始化完就
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启更新中断到NVIC通路
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);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//因为如果触发了中断,中断标志位会置为1,所以这里是对中断标志位进行判断 如果是SET就是1,那么就是确定产生中断了
{
Num++;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
若10000-1 改成1000-1 时钟速度快十倍
Timer无ClearFlag时现象:上电一瞬间计数器从1 开始
原因:
在TIM_TimeBaseInit函数末尾找到
/* Generate an update event to reload the Prescaler and the Repetition counter
values immediately */
TIMx->EGR = TIM_PSCReloadMode_Immediate;
因为预分频器有缓冲寄存器,写入的值只有在更新事件时才起作用,我们这里为了让预分频器的值立刻起作用。
其副作用是:更新事件和更新中断同时发生,更新中断会更新中断标志位,当我们初始化完了,会立刻进中断。
所以,办法:我们要手动清除这个标志位(背后的原理是:整个TIMER初始化完成前,中断状态寄存器不能有标志位)