STM32学习第一篇----------定时器定时中断

使用stm32内部时钟进行定时中断

学习江科大stm32第5天 ---- 6-1 TIM定时中断   、 6-2定时器定时中断&定时器外部中断

1、TIM(Timer) 定时器

(1)定时器对输入的时钟进行计数,当计数值达到设定值时触发中断;

(2)16位计数器、预分频器、自动重装寄存器的时基单元,并在72MHz计数时钟下可以实现最大59.65s的计时;

(3)具备基本的定时中断功能,包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能;

(4)分为高级定时器、通用定时器、基本定时器  。其中STM32C8T6中TIM1为高级定时器、TIM2 TIM3  TIM4为通用定时器;

(5)适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM);使用定时器预分频器和RCC时钟预分频器,脉冲长度和波形周期可以在几个微秒到几个微秒间调整;

(6)每个定时器都是完全独立的,没有互相共享任何资源,但可以一起可以同步操作。

图1  通用定时器框图

2、时序图

(1) 预分频器时序

         从上面两张图来看,CK_PSC一直输出一个方波,CEN高电平使能,当预分频器为0,定时器根据CK_PSC的一个波形来进行累积计数,到达更新事件(UEV)后,从之前的预分频系数变为3(即根据CK_PSC的四个波形来进行累计计数),期间控制寄存器在上一个计数周期发生变化,通过预分频缓冲器在这个周期结束后再将计数周期改变,预分频计数器通过对CK_PSC方波信号进行计数从而得到以CK_CNT的四个周期为信号的方波波形。

         且计数器计数频率:CK_CNT = CK_PSC / ( PSC + 1 )

(2) 计数器时序

CK_INT为内部时钟72MHz ,CNT_EN为计数器时钟使能(高电平使能),CK_CNT(内部时钟分频系数因子为2)。每两个时钟频率,计数器寄存器在CK_CNT的上升沿自增,到达36后计数器溢出,再来一个上升沿(计数器归零),同时产生一个更新事件脉冲,还会置一个更新中断标志位UIF(该标志位只要置1,就会申请中断,中断响应后,需要在中断程序中手动清零)

计数器溢出频率: CK_CNT_OV = CK_CNT / (ARR + 1) = CK_PSC/(PSC + 1)/(ARR + 1)

其中计数器也存在有缓存的情况

3、定时中断基本结构

        第一步,RCC开启时钟;

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

        第三步,配置时基单元(预分频器、计数器、自动重装器);

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

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

4、代码部分

(1)Timer.c
#include "stm32f10x.h"

void Timer_Init(void)
{
    //开启时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);    //开启TIM2的时钟
    
    //配置时钟源
    TIM_InternalClockConfig(TIM2); // 选择TIM2为内部时钟

    //时基单元初始化
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure ;  //定义结构体变量
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1 ; //时钟分频
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up ; //计数器模式选择向上计数
    TIM_TimeBaseInitStructure.Period  = 10000 - 1 ; //计数周期 ,即ARR的值
    TIM_TimeBaseInitStructure.Prescaler         = 7200 - 1 ;//预分频器, 即PSC的值
    TIM_TimeBaseInitStructure.RepetitionCounter = 0 ; //重复计数器,高级定时器才会用到
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure ) //将设置的结构体用来配置TIM2的时基单元

    //中断输出配置
    TIM_ClearFlag(TIM2,TIM_FLAG_Update) ;  //清除定时器更新标志位
           //TIM_TimeBaseInit函数末尾,手动产生了更新事件
           //若不清除此标志位,则开启中断后,会立刻进入一次中断
           //对上面一句话具体的描述:就是说如果开始程序后又复位,计时就会直接从1开始,而不是从0
           //如果不介意此问题,则不清除此标志位
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE) ; //开启TIM2的更新中断

    //NVIC中断分组
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2) ; //配置NVIC为分组2

    //NVIC配置
    NVIC_InitTypeDef NVIC_InitStructure ;  
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn ; //选择配置NVIC的TIM2线
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ; //指定NVIC使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2 ; //指定NVIC线路的抢占优先级为2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1 ; //指定NVIC线路的响应优先级为1
    NVIC_Init(&NVIC_InitStructure) ;//将结构体变量交给NVIC_Init,配置NVIC


    //TIM使能
    TIM_Cmd(TIM2,ENABLE); // 使能TIM2,定时器开始运行

}
(2)main.c
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) //判断是否是TIM2的更新事件触发的中断
	{
		Num ++;										 //Num变量自增,用于测试定时中断
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);	 //清除TIM2更新事件的中断标志位
													 //中断标志位必须清除
													 //否则中断将连续不断地触发,导致主程序卡死
	}
}

附:时钟树

<think>好的,我需要回答用户关于STM32F103 LED控制的问题。首先,用户提到的SRM32F103可能是拼写错误,正确型号应该是STM32F103。所以我会假设用户是想询问STM32F103的LED控制指令或代码示例。 用户之前提供的引用中有几个相关的例子,比如引用[1]提到了通过串口控制RGB彩灯,引用[3]是有源蜂鸣器的驱动代码。虽然这些不完全对应LED控制,但可以借鉴GPIO初始化和控制的方法。 首先,我需要确认LED的控制通常涉及GPIO的输出配置。STM32F103的GPIO需要配置为推挽输出模式,设置相应的时钟使能,然后通过置位和复位引脚来控制LED的开关。可能还需要延时函数来实现闪烁效果。 用户可能需要基础的LED闪烁代码,或者更复杂的控制如PWM调光。根据引用[2],提到了互补PWM波的输出,这可能与LED亮度控制相关,但用户现在可能只需要简单的开关控制。 接下来,我需要组织一个简单的示例代码,包括GPIO初始化函数、LED开关函数,以及主函数中的闪烁循环。同时,需要确保代码语法正确,比如包含必要的头文件,正确配置时钟和引脚。 另外,用户可能对如何通过串口发送指令控制LED感兴趣,如引用[1]中的例子,可以结合串口通信解析指令,控制不同的LED。不过用户的问题更偏向于直接的LED编程示例,所以可能先提供基础的GPIO控制,再提及扩展应用。 需要检查是否有常见的错误,例如GPIO端口和引脚的配置是否正确,时钟使能是否正确,延时函数是否实现。例如,引用[3]中的蜂鸣器驱动使用了PA5,而代码中可能要根据实际硬件连接调整引脚。 最后,生成相关问题,帮助用户深入理解,比如如何实现PWM调光、多LED控制、或者结合外设如串口控制LED。这些问题可以引导用户进一步探索STM32F103的功能。</think>### STM32F103 LED控制编程实现 #### 1. 基础GPIO控制LED闪烁 以下是基于STM32F103标准库的LED控制基础代码(以PA5引脚为例): ```c #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_rcc.h" void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能GPIOA时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置PA5为推挽输出模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); } void Delay(uint32_t count) { for(; count != 0; count--); } int main(void) { LED_Init(); while(1) { GPIO_SetBits(GPIOA, GPIO_Pin_5); // 点亮LED Delay(0xFFFFF); GPIO_ResetBits(GPIOA, GPIO_Pin_5); // 熄灭LED Delay(0xFFFFF); } } ``` #### 2. 进阶控制功能 1. **PWM调光控制**: 通过定时器输出PWM信号控制LED亮度: ```c // 使用TIM2_CH1(PA0)输出PWM TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_OCInitTypeDef TIM_OCInitStruct; void PWM_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置PA0为复用推挽输出 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 定时器基础配置 TIM_InitStruct.TIM_Period = 999; // PWM周期 TIM_InitStruct.TIM_Prescaler = 71; // 分频系数(72MHz/72=1MHz) TIM_InitStruct.TIM_ClockDivision = 0; TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_InitStruct); // PWM模式配置 TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStruct.TIM_Pulse = 500; // 初始占空比50% TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM2, &TIM_OCInitStruct); TIM_Cmd(TIM2, ENABLE); } ``` #### 3. 串口指令控制LED(参考引用[1]) ```c // 在串口中断服务函数中添加 void USART1_IRQHandler(void) { if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uint8_t cmd = USART_ReceiveData(USART1); switch(cmd) { case 'L': GPIO_SetBits(GPIOA, GPIO_Pin_5); break; case 'l': GPIO_ResetBits(GPIOA, GPIO_Pin_5); break; default: GPIO_ResetBits(GPIOA, GPIO_Pin_5); // 默认关闭 } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值