STM32定时器3配置时钟的坑

发布者:JoyfulExplorer最新更新时间:2024-08-13 来源: cnblogs关键字:STM32  定时器3  配置时钟 手机看文章 扫描二维码
随时随地手机看文章

STMf1的配置TIM3

我用的是原子的F1精英版,配置定时器3的时候出了点问题

问题描述

这里是主函数,在TIM3_Int_Init函数中,4999是重装载值,3599是预分频系数
计算:
如果APB1给TIM的时钟是36M的话,我使用3599预分频之后,那分频之后的频率就是 36M/3600=10K
(因为是从零开始计数,所以计算使用3600,但是代码里面要用3599)也就是说每计一个数用的时间就是1/10K = 0.0001s = 0.1ms.
我现在计数个数是5000个(0~4999),那时间就是 5000*0.1ms = 500 ms ,我让PE5每中断一次就取反一次,所以PE5的高电平时间应该是500,方波周期就是1s,频率为1Hz,
下图就是假设TIM3的时钟是36M的时候,产生的方波

这很明显就不对,所以虽然TIM是挂在时钟频率为36MHz的APB1总线上,但是最终到定时器的时钟并不是36M


int main(void)

 {

 

delay_init();     //延时函数初始化   

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

uart_init(115200); //串口初始化为115200

  LED_Init();      //LED端口初始化

TIM3_Int_Init(4999,3599);//10Khz的计数频率,计数到5000为500ms  

    while(1)

{

LED0=0;

//delay_ms(200);    

}  

}  


定时器初始化及中断函数


//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器3!

void TIM3_Int_Init(u16 arr,u16 psc)

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

NVIC_InitTypeDef NVIC_InitStructure;


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能

//定时器TIM3初始化

TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值

TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

 

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断


//中断优先级NVIC设置

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM3中断

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器



TIM_Cmd(TIM2, ENABLE);  //使能TIMx  

}

//定时器3中断服务程序

void TIM2_IRQHandler(void)   //TIM3中断

{

if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否

{

TIM_ClearITPendingBit(TIM2, TIM_IT_Update  );  //清除TIMx更新中断标志 

LED1=!LED1;

}

}

如果假设是72M,那么计算的话可以按照上面的来,最终的结果就是2Hz。那上面的那个波形图就是对的。

总的来说就是,定时器3的时钟不等于APB1的时钟


问题解决

我去看了一下那个时钟树,大概就明白了是怎么个回事,放图

在系统时钟72M进入APB1之后进行了2分频,得到了36M,所以挂在APB1总线上的外设时钟频率是36M,因为分频系数不等于1,所以APB1的36需要进行乘2才进入定时器的时钟。
这是挂在APB1上面的所有外设


#define RCC_APB1Periph_TIM2              ((uint32_t)0x00000001)

#define RCC_APB1Periph_TIM3              ((uint32_t)0x00000002)

#define RCC_APB1Periph_TIM4              ((uint32_t)0x00000004)

#define RCC_APB1Periph_TIM5              ((uint32_t)0x00000008)

#define RCC_APB1Periph_TIM6              ((uint32_t)0x00000010)

#define RCC_APB1Periph_TIM7              ((uint32_t)0x00000020)

#define RCC_APB1Periph_TIM12             ((uint32_t)0x00000040)

#define RCC_APB1Periph_TIM13             ((uint32_t)0x00000080)

#define RCC_APB1Periph_TIM14             ((uint32_t)0x00000100)

#define RCC_APB1Periph_WWDG              ((uint32_t)0x00000800)

#define RCC_APB1Periph_SPI2              ((uint32_t)0x00004000)

#define RCC_APB1Periph_SPI3              ((uint32_t)0x00008000)

#define RCC_APB1Periph_USART2            ((uint32_t)0x00020000)

#define RCC_APB1Periph_USART3            ((uint32_t)0x00040000)

#define RCC_APB1Periph_UART4             ((uint32_t)0x00080000)

