【STM库应用】stm32 之 TIM (详解一 通用定时器)

发布者:美好梦想最新更新时间:2020-03-04 来源: eefocus关键字:STM库  stm32  TIM  通用定时器 手机看文章 扫描二维码
随时随地手机看文章

定时器,中断这两样东西是学习一个MCU必须掌握的,也是非常有用的!


STM32的TIM一般有高级定时器TIM1,(TIM8只有在互联性产品有),普通定时器TIM2,TIM3,TIM4,(TIM5,TIM6,TIM7有点设备中没有);今天就只介绍普通定时器,因为高级定时器我还不会!每一个普通定时器都有4路通道!

我们先看看这个逻辑图吧!我们今天先讨论讨论定时器的问题!我用红色笔标过的路线就是定时器的工作路线,时钟有内部时钟产生,到PSC哪里进行分频处理,然后CNT进行计数,上面还有一个自动重装载寄存器APP。

这个是分频器的工作原理,我们可以看,分频器设定之前分频系数为1[1],后面的[2][3][4]分频系数为2,分频系数改变后,计数周期也跟着改变了;同时预分频设置生效时,他还会产生一个中断信号,这个中断信号不要管他,一个系统时钟周期后会自动消失,跟I2C的差不多!

这个是计数过程,上面说过了,计数跟分频后的周期有关;当计数达到装载的数值之后,系统会产生一个三个信号,其中溢出信号和更新事件一个时钟周期后会自动消失,而这时候触发了更新中断标志位UIF,我们可以用这个UPDATE来做定时器的中断标志信号!


TIM_ITConfig(TIM2, TIM_IT_UPDATE, ENABLE);


另外还有4个中断,我们知道PWM的产生把,他就跟PWM的产生有着血缘关系!

如果我们在OC模式选择的时候,TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;选择了Timing那么我们就可以做定时器了。


有时候我们会发现当UPdate中断信号产生时,其他四个中断信号也产生,什么原因呢?因为我们在设置tim.TIM_Period = period;时,period时间太短,就错觉的以为他们是一群产生中断信号的!来我们分析下:


假设分频因子为71,即72分频,PCLK为72M,我们设置的周期为1000;那么我们产生定时器的Upddate信号频率为1000Hz,周期为1ms,假设我们这里设置的CCR1 = 100;CCR2 = 500;CCR3 = 600;CCR4 = 900;


那么update信号产生后0.1ms产生CCR1的中断信号,0.5ms后产生CCR2的中断信号,0.6ms后产生CCR3的中断信号,这些中断标志位是:


#define TIM_FLAG_Update                    ((uint16_t)0x0001)

#define TIM_FLAG_CC1                       ((uint16_t)0x0002)

#define TIM_FLAG_CC2                       ((uint16_t)0x0004)

#define TIM_FLAG_CC3                       ((uint16_t)0x0008)

#define TIM_FLAG_CC4                       ((uint16_t)0x0010)

#define TIM_FLAG_COM                       ((uint16_t)0x0020)

#define TIM_FLAG_Trigger                   ((uint16_t)0x0040)

#define TIM_FLAG_Break                     ((uint16_t)0x0080)

#define TIM_FLAG_CC1OF                     ((uint16_t)0x0200)

#define TIM_FLAG_CC2OF                     ((uint16_t)0x0400)

#define TIM_FLAG_CC3OF                     ((uint16_t)0x0800)

#define TIM_FLAG_CC4OF                     ((uint16_t)0x1000)


[OF为溢出]后面做研究!


对于这些CCR1在定时方面的应用我还没有想出什么好的点子,但是他确实存在,如果想验证的话,我们可以把周期设置长一点,比如设置为1s,然后通过设置CCR的值,来看看效果,呵呵,不过这是不容易实现的,因为CCRx 最大为0xffff = 65535跟72M比比,还能说什么?好吧,谁有什么好办法,可以跟我说下!


void tim_init(u32 period,u32 psc)

{

TIM_TimeBaseInitTypeDef tim;

TIM_OCInitTypeDef  TIM_OCInitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

tim.TIM_Period = period;

  tim.TIM_Prescaler = psc;

  tim.TIM_ClockDivision = 0;

  tim.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &tim);

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OCInitStructure.TIM_Pulse = 1*period/4;

  TIM_OC2Init(TIM2, &TIM_OCInitStructure);

TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Disable);

TIM_OCInitStructure.TIM_Pulse = 2*period/4;

  TIM_OC3Init(TIM2, &TIM_OCInitStructure);

TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Disable);

TIM_OCInitStructure.TIM_Pulse = 3*period/4;

  TIM_OC4Init(TIM2, &TIM_OCInitStructure);

TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Disable);

TIM_ITConfig(TIM2, TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4, ENABLE);

TIM_Cmd(TIM2,ENABLE);

 

  /* Enable the TIM2 global Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

 

  NVIC_Init(&NVIC_InitStructure);

}


void TIM2_IRQHandler(void)

{

static u32 cc2 = 0,cc3 = 0,cc4 = 0,cc5 = 0;

static u8 flag2 = 0,flag3 = 0,flag4 = 0,flag5 = 0;

u32 capture;

if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC2) == SET)

{

cc2 ++;

if(cc2 > 1000)

{

flag2 = ~flag2;

if(flag2) led_on(4);

else led_off(4);

cc2 = 0;

}

TIM_ClearFlag(TIM2,TIM_FLAG_CC2);

capture = TIM_GetCapture2(TIM2);

    TIM_SetCompare2(TIM2, capture + 255);

}

if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC3) == SET)

{

cc3 ++;

if(cc3 > 1000)

{

flag3 = ~flag3;

if(flag3) led_on(5);

else led_off(5);

cc3 = 0;

}

TIM_ClearFlag(TIM2,TIM_FLAG_CC3);

capture = TIM_GetCapture3(TIM2);

    TIM_SetCompare3(TIM2, capture + 500);

}

if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC4) == SET)

{

cc4 ++;

if(cc4 > 1000)

{

flag4 = ~flag4;

if(flag4) led_on(6);

else led_off(6);

cc4 = 0;

}

TIM_ClearFlag(TIM2,TIM_FLAG_CC4);

capture = TIM_GetCapture4(TIM2);

    TIM_SetCompare4(TIM2, capture + 725);

}

if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update) == SET)

{

cc5 ++;

if(cc5 > 1000)

{

flag5 = ~flag5;

if(flag5) led_on(7);

else led_off(7);

cc5 = 0;

}

TIM_ClearFlag(TIM2,TIM_FLAG_Update);

}

}

关键字:STM库  stm32  TIM  通用定时器 引用地址:【STM库应用】stm32 之 TIM (详解一 通用定时器)

上一篇:【菜鸟入门】stm32 之 ADC 模数转换
下一篇:【菜鸟入门】stm32 之 iic

推荐阅读最新更新时间:2024-11-24 08:47

STM32:ADC采集数据实例(采用DMA模式)
SOC:STM32F103RCT6 软件平台:STM官方库V3.5.0 开发工具:Keil 1. 摘要 本文章将给出STM32F103RCT6控制AT24C02的代码。如有疑问和错误,欢迎留言告之。 2.硬件连接 AT24C02使用I2C进行数据访问,板子上使用STM32的I2C控制器2和AT24C02进行连接。 具体来说,PB10作为SCL和AT24C02相连,PB11作为SDL和AT24C02相连。 这里就不给出硬件连接图了,比较简单。 3. AT24C022C访问代码(轮询) I2C这里使用轮询方法,不是中断,请留意。 首先,给出I2C控制器的初始化代码,和读写代码,一共三个函数,对应三个功能。 注意
[单片机]
stm32 hal 读写字节代码
void Single_WriteI2C(uint8_tREG_Address,uint8_t REG_data)//写入一个字节的代码 { uint8_t TxData = {REG_Address,REG_data}; while(HAL_I2C_Master_Transmit(&hi2c1,0xa6,(uint8_t*)TxData,2,1000)!= HAL_OK) { if (HAL_I2C_GetError(&hi2c1) !=HAL_I2C_ERROR_AF) { Error_Handler(); } }
[单片机]
stm32实用循环buffer
本人在实际开发中多次用到串口的循环buffer,最开始在网上搜索了相关文章和资料,感觉通用性不是很高。自己也写过fifo,感觉还是过于臃肿。一直想找个完美的循环buffer。在看linux内核代码时,发现内核里面也经常使用fifo。linux内核代码是最优美、精简的,高效的代码。真是“山穷水尽疑无路,柳暗花明又一村”。特意移植除出来,希望对大家有用。代码设计的相当的巧妙~~~ 头文件: /******************************************************************************* * @File : fifo.h * @Author : cqx * @
[单片机]
stm32 起步 gpio操作
在工程中增加gpio lib.h和stm32头文件,如下: #include “stm32f10x.h” // Device header #include “stm32f10x_gpio.h” 调用lib配置gpio工作方式,先开启时钟,选GPIO,设置GPIO mode,gpio speed,主要看GPIO_InitTypeDef 结构体,芯片不同结构体不同,开始不清楚具体使用可以参考系统自带的example code,my setting如下: void GPIO_Initmain(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Configure all
[单片机]
关于STM32发送中断的一些问题
SECTION 2 先说TC。即Transmission Complete。发送一个字节后才进入中断,这里称为“发送后中断”。和原来8051的TI方式一样,都是发送后才进中断,需要在发送函数中先发送一个字节触发中断。发送函数如下 /******* 功能:中断方式发送字符串.采用判断TC的方式.即 判断 发送后中断 位. 输入:字符串的首地址 输出:无 *******/ void USART_SendDataString( u8 *pData ) { pDataByte = pData; USART_ClearFlag(USART1, USART_FLAG_TC);//清除传输完成标志位,否则可能会丢失第1个字节的数
[单片机]
Stm32矩阵键盘扫描程序分析
我们知道在51单片机中,通过扫描某个口的电平高低得知那个按键按下,比如,控制两行4列, 假如让P1=0xCf;低位都置1 (pb0-pb3),pb4-pb5置0;然后我们就扫描P1口就行了,如果有按键被按下的,高电平会被强制拉低的。 假如按键返回的值为0xce,可知是pb0被拉低了,由此可判断是S1或者S2按下了,其他的同理。 当然只让P1=0xcf,是不能判断出具体的按键是哪个的,此时,如果我们取反既P1=0x30; 当按键返回值为0x10时,我们可得知01 0000,pb5=0,s1或者s2被按下,这个时候我们将0xce|0x10=0xde,就是唯一的值了。以此类推,得出其他的值来。 在stm32中是同样的大道
[单片机]
<font color='red'>Stm32</font>矩阵键盘扫描程序分析
STM32控制三轴加速度传感器实现分析
买的stm32F107VC开发板,带三轴加速度传感器LIS302DL,附带的示例代码。学习了几天,总结如下。 1。逻辑结构 初始化各外设(RCC,GPIO,SPI,NVIC,I2C,LCD) 检测MEMS并显示检测状态 在死循环中不断查询加速度值并描画。 2。硬件原理 与该程序相关的硬件连接图: MEMS连接图 MEMS引出脚与MCU(左)、IO扩展(右下)连接图 LCD连接图 LCD引出脚与MCU(左)、IO扩展(右上)连接图 从图中可以看出,MEMS使用I2C接口SCL和SDA连接MCU;LCD使用SPI3接口连接MCU。
[单片机]
<font color='red'>STM32</font>控制三轴加速度传感器实现分析
STM32 F0:演绎MCU领域的物种进化论
“今天我们主要谈一谈遗传方面的东西。”若听到意法半导体的微控制器全球市场部总监Daniel Colonna的嘴里说出这句话,定是觉得一头雾水。没错,在意法半导体5月15日举办的新品发布会上谈论的就是这个话题。主角就是意法半导体要隆重推出的针对低端应用的STM32 F0系列入门型微控制器,那这又跟遗传学扯上什么关系了呢? 意法半导体的STM32家族又添新军,8位微控制器的终结者STM32 F0系列微控制器,基于超低功耗的ARM Cortex-M0架构,以彻底消除8/16位在应用上的局限性和性能差距为终极目标,可简化家电和工业控制应用开发任务。更重要的是,STM32 F0不仅仅是填补了STM32在低端应用领域的空缺,更是ST
[单片机]
<font color='red'>STM32</font> F0:演绎MCU领域的物种进化论
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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