自学内容网 自学内容网

STM32学习--6-1 定时器定时中断

定时器电路图

 第一步:RCC开启时钟,基本上每个代码都是第一步

第二步:选择时基单元的时钟源(内部时钟)

第三步:配置时基单元,包括预分频器、自动重装器、计数模式等,通过结构体配置

第四步:配置中断输出控制,允许更新中断输出到NVIC

第五步:配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级

第六步:运行控制,整个模块配置完成后,还需要使能一下计数器,当定时器使能后,计数器就会开始计数了,当计数器更新时,触发中断,

最后再写一个中断函数,这样这个中断函数每隔一段时间就能自动执行一次了。

定时器库函数

  • void TIM_DeInit(TIM_TypeDef* TIMx);    // 恢复缺省配置 
  • void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);   // 时基单元初始化 TIMx 选择哪个定时器 对应2
  • void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); //时基单元结构体初始化 对应2
  • void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);// 使能计时器,运行控制时开启  TIMx 选择哪个定时器 ;NewState:ENABLE 对应6
  • void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); //使能中断输出控制  TIMx 选择哪个定时器;TIM_IT:选择配置哪个中断输出;NewState:ENABLE  对应4
  • 以下五个时钟源选择对应图中标志1
  • void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
  • void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
  • void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);
  • void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
  • void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

  • void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);  // 预分频设置  Prescaler 0代表1分频,1代表2分频即加1,TIM_PSCReloadMode 代表立即执行还是下个周期执行
  • void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode); // 选择计数模式是上升还是下降
  • void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); // 自动预装功能  有无预装器
  • void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter); // 手动给一个计数值
  • void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload); // 给自动重装器写入一个值
  • uint16_t TIM_GetCounter(TIM_TypeDef* TIMx); // 查看当前计数器记到哪里了
  • uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);// 获取预分频器的值

// 获取标志位,清除标志位,前两个是CPU运行时获取,后两个为中断获取

  • 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);

Time.c

#include "stm32f10x.h"                  // Device header

extern uint16_t Num;  // 告诉编译器已经定义过Num,自己去找  是main.c 中Num的引入

void Timer_Init(void)
{
// 初始化定时器
// 1.开启时钟  TIM2 为 APB1 外设
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
// 2.TIM2的时基单元由内部时钟来驱动了 ,不写也可以,默认上电使用内部时钟
TIM_InternalClockConfig(TIM2);
// 3.配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; // 配置进入时分频器
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 配置向上计数
TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;  // ARR 的周期(都在65535以内)
TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1; // 预分频的值 PSC
// CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC / (PSC + 1) / (ARR + 1)
// 1Hz = 72M / 10000 / 7200
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; // 重复计数的值,此时用不着,设0
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
// 避免刚初始化完就进中断的问题   void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
// 4.配置使能中断 TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);  // TIM_IT_Update: TIM update Interrupt source
// 5.NVIC配置 
// 5.1 优先级分组 NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// 5.2 NVIC初始化 void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; // 中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; // 中断通道使能
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; // 设置抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; // 设置响应优先级
NVIC_Init(&NVIC_InitStruct);
// 6 启动定时器 TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
TIM_Cmd(TIM2, ENABLE);
}

// TIM2中断函数  在Start -》 startup_stm32f10x_md_vl.s中 107 行
void TIM2_IRQHandler(void)
{
// 检查标志位  ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)  更新中断位
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Num++;
// 清除标志位 防止不断进中断,使系统崩溃 void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}

Timer.h 

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);

#endif

 main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;  // 定义全局变量在中断中加1

int main(void)
{
OLED_Init();
Timer_Init();
OLED_ShowString(1,3,"Num:");  // 字符串用双引号括起来

while(1)
{
OLED_ShowNum(1,7,Num,5);
OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5); // 获取计数器数值 
// 由于设置的是 9999 故数值在0 - 9999 之间累加
}
}

 


原文地址:https://blog.csdn.net/weixin_62549128/article/details/142886432

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!