STM32学习笔记(一)时钟和定时器
由于近期在准备海洋航行器比赛,正好趁此机会学习一下ARM,看到周围很多同学都在使用32,所以我也买了一块STM32F103ZET6,准备好好地学习一下。
STM32的时钟系统相当的复杂,包含了5个时钟源,分别是HSI HSE LSI LSE PLL,HSI是高速内部时钟、RC振荡器,频率为8M,HSE是高速外部时钟,即晶振,我的核心板上晶振为8M。LSI为低速内部时钟、RC振荡器,频率40k,LSE为低速外部时钟,接32.768kHz晶振,作为RTC时钟源。PLL为锁相环倍频输出,最大不超过72M。
我在学习定时器时先看的是TIM3,它挂载在APB1分频器上,APB1上面挂载的是低速外设,APB2上挂载高速外设。
在system_stm32f10x.c文件下,有默认定义SYSCLK_FREQ_72MHz,同时在SystemInit()函数下调用了SetSysClock(),根据宏定义将时钟设为72M。
读取SystemCoreClock变量即可获得系统时钟频率。
在默认情况下,系统的各个时钟频率如下:
SYSCLK:72M
AHB:72M
APB1(PCLK1):36M
APB2(PCLK2):72M
PLL:72M
详细的定时器设定如下:
①首先要搞清楚定时器的计数时钟频率,在预分频系数≠1的时候,TIM2~7的时钟频率为APB1的2倍,即72MHz,预分频系数的默认值不是1,但我并未查到该如何设置该值。
②定时器的设置主要包括定时器的初始化和中断的初始化。
2.1 定时器初始化:
首先定义TIM_TimeBaseInitTypeDef类型的结构体,它包含了如下的内容:
typedef struct
{
uint16_t TIM_Prescaler;
uint16_t TIM_CounterMode;
uint16_t TIM_Period;
uint16_t TIM_ClockDivision;
uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
第一项TIM_Prescaler是预分频值,它与TIM_Period(重载周期值)的乘积即为计数的总值。
第二项TIM_CounterMode为计数模式,它的内容如下:
#define TIM_CounterMode_Up ((uint16_t)0x0000)
#define TIM_CounterMode_Down ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060)
后面三项为中心对齐模式,指的是计数到一定的值,产生溢出事件,再向下计数到0。常用的为向上计数模式,即TIM_CounterMode_Up
第四项TIM_ClockDivision为时钟分割,对于时钟分割没有查到太多的描述,一般设定为TIM_CKD_DIV1,或者直接填入0x0000。
第五项TIM_RepetitionCounter为PWM模式的一些设定,一般的定时器不用设置。
除此之外还要设置中断的类型,一般的定时器为更新中断,即由溢出事件产生的中断,设置的方式为:TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE),其中第一项是定时器代号,第二项为类型,这里设定为更新方式,第三项为使能。
根据上述内容我们知道,初始化的过程如下:
3
TIM_TimeBaseInitTypeDef TIM_STR;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//TIM3挂载在APB1上
//由于预分频系数默认不是1,所以TIM3的时钟为2*APB1=72M
TIM_STR.TIM_Period=arr;
TIM_STR.TIM_Prescaler=psc;
//(arr+1)*(psc+1)/TIM时钟=定时器溢出中断触发周期
TIM_STR.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_STR.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_STR);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
2.2 中断初始化:
中断初始化为操作NVIC(嵌套向量中断控制器)函数。 设置方式如下:
NVIC_STR.NVIC_IRQChannel=TIM3_IRQn;//设定为TIM3中断
NVIC_STR.NVIC_IRQChannelPreemptionPriority=0;//先占优先级0级
NVIC_STR.NVIC_IRQChannelSubPriority=3;//从优先级3级
NVIC_STR.NVIC_IRQChannelCmd=ENABLE;//IRQ通道时能
NVIC_Init(&NVIC_STR);//中断初始化
TIM_Cmd(TIM3,ENABLE);//TIM3定时器使能
2.3 把这些都封装成一个函数,既可作为TIM3的初始化函数。如下:
void TIM3_Init(u16 arr,u16 psc)
{
//定时时间=(arr+1)*(psc+1)/72 单位为us
TIM_TimeBaseInitTypeDef TIM_STR;
NVIC_InitTypeDef NVIC_STR;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
//初始化定时器
TIM_STR.TIM_Period=arr;
TIM_STR.TIM_Prescaler=psc;
TIM_STR.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_STR.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_STR);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
//初始化中断
NVIC_STR.NVIC_IRQChannel=TIM3_IRQn;
NVIC_STR.NVIC_IRQChannelPreemptionPriority=0;
NVIC_STR.NVIC_IRQChannelSubPriority=3;
NVIC_STR.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_STR);
//使能定时器
TIM_Cmd(TIM3,ENABLE);
}
③中断服务函数:
中断函数的名字,TIM3的为TIM3_IRQHandler
中断服务函数内包含了:判断是否发生中断、中断发生后执行的内容、清除标志位三部分。
首先是判断是否发生了更新中断,利用库函数TIM_GetITStatus(P1,P2),它的参数P1为代号,这里是TIM3,P2为中断类型,这里为更新中断TIM_IT_Update,当它为1时即发生了更新中断,这里为了增强可读性,采用一个RESET代表0,当函数返回值不是RESET的时候,即发生了置位(中断)。
清除标志位采用的是库函数TIM_ClearITPendingBit(P1,P2),参数与判断的函数一样。
具体函数如下:
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
//在这里执行中断内容
}
}
④完成调用
只要在main函数里调用TIM3_Init()函数,并填入适当的参数,即可实现精确的定时中断,例如获得一秒,即72M个数字中断一次,可分解为10000*7200,配置如下:
TIM3_Init(9999,7199);
STM32学习笔记(一)时钟和定时器的更多相关文章
- STM32学习笔记——OLED屏
STM32学习笔记--OLED屏 OLED屏的特点: 1. 模块有单色和双色可选,单色为纯蓝色,双色为黄蓝双色(本人选用双色): 2. 显示尺寸为0.96寸 3. 分辨率为128*64 4. ...
- STM32学习笔记——点亮LED
STM32学习笔记——点亮LED 本人学习STM32是直接通过操作stm32的寄存器,使用的开发板是野火ISO-V2版本: 先简单的介绍一下stm32的GPIO: stm32的GPIO有多种模式: 1 ...
- stm32学习笔记----双串口同时打开时的printf()问题
stm32学习笔记----双串口同时打开时的printf()问题 最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其 ...
- stm32学习笔记——外部中断的使用
stm32学习笔记——外部中断的使用 基本概念 stm32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组为一个单位的,同组间的外部中断同一时间只能使用一个.比如说,PA0,PB0 ...
- STM32学习笔记(四)——串口控制LED(中断方式)
目录: 一.时钟使能,包括GPIO的时钟和串口的时钟使能 二.设置引脚复用映射 三.GPIO的初始化配置,注意要设置为复用模式 四.串口参数初始化配置 五.中断分组和中断优先级配置 六.设置串口中断类 ...
- STM32学习笔记-NVIC中断知识点
STM32学习笔记-NVIC中断知识点总结 中断优先级设置步骤 1. 系统运行后先设置中断优先级分组 函数:void NVIC_PriorityGroupConfig(uint32_tNVIC_Pri ...
- STM32学习笔记之一(初窥STM32)
怎么做好学习笔记? 答:自我感知-->学习知识-->归纳总结-->自我升华(真正属于自己的知识是,抛开书本,运用时,你还能记得的思想) 自我感知--看到知识概念,先自我感觉那应该是个 ...
- STM32学习笔记(一)——点亮一个LED
引言 最近报名了2017全国大学生电子设计竞赛,我们学校是第一次参加这个比赛,由于8/9月份就要比赛了,所以现在准备是比较晚的了,指导老师说只能做控制类的题目了,让我们学习一下STM32单片机,51到 ...
- STM32学习笔记(二) 基于STM32-GPIO的流水灯实现
学会了如何新建一个工程模板,下面就要开始动手实践了.像c/c++中经典的入门代码"hello world"一样,流水灯作为最简单的硬件设备在单片机领域也是入门首推.如果你已经有了一 ...
- STM32学习笔记(二)——串口控制LED
开发板芯片:STM32F407ZGT6 PA9-USART1_TX,PA10-USART1_RX; PF9-LED0,PF10-LED1; 一.串口1配置过程(不使用串口中断): 1.使能时钟,包括G ...
随机推荐
- Oracle性能优化-读懂执行计划
Oracle的执行计划 得到执行计划的方式 Autotrace例子 使用Explain explain plan set STATEMENT_ID='testplan' for select * fr ...
- 用Netty解析Redis网络协议
用Netty解析Redis网络协议 根据Redis官方文档的介绍,学习了一下Redis网络通信协议.然后偶然在GitHub上发现了个用Netty实现的Redis服务器,很有趣,于是就动手实现了一下! ...
- Ubuntu使用dpkg安装软件依赖问题解决 ubuntu-tweak ubuntu 16.04 LTS 系统清理
Ubuntu使用dpkg安装软件依赖问题解决 这里以在ubuntu 16.04安装Ubuntu Tweak为例进行说明,通常安装包依赖问题都可以用这种方法解决: sudo apt-get instal ...
- 用Python最原始的函数模拟eval函数的浮点数运算功能(2)
这应该是我编程以来完成的难度最大的一个函数了.因为可能存在的情况非常多,需要设计合理的参数来控制解析流程.经验概要: 1.大胆假设一些子功能能够实现,看能否建立整个框架.如果在假设的基础上都无法建立, ...
- Web Service进阶(三)HTTP-GET, HTTP-POST and SOAP的比较
XML Web Service支持三种协议来与用户交流数据.这三种协议分别是: 1.SOAP:Simple Object Access Protocol 2.HTTP-GET 3.HTTP-POST ...
- 悲观的并发策略——Synchronized互斥锁
volatile既然不足以保证数据同步,那么就必须要引入锁来确保.互斥锁是最常见的同步手段,在并发过程中,当多条线程对同一个共享数据竞争时,它保证共享数据同一时刻只能被一条线程使用,其他线程只有等到锁 ...
- Eclipse打jar包,资源文件的读取
最近的工作中需要将java程序打一个jar包,然后在Linux中供调用.程序中需要读取一个配置文件.遇到了三个问题.第一个是依赖的第三方Jar包打成Jar包后找不到:第二个问题是资源文件所在的文件夹打 ...
- Dynamics CRM2013 用户进入系统所必需的那些权限
本篇以CRM2013为例,在CRM中新建一个安全角色后该安全角色基本是空的,如果新建的安全角色作为一个账号的唯一安全角色时,那这个安全角色除了需要配置业务场景所需的权限外,是要优先具备进入CRM系统的 ...
- 删除表中重复行SQL
delete from table_name a where rowid < (select max(rowid) from table_name b where a.col1 = b.col1 ...
- 剑指Offer——滴滴笔试题+知识点总结
剑指Offer--滴滴笔试题+知识点总结 情景回顾 时间:2016.9.18 15:00-17:00 地点:山东省网络环境智能计算技术重点实验室 事件:滴滴笔试 总体来说,滴滴笔试内容体量不算多, ...