#define RCC_APB1Periph_UART5             ((uint32_t)0x00100000)

#define RCC_APB1Periph_I2C1              ((uint32_t)0x00200000)

#define RCC_APB1Periph_I2C2              ((uint32_t)0x00400000)

#define RCC_APB1Periph_USB               ((uint32_t)0x00800000)

#define RCC_APB1Periph_CAN1              ((uint32_t)0x02000000)

#define RCC_APB1Periph_CAN2              ((uint32_t)0x04000000)

#define RCC_APB1Periph_BKP               ((uint32_t)0x08000000)

#define RCC_APB1Periph_PWR               ((uint32_t)0x10000000)

#define RCC_APB1Periph_DAC               ((uint32_t)0x20000000)

#define RCC_APB1Periph_CEC               ((uint32_t)0x40000000)


总结

虽然不知道系统在那里设置了乘2的操作,但是现在我就是只知道这样子去用,以后配置的时候都按照72M的时钟去配置定时器。

关键字:STM32  定时器3  配置时钟 引用地址:STM32定时器3配置时钟的坑

上一篇:STM32之旅1——LED
下一篇:启动模式,BOOT0和BOOT1详解

推荐阅读最新更新时间:2026-03-21 11:26

stm32的RCC系统时钟配置
一直以来,我使用的系统时钟都是默认设置,没有经过修改,也一直能用,但是一直不清楚如何一步步配置,现在知道怎么改了,所以把修改的方法写下来供参考。 很全很细的介绍请看这里 https://wenku.baidu.com/view/3c11ec1925c52cc58bd6bed8.html 想复制一下,随便改改就能用请看下面。重点是注释 首先贴我从野火f103抄来的,经过修改的代码 1 void HSE_SetSysClockTo72(void) 2 { 3 __IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0; 4 5 // 把RCC外设初始化成
[单片机]
stm32单片机时钟中断的配置
配置流程: 1:系统时钟初始化,包括系统时钟和要开放的IO口或者功能的时钟配置。 2:IO口初始化,包括引脚,速率,输入输出模式等。 3:NVIC 中断向量配置 ,中断向量基地址和优先级的配置。 4:TIM3初始化:包括自动重装值,分频值,计数模式,使能TIM中断,使能TIM3外设 5:中断处理函数:注意清除TIMx的中断待处理位 注意: 1:RCC初始化要使能或者失能 APB1 外设时钟。 2:中断处理函数:注意清除TIMx的中断待处理位 TIMx_SR寄存器 3:关于时钟:初始化RCC时使用SystemInit()函数时默认的是AHB不分频,即HCLK等于SYSHCLK,APB2不分频,APB1为HCLK 2分频而定时器3时
[单片机]
<font color='red'>stm32</font>单片机<font color='red'>时钟</font>中断的<font color='red'>配置</font>
RTC时钟和BKP的配置stm32
RTC和后备寄存器通过一个开关供电,在VDD有效的时候选择VDD供电,否则选择VBAT引脚供电. 后备寄存器(10个16位的寄存器),可以用于在关闭VDD时,保存20个字节的用户应用数据(中容量和小容量产品,大容量和互联性产品有84字节). RTC和后备寄存器不会被系统或电源复位源复位;当从待机模式唤醒时,也不会被复位. RTC的作用: 日历时钟功能; 闹钟中断; 阶段性中断; RTC时钟源: 外部晶体32.768kHz振荡器;内部低功耗RC振荡器; 高速的外部时钟经128分频. 复位后,对备份寄存器和RTC的访问被禁止,并且备份域被保护,以防止可能存在的意外的操作. 执行下面操作,可以是能对备份寄存器和RTC的访问: 打
[单片机]
RTC<font color='red'>时钟</font>和BKP的<font color='red'>配置</font><font color='red'>stm32</font>
STM32 MCO时钟输出配置实验
STM32的PA.8引脚具有复用功能——时钟输出(MCO), 该功能能将STM32内部的时钟通过PA.8输出. 操作流程: 1)、设置PA.8为复用AF模式。 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
[单片机]
<font color='red'>STM32</font> MCO<font color='red'>时钟</font>输出<font color='red'>配置</font>实验
STM32系统时钟配置
STM32的SYSCLK(系统时钟)可由三种不同的时钟源来驱动,分别是HSI振荡器时钟、HSE振荡器时钟、PLL时钟。这些设备还拥有2种二级时钟源: 1、低速内部RC(LSI RC)振荡器,频率在30~60KHZ之间变化,为了方便计算我们一般估算为40KHZ,它主要为独立看门狗提供时钟源,或通过相关寄存器配置驱动RTC(RTCCLK),用于从停机/待机模式下自动唤醒系统。 2、使用32.768KHZ的低速外部晶体时钟来驱动RTC(RTCCLK)。 为减小功耗,STM32的任一时钟源都可以独立地开启或关闭。 注意:1、当HSI(高速内部时钟)作为PLL时钟输入时,SYSCLK得到的最大频率为36MHZ(有些写的是64MHZ)。SD
[单片机]
<font color='red'>STM32</font>系统<font color='red'>时钟</font><font color='red'>配置</font>
stm32变更外部晶振时时钟配置
学习野火的固件库UART1串口案例时,用的是SIM9008模块应用板上STM32103F103RB芯片,使用的外部晶振是12M。 串口读取的是乱码 默认的外部晶振是8M 由于stm32的库默认是外部晶振8M的情况下实现的,所以配置串口波特率的时候也是按8M,包括主频。 如果采用外部晶振8M或12M,配置时钟为72MHZ 。 1)在system32_stm32f10x.c文件中的void SetSysClockTo72(void)里这样改: 8M: RCC- CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);//8*9=72 12M: RCC- CFGR |=
[单片机]
关于 STM32 时钟配置的那些坑
今天分享以下两点内容: 1.为什么我们要先开启STM32外设模块时钟; 2.关于STM32的 I/O 复用功能及什么时候开启AFIO时钟; 1为什么我们要先开启STM32外设时钟 讲述本节内容之前先说一个案例: 前段时间,有一个朋友为配置EXTI的代码折腾了一天,最终没有结果。于是问了我这样一个问题:“你用过STM32F051C8T6的外部中断吗,就是GPIO管脚做中断,我这边就是进不了中断”。 然后他把基于标准外设库、寄存器写的代码都给我发过来了。我仔细看了又看,没发现有什么毛病啊。(但是,代码是截图分来给我发过来的)。 于是,我将之前配置IO外部中断的代码,按照他(PB2)的要求,写成一个“EXTI配置”函数发给他,他直接
[单片机]
关于 <font color='red'>STM32</font> <font color='red'>时钟</font><font color='red'>配置</font>的那些坑
浅谈STM32时钟配置及相关问题
Ⅰ、写在前面 最近有很多朋友问:1.我的USART串口打印出来的数据是乱码?2.我的TIM定时器延时或定时不准确? 常见可能原因: 1.晶振问题:外部晶振不起振、或频率与配置不匹配。 2.软件问题:分频、倍频、时钟源选择等。 总结来说,主要还在于软件的问题。因为即使没有外部晶振,也可以使用内部晶振。 其实,软件的问题是容易得到解决的,只要你了解了STM32时钟配置里面具体内容就知道了。 关于本文的详细内容请看下面章节 Ⅱ、本文要点 要了解时钟的配置,就需要知道它在哪里配置,也就是还需要了解软件执行的流程。 1.软件流程 说软件流程是让大家知道系统时钟配置的位置。不管是使用寄存器开发,还是使用库(标准库、HAL库)开发STM
[单片机]
浅谈<font color='red'>STM32</font><font color='red'>时钟</font><font color='red'>配置</font>及相关问题
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved