基本定时器,只能使用内部时钟
时基单元包括:PSC预分频器、CNT计数器、自动重装寄存器
当PSC=0时不分频,还是72MHz; 当PSC=1时就是2分频,等于72/2=36MHz 16位
CNT计数器对分频后的脉冲计数,通过上升沿+1 16位, // 当值增加到65535后再增加就清零,触发中断,运行定时任务?
自动重装寄存器,写入需要计数的目标,达到这个计数就产生一个中断,并且清零计数器 。这个中断叫 “更新中断”,通往配置好的NVIC的定时器通道.同时还有产生的U“更新事件”,不能被CPU执行,可以被其他外设执行。
void Timer_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_InternalClockConfig(TIM2); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//输入滤波ETRP那里使用,内部时钟分频多少 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数 TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1; //ARR自动重装器的值? TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; //PSC 预分频器的值 //目标频率=CK_PSC/(psc+1)/(ARR+1) 这里定时1S TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器的值 (高级定时器才有,不用的话给0) //这里没有计数器的值,后期可以使用SetCounter和GetCounter函数来操作 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); TIM_ClearFlag(TIM2, TIM_FLAG_Update); //?? 用来避免初始化完就立刻进中断, //因为写的预分频器的值只有在更新事件时起作用,为了立刻起作用,就手动生成一个事件 //同时更新事件和更新中断同时发生,当上电后自动触发一次中断,所以计数会直接从1开始 //这里手动把中断标志位清除一下,避免刚初始化完就进中断的问题 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); }View Code
void TIM2_IRQHandler(void) //中断函数可以放在任何地方 { if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) { Num ++; TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } }View Code
定时器主模式
用DAC输出一段波形,每隔一段时间来触发一次DAC。让它输出下一个电压点:
就是先设置一个定时器产生中断,然后就可以每隔一段时间在中断程序中调用代码手动触发一次DAC转换。然后DAC输出(缺点:主程序频繁被中断)
使用定时器主模式可以(硬件自动化DAC),节省CPU资源
通用定时器
包含基本定时器所有功能
有向上计数,向下计数,中央对齐三种计数模式
输出比较功能
外部时钟
外部触发输入ETR
作为外部时钟使用的时候走上面ETRF那条路线的叫:外部时钟模式2 ; 走中间TRGI路线的叫:外部时钟模式1
void Timer_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); //外部时钟配置 (TIM2,不需要分频,正向【高电平上升沿有效】,滤波参数【多少频率下几个点一样】) TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F); TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_Period = 10-1; //计次10次触发 +1 TIM_TimeBaseInitStructure.TIM_Prescaler = 0x01; //OLED屏幕熄灭?? 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); }View Code
为什么TIM2 ETR的外部中断要接PA0呢?因为引脚物理固定
TRGI 触发输入,主要触发定时的从模式
对于时钟输入而言,ETR红色线也可以走绿色线路,只不过会占用通道
ITR0-3紫色线路信号来自其他4个定时器
ITR0-3 来自其他定时器的信号 (可以接受其他定时器的TRGO信号)
具体怎么连接(绿色主,红色从)
解读:TIM2的ITR0连接在TIM1的TRGO上
高级定时器
增加了这个,可以实现每隔几个周期再触发比如之前的59S可以再*65536
计数器预装时序
ARPE=1时,当设定的计数值改变,等本次周期运行完后,下一轮使用新值(使值的变化与更新事件同步发生)
ARPE=0时,当设定的计数值改变,本次周期直接使用新值,到新值则更新(两者不同步)
RCC时钟树讲解42分
先启动内部8M RC时钟,再启动外部8M石英时钟,通过PLL锁相环倍频到72M,稳定后作为系统时钟
CSS可以检测外部时钟是否失效
标签:TIM2,TimeBaseInitStructure,定时器,NVIC,TIM,InitStructure From: https://www.cnblogs.com/liujinmeng/p/17636068.html