STM32学习笔记一时钟和定时器

发布者:张延强最新更新时间:2016-05-25 来源: eefocus关键字: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学习笔记一时钟和定时器

上一篇:LPC1768之系统滴答定时器
下一篇:STM32系统滴答_及不可不知的延时技巧上

推荐阅读最新更新时间:2024-03-16 14:54

解决STM32单片机的ADC采样不准确偏移的问题
项目场景: 用STM32CubeMX生成的ADC采样测量电压。 单片机:STM32G070 MDK:V5.25 问题描述: 采样回来的数值Debug看总是大了些许,几个通道都是这样,具体测试情况如下: 原因分析: 翻阅对比官方历程检查发现没有ADC校准,STM32CubeMX不会自动帮你配置校准。 /* Run the ADC calibration */ if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) { /* Calibration Error */ Error_Handler(); } /* USER CODE END 2 */ /*
[单片机]
解决<font color='red'>STM32</font>单片机的ADC采样不准确偏移的问题
STM32系列微控制器开发工具与应用——keil
STM32微处理器基于ARM核,所以很多基于ARM嵌入式开发环境都可用于STM32开发平台。开发工具都可用于STM32开发。选择合适的开发环境可以加快开发进度,节省开发成本。本章将先对STM32常用的开发工具Keil MDK和IAR EWARM进行简单介绍,然后结合STM32_SK仿真评估板和STM32F103C的开发板讲解STM32片上资源使用,最后给出一个基于STM32的数据采集器的应用实例。 5.1 Keil MDK介绍 Keil是德国知名软件公司Keil(现已并入ARM 公司)开发的微控制器软件开发平台,是目前ARM内核单片机开发的主流工具。Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器在内的
[单片机]
<font color='red'>STM32</font>系列微控制器开发工具与应用——keil
STM32高级开发(1)-开源是什么
开源的历史及简介 在上个世纪计算机发展的早期阶段,软件几乎都是开放的,任何人使用软件的同时都可以查看软件的源代码,或者根据自己的需要去修改它。在程序员的社团中大家互相分享软件,共同提高知识水平。这种自由的风气给大家带来了欢乐,也带来了进步。 但不久之后,以微软为主的一些商业公司就破坏了这种风气。这些商业公司从自由的计算机社团里雇佣了大量的技术高手,开发带有知识产权保护的专有软件。他们在分发软件的时候也不再附带源代码。从此,专有软件的时代到来了。直到现在,专有软件不公开源代码仍是默认的行业潜规则。 即使这样,崇尚自由的斗士们也没有妥协。他们认为,数字时代本应是自由的,任何人都可以自由的获取软件资源及其源代码,而不应该被少数
[单片机]
<font color='red'>STM32</font>高级开发(1)-开源是什么
I2C之知(三)--I2C总线的字节格式、时钟同步和仲裁
        字节格式         发送到SDA线上的每个字节必须是8位.每次传输的字节数量是不受限制的.每个字节后必须跟着一个ACK应答位.数据从最高有效位(MSB)开始传输.如果从机要执行一些功能后才能接收或者发送新的完整数据,比如说服务一个内部中断,那么它可以将时钟线SCL拉低来强制使主机进入wait状态.当从机准备好新的字节数据传输时,释放时钟线SCL,数据传输便继续进行.         ACK和NACK         每个字节后都有ACK发生.ACK应答位允许接收器通知发送器字节成功接收了下一个字节可以发送了.主机产生所有的时钟脉冲,包括应答位的第9个时钟脉冲. ACK应答信号是如下定义的:在ACK的第9
[嵌入式]
STM32 I2C上拉电阻的选择问题
从开源的设计中我们可以看到,I2C的上拉电阻可以是1.5K,2.2K,4.7K,然而电阻的大小对时序有一定影响,对信号的上升时间和下降时间也有影响,一般接1.5K 或2.2K。 上拉电阻阻值的确定: 由于I2C 接口采用Open Drain 机制,器件本身只能输出低电平,无法主动输出高电平,只能通过外部上拉电阻RP 将信号线拉至高电平。因此I2C 总线上的上拉电阻是必须的! RP 不宜过小,一般不低于1KΩ。 一般IO 端口的驱动能力在2mA~4mA 量级。如果RP 阻值过小,VDD 灌入端口的电流将较大,这导致端口输出的低电平值增大(I2C 协议规定,端口输出低电平的最高允许值为0.4V);如果灌入端口的电流过大,还可能损坏
[单片机]
UCOSIII简介于移植
UCOSIII简介 UCOSIII是一个可裁剪,可固化,可剥夺的多任务系统。相比于前代产品其最大任务数目没有限制,优先级相同的任务数目没有限制且有无需调度的的发送机制。 UCOSIII文件 在移植UCOSIII之前我们需要准备两样东西:一个是UCOSIII的源码,一个是Micrium官方在STM32F1xx上移植好的工程文件。 在Micrium文件夹中有四个文件夹 1、EvaBoards文件夹 这个文件夹里面就是关于STM32F107的工程文件。其中的处app.c和stm32f10x_conf.h外的文件的八个文件使我们需要添加到工程文件当中的。 2、uC-CPU文件夹 这个文件夹里面是与CPU相关的代码,有下面几个文
[单片机]
LPC1114/LPC11U14和LPC1343对比学习(四)定时器
这三种芯片都有2个16位的定时器和2个32位的定时器。这4个定时器的功能都非常强大,不在是像8051一样,只有定时与计数功能。除了这两个强大的功能外,还添加了匹配输出,捕获输入,PWM输出等。在这里我们只学习它们最基本的定时功能,对于其他功能就不作介绍。 在PWM模式下,2个32位可编程定时器/计数器均有3个匹配寄存器用于提供单边沿的PWM输出,剩下的那个匹配寄存器则用于控制PWM周 期长度。在PWM模式下,16位定时器0(CT16B0)与32位定时器相同,而16位定时器1(CT16B1)只有其中的两个匹配可用于向匹配输出管脚 提供单边沿的PWM输出。 在这4个定时器中,基本操作是一模一样的,所以在下面我们只拿一个定时器作为实例进
[单片机]
LPC1114/LPC11U14和LPC1343对比<font color='red'>学习</font>(四)<font color='red'>定时器</font>
如何有效地使用串口通讯接收数据
引言 在使用stm32或者其他单片机的时候,会经常使用到串口通讯,那么如何有效地接收数据呢?假如这段数据是不定长的有如何高效接收呢? 同学A:数据来了就会进入串口中断,在中断中读取数据就行了! 中断就是打断程序正常运行,怎么能保证高效呢?经常把主程序打断,主程序还要不要运行了? 同学B:串口可以配置成用DMA的方式接收数据,等接收完毕就可以去读取了! 这个同学是对的,我们可以使用DMA去接收数据,不过DMA需要定长才能产生接收中断,如何接收不定长的数据呢? DMA简介 题外话:其实,上面的问题是很有必要思考一下的,不断思考,才能进步。 什么是DMA DMA :全称Direct Memory Access,即直接存储器访问
[单片机]
如何有效地使用串口通讯接收数据
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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