stm32的定时器学习

发布者:science56最新更新时间:2017-09-13 来源: eefocus关键字:stm32  定时器 手机看文章 扫描二维码
随时随地手机看文章

看了几篇博客之后,对这个定时器也有了一些认识,其实和51差不多,就是配置定时器的时候多了几个步骤而已。


其中很好的一片是:http://blog.sina.com.cn/s/blog_49cb42490100s6ud.html

 

STM32中一共有11个定时器,其中2个高级控制定时器,4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。其中系统嘀嗒定时器是前文中所描述的SysTick,

其中TIM1和TIM8是能够产生3对PWM互补输出的高级登时其,常用于三相电机的驱动,时钟由APB2的输出产生。TIM2-TIM5是普通定时器,TIM6和TIM7是基本定时器,其时钟由APB1输出产生。

由于STM32的TIMER功能太复杂了,所以只能一点一点的学习。因此今天就从最简单的开始学习起,也就是TIM2-TIM5普通定时器的定时功能。

2.3    编程步骤

1.       配置系统时钟;

2.       配置NVIC;

3.       配置GPIO;

4.       配置TIMER;

其中,前3项很简单,在此就不再赘述了。第4项配置TIMER有如下配置:

(1)       利用TIM_DeInit()函数将Timer设置为默认缺省值;

(2)       TIM_InternalClockConfig()选择TIMx来设置内部时钟源;   //可省略

(3)       TIM_Perscaler来设置预分频系数;

(4)       TIM_ClockDivision来设置时钟分割;

(5)       TIM_CounterMode来设置计数器模式;

(6)       TIM_Period来设置自动装入的值

(7)       TIM_ARRPerloadConfig()来设置是否使用预装载缓冲器  //可省略

(8)       TIM_ITConfig()来开启TIMx的中断

其中(3)-(6)步骤中的参数由TIM_TimerBaseInitTypeDef结构体给出。步骤(3)中的预分频系数用来确定TIMx所使用的时钟频率,具体计算方法为:CK_INT/(TIM_Perscaler+1)。CK_INT是内部时钟源的频率,是根据2.1中所描述的APB1的倍频器送出的时钟,TIM_Perscaler是用户设定的预分频系数,其值范围是从0 – 65535。

步骤(7)中需要禁止使用预装载缓冲器。当预装载缓冲器被禁止时,写入自动装入的值(TIMx_ARR)的数值会直接传送到对应的影子寄存器;如果使能预加载寄存器,则写入ARR的数值会在更新事件时,才会从预加载寄存器传送到对应的影子寄存器。

 

下面是我改了的一个历程,适合我的板子。

 

 

/***********************************************************

本例实现的是通过TIM2的定时功能,使得LED灯按照1s的时间间隔来闪烁,D5灯,D13端口
STM32中一共有11个定时器,其中2个高级控制定时器,4个普通定时器和2个基本定时器,
以及2个看门狗定时器和1个系统嘀嗒定时器。其中系统嘀嗒定时器是前文中所描述的SysTick,
其中TIM1和TIM8是能够产生3对PWM互补输出的高级登时其,常用于三相电机的驱动,时钟由APB2的输出产生。
TIM2-TIM5是普通定时器,TIM6和TIM7是基本定时器,其时钟由APB1输出产生。

日期 :2016年2.23

****************************************************************/


#include "stm32f10x.h"

//void RCC_cfg();              原程序中是配置系统时钟,但是这个版本不需要,下面直接systeminit()
void TIMER_cfg(void); //定时器函数 
void NVIC_cfg(void); //中断配置函数
void GPIO_cfg(void); //LED配置


int main()
{
// RCC_cfg();
//SystemInit();
GPIO_cfg();
NVIC_cfg();

TIMER_cfg();

//开启定时器2
// TIM_Cmd(TIM2,ENABLE);

while(1);
}

/*
void RCC_cfg()
{

//定义错误状态变量
ErrorStatus HSEStartUpStatus;

//将RCC寄存器重新设置为默认值
RCC_DeInit();

//打开外部高速时钟晶振
RCC_HSEConfig(RCC_HSE_ON);

//等待外部高速时钟晶振工作
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
//设置AHB时钟(HCLK)为系统时钟
RCC_HCLKConfig(RCC_SYSCLK_Div1);

//设置高速AHB时钟(APB2)为HCLK时钟
RCC_PCLK2Config(RCC_HCLK_Div1);

//设置低速AHB时钟(APB1)为HCLK的2分频
RCC_PCLK1Config(RCC_HCLK_Div2);

//设置FLASH代码延时
FLASH_SetLatency(FLASH_Latency_2);

//使能预取指缓存
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

//设置PLL时钟,为HSE的9倍频 8MHz * 9 = 72MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

//使能PLL
RCC_PLLCmd(ENABLE);

//等待PLL准备就绪
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

//设置PLL为系统时钟源
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

//判断PLL是否是系统时钟
while(RCC_GetSYSCLKSource() != 0x08);
}

//允许TIM2的时钟
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//允许GPIO的时钟
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);


}*/

void TIMER_cfg()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定义timer结构体变量

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //TIM 2-7在总线1上面

//重新将Timer设置为缺省值。。
TIM_DeInit(TIM2); 

//采用内部时钟给TIM2提供时钟源,
// TIM_InternalClockConfig(TIM2); //源程序 有这个,但是去掉 也无妨

//预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz
TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1;
//设置时钟分割
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//设置计数器模式为向上计数模式
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
//设置计数溢出大小,每计2000个数就产生一个更新事件
TIM_TimeBaseStructure.TIM_Period = 2000 - 1;
//将配置应用到TIM2中
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);

//清除溢出中断标志
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//禁止ARR预装载缓冲器
// TIM_ARRPreloadConfig(TIM2, DISABLE);
//开启TIM2的中断
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

TIM_Cmd(TIM2,ENABLE);
}


void NVIC_cfg()
{
NVIC_InitTypeDef NVIC_InitStructure;
//选择中断分组1
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);


//选择TIM2的中断通道
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 
//抢占式中断优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//响应式中断优先级设置为0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
//使能中断
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); //初始化
}

void GPIO_cfg()
{
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //选择引脚5
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出频率最大50MHz
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //带上拉电阻输出
GPIO_Init(GPIOD,&GPIO_InitStructure);

}

//在stm32f10x_it.c中,我们找到函数TIM2_IRQHandler(),并向其中添加代码,如果没有这个文件,在主函数里直接写也可以

void TIM2_IRQHandler(void)
{
u8 ReadValue;
//检测是否发生溢出更新事件
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
//清除TIM2的中断待处理位
TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
//将PB.5管脚输出数值写入ReadValue
ReadValue = GPIO_ReadOutputDataBit(GPIOD,GPIO_Pin_13);

if(ReadValue == 0)
{
GPIO_SetBits(GPIOD,GPIO_Pin_13);

else
{
GPIO_ResetBits(GPIOD,GPIO_Pin_13); 
}
}

}


关键字:stm32  定时器 引用地址:stm32的定时器学习

上一篇:stm32之USART学习
下一篇:stm32中断学习总结

推荐阅读最新更新时间:2024-03-16 15:36

STM32系统时钟树分析
下面是一个STM32芯片的时钟树图 1、LSI是低速内部时钟,RC振荡器,频率为32kHz左右。供独立看门狗和自动唤醒单元使用。 2、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。这个主要是RTC的时钟源。 3、HSE是高速外部时钟,课接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~26MHz。我们开发板接的是8M的晶振。HSE也可以直接作为系统时钟或者PLL输入。 4、HSI是高速内部时钟,RC振荡器,频率为16MHz。可以直接作为系统时钟或者用作PLL输入。 5、PLL为锁相环倍频输出。STM32F4有两个PLL: (1)主PLL由HSE或者HSI提供时钟信号,并具有两个不同的输出时钟。 第一个输出P
[单片机]
<font color='red'>STM32</font>系统时钟树分析
STM32学习手记②-USART中断
/************************************ * 文件名: main.c * 内容简述: 本例程演示如何操作USART的接收程序(中断模式)。 * 用串口调试软件向开发板发送一字节,开发板会将该字节反发回PC */ #include stm32f10x_lib.h /*************************************************** * 函数名称 :void RCC_Configuration() * 功能描述 : 复位和时钟控制 配置 * 参数 : 无 * 返回值 : 无 * 全局变量 : 无 * 全局静态变量: 无 * 局部静态变量: 无 ***
[单片机]
stm32的IO模式具体意义
Ⅰ、写在前面 在开发STM32的时候,都需要对IO的模式进行配置(GPIO_InitStructure. GPIO_Mode = xxx)。但是,你们都知道各种模式的具体意义吗? 有的人问:IO口输出可以上拉吗? 开漏输出是干什么用的? 其实这些问题并不难,只要你了解到每一种模式的真正意思,相信这些问题都不会难道你。本文的内容比较基础,也比较实用,希望对你有所帮助。 关于本文的详细内容请看下面章节 Ⅱ、模式说明 STM32芯片的IO有8中模式: (1)GPIO_Mode_AIN 模拟输入 (2)GPIO_Mode_IN_FLOATING 浮空输入 (3)GPIO_Mode_IPD 下拉输入 (4)GPIO_Mode_IPU 上
[单片机]
<font color='red'>stm32</font>的IO模式具体意义
STM32的i2c容易出的问题 和l3g4200d例程
调试了一晚上,终于一点点把stm32可怕的i2c消灭了,这里分享一下遇到的问题。 最严重的一次卡住居然是在这句话上 /* Send START condition */ I2C_GenerateSTART(I2C1, ENABLE); /* Test on EV5 and clear it */ while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); 执行到第二句就怎么也过不去了,后来才很气愤的发现这是stm32的硬件bug,把fsmc关掉才能使用i2c1的非重影射引脚,关掉以后一切正常。害得我干瞪了两个小时屏幕。 第二次被卡住是在 I2C_Send7bitAdd
[单片机]
STM8学习笔记——定时器定时功能和中断相关
定时器都差不多,无非就是计数,溢出了标志置位,如果中断允许的话产生一个中断。说到中断,STM8S105的中断向量表如下 时基单元: 在选用内部时钟的情况下,CK_PSC是由fmaster提供的,经过定时器预分频器分频产生CK_CNT时钟,然后作为一次计数的时基,举个例子,16M的内部RC,经过16分频,则CK_CNT为1M,那么定时1ms只需计数1000次。 计数模式: 共有三种:向上,向下,中央对齐 以向上计数为例:计数器从0计数到用户定义的比较值(TIMx_ARR寄存器的值),然后重新从0开始计数并产生一个计数器溢出事件,同时,如果TIM1_CR1寄存器的UDIS位是0,将会产生一个更新事件(U
[单片机]
STM32的IIC应用详解1
概要 IIC(IIC,inter-Integrated circuit),两线式串行总线,用于MCU和外设间的通信。 IIC只需两根线:数据线SDA和时钟线SCL。以半双工方式实现MCU和外设之间数据传输,速度可达400kbps。 多主机I2C总线结构 注意SDA和SCL两根总线需要上拉,使总线处于空闲状态。 IIC协议 空闲状态 协议规定,SDA和SCL同时为高电平时,总线处于空闲状态。上拉电阻保证电平处于高电平。 起始信号和停止信号 起始信号:SCL为高电平时,SDA电平发生高到低的跳变 停止信号:SCL为高电平时,SDA电平发生低到高的跳变 应答信号 发送器每发送完一个字节(8个脉冲),在第9个脉
[单片机]
<font color='red'>STM32</font>的IIC应用详解1
stm32汇编实例
例子一 1 ;RCC寄存器地址映像 2 RCC_BASE EQU 0x40021000 3 RCC_CR EQU (RCC_BASE + 0x00) 4 RCC_CFGR EQU (RCC_BASE + 0x04) 5 RCC_CIR EQU (RCC_BASE + 0x08) 6 RCC_APB2RSTR EQU (RCC_BASE + 0x0C) 7 RCC_APB1RSTR EQU (RCC_BASE + 0x10) 8 RCC_AHBENR EQ
[单片机]
<font color='red'>stm32</font>汇编实例
STM32为什么需要位带操作呢?
为什么需要位带操作? 因为编程需要操作某个bit位来达到我们想要的功能,比如点灯需要操作GPIOA- ODR 的某个bit假设是第2bit,写1就可以让GPIO输出一个高电平。 GPIOA- ODR |= 1 2; 这样写其实有三个隐含的操作: //1.读取ODR寄存器的值到内存//2.改写第2bit的值//3.再把改写后的值写进ODR寄存器 这样的缺点:效率低 位带操作就是为了解决这个问题,前提是硬件支持这么做。 位操作就是可以单独的对一个比特位读和写,这个在 51 单片机中非常常见。51 单片机中通过关键字 sbit 来实现位定义,STM32没有这样的关键字,而是通过访问位带别名区来实现,例如 sbit LED P1^2LE
[单片机]
<font color='red'>STM32</font>为什么需要位带操作呢?
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved