stm32定时器参考资料.docx
- 文档编号:11434213
- 上传时间:2023-03-01
- 格式:DOCX
- 页数:104
- 大小:64.50KB
stm32定时器参考资料.docx
《stm32定时器参考资料.docx》由会员分享,可在线阅读,更多相关《stm32定时器参考资料.docx(104页珍藏版)》请在冰豆网上搜索。
stm32定时器参考资料
一、 本课内容概述
这一课的主要内容是STM32系统时钟定时器systick的配置以及如何产生精确延时。
通常实现Delay(N)函数的方法为:
for(i = 0; i <= x; i ++);
x --- 对应于 对应于N 毫秒的循环值
对于STM32系列微处理器来说,执行一条指令只有几十个ns,进行for循环时,要实现N毫秒的x值非常大,而且由于系统频率的宽广,很难计算出延时N毫 秒的精确值。
针对STM32微处理器,需要重新设计一个新的方法去实现该功能,以实现在程序中使用Delay(N)。
注:
全局变量TimingDelay 必须定义为volatile
二、 SysTick的配置使用方法
外部晶振为8MHz,9倍频,系统时钟为72MHz,SysTick的最高频率为9MHz(最大为HCLK/8),在这个条件下,把SysTick 效验值设置成9,将SysTick 时钟设置为9MHz, 就能够产生1us的时间基值,即SysTick产生1us的中断。
使用ST的函数库使用systick的方法
1、调用SysTick_CounterCmd() 失能SysTick计数器
2、调用SysTick_ITConfig () 失能SysTick中断
3、调用SysTick_CLKSourceConfig() 设置SysTick时钟源。
4、调用SysTick_SetReload() 设置SysTick重装载值。
5、调用SysTick_ITConfig () 使能SysTick中断
6、调用SysTick_CounterCmd() 开启SysTick计数器
7、去掉stem32f10x_conf.c文件里面关于SysTick的注释,包含编译相关文件
8、在FWLIB里面加入stm32f10x_systick.c
9、修改工程设置,把中断向量表指向FLASH空间:
project-option-C/C++ Complier-Processor-Defined symbols改为VECT_TAB_FLASH
相关程序
1.
(1)建立systick.c文件
2.新建systick.c文件,作为systick相关函数的子函数,子函数里面应包括:
SysTick_Init,SysTickDelayUs, TimingDelayMs_Decrement三个函数,由于程序用到一个存放中断计数值的全局变量,而我们将次变量与main.c文件中定义,因此还要在这个文件中做外部引用定义:
extern vu32 TimingDelay;,再把系统初始化头文件包括,就完成了此文件的建立:
#include "systemInit.h"。
3.
(2)修改systemInit.h文件
4.由于在其他C文件中要用到systick.c定义的一些函数,因此我们在systemInit.h中进行外部函数声明:
5.extern void SysTick_Init(void);
6.extern void SysTickDelayUs(u32);
7.extern void TimingDelay_Decrement(void);
8.(3)修改中断文件stm32f10x_it.c
9.由于我们用到了systick系统时钟计数器中断计数的方法来产生延时,因此,我们必须在此文件中修改相应的中断函数,打开stm32f10x_it.c找到相应的函数,加入中断计数函数。
10.
11.void SysTickHandler(void)
12.{
13. TimingDelay_Decrement(); //中断计数函数
14.}
15.由于在此文件中调用了TimingDelay_Decrement()函数,因此必须将对此函数进行了外部声明的头文件systemIni.h包括进来:
16.
17.#include "stm32f10x_it.h"
18.#include "systemInit.h"
19.(3)修改main.c文件
20.由于使用了全局变量TimingDelay,因此要进行定义:
vu32 TimingDelay;,而要完成sistick的初始化,我们要在系统初始化总程序System_Init()里引用SysTick_Init();函数。
21.根据需要编写我们的应用主程序,给出一个实现流水灯的例程:
22.
23.int main(void)
24.{
25. System_Init();
26. while
(1)
27. {
28. LED1_H;
29. SysTickDelayUs(500000);
30. LED1_L;
31. SysTickDelayUs(500000);
32. LED2_H;
33. SysTickDelayUs(500000);
34. LED2_L;
35. SysTickDelayUs(500000);
36. LED3_H;
37. SysTickDelayUs(500000);
38. LED3_L;
39. SysTickDelayUs(500000);
40. LED4_H;
41. SysTickDelayUs(500000);
42. LED4_L;
43. SysTickDelayUs(500000);
44. }
45.}
46.#include "systemInit.h"
47.extern vu32 TimingDelay;
48.SysTick 初始化函数
49.
50.//SysTick设置
51.void SysTick_Init(void)
52.{
53.
54. SysTick_CounterCmd(SysTick_Counter_Disable);
55.
56.
57. SysTick_ITConfig(DISABLE);
58.
59.
60. SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
61.
62. SysTick_SetReload(9);
63.
64. SysTick_ITConfig(ENABLE);
65.}
66.SysTickDelayMs 延迟一微秒函数
67.
68.void SysTickDelayUs(u32 nTime)
69.{
70.
71. SysTick_CounterCmd(SysTick_Counter_Enable);
72.
73. TimingDelay = nTime;
74. while(TimingDelay !
= 0);
75.
76. SysTick_CounterCmd(SysTick_Counter_Disable);
77.
78. SysTick_CounterCmd(SysTick_Counter_Clear);
79.}
80.TimingDelayMs_Decrement 中断调用函数
81.
82.void TimingDelay_Decrement(void)
83.{
84. if (TimingDelay !
= 0x00)
85. {
86. TimingDelay--;
87. }
88.}
89.SysTickHandler 中断进入函数
90.
91.void SysTickHandler(void)
92.{
93. TimingDelay_Decrement();
94.}
95.NVIC_Configuration 中断向量表配置
96.
97.void NVIC_Configuration(void)
98.{
99.#ifdef VECT_TAB_RAM
100.
101. NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
102.#else
103.
104. NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
105.#endif
106.}
对定时器的基本配置
TIM_TimeBaseStructure.TIM_Period=1000;//设置自动装载寄存器
TIM_TimeBaseStructure.TIM_Prescaler=35999;//分频计数
TIM_TimeBaseStructure.TIM_ClockDivision=0;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;//选择向上计数
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
TIM_Cmd(TIM2,ENABLE);//是能定时器
始能定时器的中断:
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
在开启时钟里一定要打开TIM2的时钟,函数表达式如下:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
4:
中断向量函数的编写:
voidNVIC_Configuration(void)
{
NVIC_InitTypeDefNVIC_InitStructure;
#ifdefVECT_TAB_RAM//如果程序在ram中调试那么定义中断向量表在Ram中否则在Flash中
/*SettheVectorTablebaselocationat0x20000000*/
NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);
#else/*VECT_TAB_FLASH*/
/*SettheVectorTablebaselocationat0x08000000*/
NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);
#endif
/*EnabletheTIM2globalInterrupt*/
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
5:
中断函数的编写:
当有TIM2的无论哪个中断触发中断发生那么就会进入这个函数
TIM2_IRQHandler(void)
所以这个更新事件的中断判断要依靠以下语句:
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
按照以上步骤配置可以顺利进行定时器的基本定时应用
第二种方法:
/*EnableTIM2Updateinterrupt[TIM2溢出中断允许]*/
TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE);
中断中的设置为:
if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!
=RESET)
STM32定时器定时时间的计算
假设系统时钟是72Mhz,TIM1是由PCLK2(72MHz)得到,TIM2-7是由PCLK1得到
关键是设定时钟预分频数,自动重装载寄存器周期的值
/*每1秒发生一次更新事件(进入中断服务程序)。
RCC_Configuration()的SystemInit()的
RCC->CFGR|=(uint32_t)RCC_CFGR_PPRE1_DIV2表明TIM3CLK为72MHz。
因此,每次进入中
断服务程序间隔时间为
((1+TIM_Prescaler)/72M)*(1+TIM_Period)=((1+7199)/72M)*(1+9999)=1秒*/
定时器的基本设置
1、 TIM_TimeBaseStructure.TIM_Prescaler=7199;//时钟预分频数 例如:
时
钟频率=72/(时钟预分频+1)
2、TIM_TimeBaseStructure.TIM_Period=9999;//自动重装载寄存器周期的值(定时
时间) 累计0xFFFF个频率后产生个更新或者中断(也是说定时时间到)
3、 TIM_TimeBaseStructure.TIM_CounterMode= TIM1_CounterMode_Up;//定时器
模式 向上计数
4、TIM_TimeBaseStructure.TIM_ClockDivision=0x0;//时间分割值
5、TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);//初始化定时器2
6、TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //打开中断 溢出中断
7、TIM_Cmd(TIM2,ENABLE);//打开定时器
或者:
TIM_TimeBaseStructure.TIM_Prescaler=35999;//分频35999 72M/
(35999+1)/2=1Hz 1秒中断溢出一次
TIM_TimeBaseStructure.TIM_Period=2000;//计数值2000
((1+TIM_Prescaler)/72M)*(1+TIM_Period)=((1+35999)/72M)*(1+2000)=1秒*/
STM32中断优先级和开关总中断
一,中断优先级:
STM32(Cortex-M3)中的优先级概念
STM32(Cortex-M3)中有两个优先级的概念——抢占式优先级和响应优先级,有人把响应优先级称作'亚优先级'或'副优先级',每个中断源都需要被指定这两种优先级。
具有高抢占式优先级的中断可以在具有低抢占式优先级的中断处理过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以嵌套低抢占式优先级的中断。
当两个中断源的抢占式优先级相同时,这两个中断将没有嵌套关系,当一个中断到来后,如果正在处理另一个中断,这个后到来的中断就要等到前一个中断处理完之后才能被处理。
如果这两个中断同时到达,则中断控制器根据他们的响应优先级高低来决定先处理哪一个;如果他们的抢占式优先级和响应优先级都相等,则根据他们在中断表中的排位顺序决定先处理哪一个。
既然每个中断源都需要被指定这两种优先级,就需要有相应的寄存器位记录每个中断的优先级;在Cortex-M3中定义了8个比特位用于设置中断源的优先级,这8个比特位可以有8种分配方式,如下:
所有8位用于指定响应优先级
最高1位用于指定抢占式优先级,最低7位用于指定响应优先级
最高2位用于指定抢占式优先级,最低6位用于指定响应优先级
最高3位用于指定抢占式优先级,最低5位用于指定响应优先级
最高4位用于指定抢占式优先级,最低4位用于指定响应优先级
最高5位用于指定抢占式优先级,最低3位用于指定响应优先级
最高6位用于指定抢占式优先级,最低2位用于指定响应优先级
最高7位用于指定抢占式优先级,最低1位用于指定响应优先级
这就是优先级分组的概念。
--------------------------------------------------------------------------------
Cortex-M3允许具有较少中断源时使用较少的寄存器位指定中断源的优先级,因此STM32把指定中断优先级的寄存器位减少到4位,这4个寄存器位的分组方式如下:
第0组:
所有4位用于指定响应优先级
第1组:
最高1位用于指定抢占式优先级,最低3位用于指定响应优先级
第2组:
最高2位用于指定抢占式优先级,最低2位用于指定响应优先级
第3组:
最高3位用于指定抢占式优先级,最低1位用于指定响应优先级
第4组:
所有4位用于指定抢占式优先级
可以通过调用STM32的固件库中的函数NVIC_PriorityGroupConfig()选择使用哪种优先级分组方式,这个函数的参数有下列5种:
NVIC_PriorityGroup_0=>选择第0组
NVIC_PriorityGroup_1=>选择第1组
NVIC_PriorityGroup_2=>选择第2组
NVIC_PriorityGroup_3=>选择第3组
NVIC_PriorityGroup_4=>选择第4组
接下来就是指定中断源的优先级,下面以一个简单的例子说明如何指定中断源的抢占式优先级和响应优先级:
//选择使用优先级分组第1组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//使能EXTI0中断
NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//指定抢占式优先级别1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;//指定响应优先级别0
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
//使能EXTI9_5中断
NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//指定抢占式优先级别0
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//指定响应优先级别1
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
要注意的几点是:
1)如果指定的抢占式优先级别或响应优先级别超出了选定的优先级分组所限定的范围,将可能得到意想不到的结果;
2)抢占式优先级别相同的中断源之间没有嵌套关系;
3)如果某个中断源被指定为某个抢占式优先级别,又没有其它中断源处于同一个抢占式优先级别,则可以为这个中断源指定任意有效的响应优先级别。
二,开关总中断:
在STM32/Cortex-M3中是通过改变CPU的当前优先级来允许或禁止中断。
PRIMASK位:
只允许NMI和hardfault异常,其他中断/异常都被屏蔽(当前CPU优先级=0)。
FAULTMASK位:
只允许NMI,其他所有中断/异常都被屏蔽(当前CPU优先级=-1)。
在STM32固件库中(stm32f10x_nvic.c和stm32f10x_nvic.h)定义了四个函数操作PRIMASK位和FAULTMASK位,改变CPU的当前优先级,从而达到控制所有中断的目的。
下面两个函数等效于关闭总中断:
voidNVIC_SETPRIMASK(void);
voidNVIC_SETFAULTMASK(void);
下面两个函数等效于开放总中断:
voidNVIC_RESETPRIMASK(void);
voidNVIC_RESETFAULTMASK(void);
上面两组函数要成对使用,不能交叉使用。
例如:
第一种方法:
NVIC_SETPRIMASK(); //关闭总中断
NVIC_RESETPRIMASK();//开放总中断
第二种方法:
NVIC_SETFAULTMASK(); //关闭总中断
NVIC_RESETFAULTMASK();//开放总中断
常常使用
NVIC_SETPRIMASK(); //DisableInterrupts
NVIC_RESETPRIMASK(); //EnableInterrupts
STM32时钟系统
STM32资料 2009-09-2314:
53 阅读72 评论0
字号:
大大 中中 小小
在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。
①、HSI是高速内部时钟,RC振荡器,频率为8MHz。
②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
③、LSI是低速内部时钟,RC振荡器,频率为40kHz。
④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
⑤、PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。
倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。
图1HSE/LSE时钟源
其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。
另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。
RTC的时钟源通过RTCSEL[1:
0]来选择。
STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- stm32 定时器 参考资料