网站开发建设及推广合同,好的企业型网站模板下载,网站正在建设代码,企业微网站模版目录 一、TIM#xff08;Timer#xff09;定时器简介
二、定时器类型
2.1基本定时器结构
2.2通用定时器结构
2.3高级定时器结构
三、定时中断基本结构
四、时序图分析
4.1 预分频器时序
4.2 计数器时序
4.3 计数器无预装时序#xff08;无影子寄存器#xff09;
…目录 一、TIMTimer定时器简介
二、定时器类型
2.1基本定时器结构
2.2通用定时器结构
2.3高级定时器结构
三、定时中断基本结构
四、时序图分析
4.1 预分频器时序
4.2 计数器时序
4.3 计数器无预装时序无影子寄存器
4.4 计数器有预装时序有影子寄存器
五、RCC时钟树
六、开发步骤
七、定时器函数
八、实验
8.1定时器定时中断
8.2定时器外部时钟 一、TIMTimer定时器简介 ①定时器可以对输入的时钟进行计数并在计数值达到设定值时触发中断 ②16位计数器、预分频器、自动重装寄存器的时基单元在72MHz计数时钟下可以实现最大59.65s的定时 计数器执行计数定时的一个寄存器每来一个时钟计数器加1 预分频器对计数器的时钟进行分频让这个计数更加灵活 自动重装寄存器计数的目标值计多少个时钟来申请一次中断 ③不仅具备基本的定时中断功能而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能 ④根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型 二、定时器类型 2.1基本定时器结构 主模式触发DAC功能把定时器的更新事件映射到触发输出TRGO(Trigger Out)的位置TRGO直接接到DAC的触发转换引脚上这样就不需要通过中断来触发DAC转换了。实现了硬件的自动化。 通用定时器和高级定时器除了向上计数模式还有向下计数模式和中央对齐模式 2.2通用定时器结构 2.3高级定时器结构 三、定时中断基本结构 四、时序图分析
4.1 预分频器时序 计数器计数频率CK_CNT CK_PSC / (PSC 1) 4.2 计数器时序 计数器溢出频率CK_CNT_OV CK_CNT / (ARR 1) CK_PSC / (PSC 1) / (ARR 1) 计数器时间(PSC 1)(ARR 1)/CK_PSC 4.3 计数器无预装时序无影子寄存器 4.4 计数器有预装时序有影子寄存器 五、RCC时钟树 作用产生和配置时钟将配置好的时钟发送到各个外设系统 开发技巧 在SystemInit函数中首先启动内部8MHz时钟为系统时钟运行然后再启动外部时钟进入PLL锁相环进行倍频8MHz倍频9倍得到72MHz锁相环输出稳定之后选择锁相环输出为系统时钟这样就把系统时钟由8MHz变成了72MHz。 实际问题 如果外部晶振出现问题程序时钟慢了大概10倍定时器定时1s结果过了大概10s才进中断。是因为现在是以内部时钟8MHz运行的 六、开发步骤 ①RCC打开时钟 ②选择时基单元的时钟源 ③结构体配置时基单元预分频器自动重装器计数模式 ④配置输出中断控制允许更新中断输出到NVIC ⑤配置NVIC在NVIC中打开定时器中断的通道并分配一个优先级 ⑥运行控制使能计数器 ⑦写定时器中断函数 七、定时器函数 基本函数 void TIM_DeInit(TIM_TypeDef* TIMx); //定时器恢复缺省配置 void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); //时基单元初始化 //第一个参数某个定时器第二个参数结构体 void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); //把结构体变量赋默认值 void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); //使能计数器 //第一个参数TIMx选择定时器第二个参数使能或失能 void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); //使能中断输出信号中断输出控制 //第一个参数TIMx选择定时器第二个参数哪个中断输出第三个参数使能或失能 配置时钟输入的函数 void TIM_InternalClockConfig(TIM_TypeDef* TIMx); //选择内部时钟 void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); //选择ITRx其他定时器时钟 //第一个参数选择配置哪个定时器第二个参数选择要接入哪个定时器 void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter); //选择TIx捕获通道的时钟 //第一个参数TIMx第二个参数TIMx具体哪个引脚第三、四个参数输入极性和滤波器 void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter); //ETR通过外部时钟模式1输入时钟 //第一个参数TIMx第二个参数外部触发预分频器第三、四个参数输入极性和滤波器 void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); //ETR通过外部时钟模式2输入时钟 //第一个参数TIMx第二个参数外部触发预分频器第三、四个参数输入极性和滤波器 void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter); //单独配置ETR引脚的预分频器、极性、滤波器 //第一个参数TIMx第二个参数外部触发预分频器第三、四个参数输入极性和滤波器 更改关键参数函数预分频值自动重装载值 void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); //修改预分频值 //第一个参数TIMx第二个参数预分频值第三个参数写入模式 void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode); //修改计数器的计数模式 //第一个参数TIMx第二个参数新的计数器模式 void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); //自动重装器预装功能配置 //第一个参数TIMx第二个参数预装功能使能或失能 void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter); //给计数器值 //第一个参数TIMx第二个参数计数器值 void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload); //给自动重装器写入值 //第一个参数TIMx第二个参数自动重装值 uint16_t TIM_GetCounter(TIM_TypeDef* TIMx); //获取计数器值 uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx); //获取预分频值 获取和清除标志位函数 //主函数 FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); //中断函数 ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT); void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT); 八、实验
8.1定时器定时中断 实验现象1s计数加一 代码实现 Timer.c #include stm32f10x.h // Device headervoid Timer_Init(void)
{/*一、RCC开启时钟*/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;//ARR自动重装器值TIM_TimeBaseInitStructure.TIM_Prescaler 7200 - 1;//PSC预分频器值TIM_TimeBaseInitStructure.TIM_RepetitionCounter 0;//重复计数器值高级定时器才有TIM_TimeBaseInit(TIM2,TIM_TimeBaseInitStructure);/*避免刚初始化就进入中断复位就是1而不是0*/TIM_ClearFlag(TIM2,TIM_FLAG_Update);/*四、配置输出中断控制允许更新中断输出到NVIC*/TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启更新中断到NVIC的通路/*五、配置NVIC在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){TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}
*/Timer.h #ifndef __TIMER_H
#define __TIMER_Hvoid Timer_Init(void);#endifmain.c #include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include Timer.huint16_t Num;int main(void)
{OLED_Init();Timer_Init();OLED_ShowString(1,1,Num:);OLED_ShowString(2,1,CNT:);while (1){OLED_ShowNum(1,5,Num,5);OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);//观察CNT计数器值的变化情况}
}void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2,TIM_IT_Update) SET){Num ;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}8.2定时器外部时钟 方法定时器指定的外部引脚输入一个方波信号来提供定时器计数的时钟 实验现象利用对射式红外传感器来手动模拟一个外部时钟用挡光片依次遮挡、移开来模拟一个方波定时器计数值(CNT)逐次加一当CNT到9后产生一次中断Num加一CNT清零重新计数 代码实现 Timer.c #include stm32f10x.h // Device headervoid Timer_Init(void)
{/*一、RCC开启时钟 GPIOA的初始化*/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);/*二、选择时基单元的时钟源*/TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00);//通过ETR的外部时钟模式2不分频不反向高电平/上升沿有效外部触发滤波器/*三、配置时基单元(预分频器自动重装器计数模式)*/TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period 10 - 1;//ARR自动重装器值TIM_TimeBaseInitStructure.TIM_Prescaler 1 - 1;//PSC预分频器值TIM_TimeBaseInitStructure.TIM_RepetitionCounter 0;//重复计数器值TIM_TimeBaseInit(TIM2,TIM_TimeBaseInitStructure);/*避免刚初始化就进入中断复位就是1而不是0*/TIM_ClearFlag(TIM2,TIM_FLAG_Update);/*四、配置输出中断控制允许更新中断输出到NVIC*/TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/*五、配置NVIC在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);
}/*查看CNT的值*/
uint16_t Timer_GetCounter(void)
{return TIM_GetCounter(TIM2);
}/*中断函数模板
void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2,TIM_IT_Update) SET){TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}
*/Timer.h #ifndef __TIMER_H
#define __TIMER_Hvoid Timer_Init(void);
uint16_t Timer_GetCounter(void);#endifmain.c #include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include Timer.huint16_t Num;int main(void)
{OLED_Init();Timer_Init();OLED_ShowString(1,1,Num:);OLED_ShowString(2,1,CNT:);while (1){OLED_ShowNum(1,5,Num,5);OLED_ShowNum(2,5,Timer_GetCounter(),5);//观察CNT计数器值的变化情况}
}void TIM2_IRQHandler(void)
{if(TIM_GetITStatus(TIM2,TIM_IT_Update) SET){Num ;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}