当前位置: 首页 > news >正文

STM32时钟系统和TIMER配置(溢出中断/PWM)实例

目录:

1. STM32时钟系统

2. STM32的定时器典型配置之溢出中断

3. STM32的定时器典型配置之PWM输出

1. STM32时钟系统

(1)Clock tree

        可以在官方手册(Stm32x-series-Reference-manual)的clock tree中可以对相应MCU的时钟系统有个大致了解。

        也可以从中了解到STM32哪些外设挂在哪一条总线上,然后根据Cube中配置的时钟频率和各种分频就可以得到各总线的时钟频率,注意挂在这些总线上的外设还需要在配置时经过分频得到外设的时钟频率。

(2)STM32总线与时钟配置

        假如STM32时钟源为HSE高速外部晶振,HSE一般为8MHz,经过x分频和y倍频后得到系统时钟,即PLLCLK = (8/x)*y MHz。

        AHB总线上时钟由系统时钟PLLCLK经过z分频得到,HCLK = PLLCLK/z。

        APB2上的总线时钟PCLK2经过HCLK的m分频得到,PCLK2 = HCLK/m。

        APB1上的总线时钟PCLK1经过HCLK的n分频得到,PCLK1 = HCLK/n。

外设时钟举例: 挂在高速总线APB2上的ADC时钟经过APB2总线时钟2分频得到,即ADCCLK = PCLK2/2 。

外设时钟举例:挂在低速总线APB1上的TIM2时钟经过APB1总线时钟2分频得到,即TIM2CLK = PCLK1/2 。

2. STM32的定时器典型配置之溢出中断

(1)定时器分类

        STM32的物理定时器解决了MCU单任务运行使用CPU计数对性能的影响,定时器根据功能从多到少分为高级定时器、通用定时器、基本定时器。低功耗定时器、看门狗定时器、某些MCU还有HRTIM等。

(2)定时器挂在哪条总线上

        以STM32F10x系列的MCU为例,TIM1/8挂在APB2高速总线上,TIM2-7挂在APB1低速总线上。

 (3)定时器初始时钟频率

        有人说如果APB1和APB2经过HCLK都进行1分频,那么TIM1/8的时钟为APB2的时钟,TIM2-7的时钟为APB1的时钟。

        如果APB1和APB2经过HCLK进行分频,分频系数不为1,那么TIM1/8的时钟为APB2时钟的两倍,TIM2-7为APB1的时钟的两倍。

        在实际应用中,要根据不同的MCU和时钟系统配置得到相应定时器的初始时钟频率。

 (4)定时器计数时钟频率

        所谓计数时钟频率,就是上面提到每种外设具体时钟频率还要经过外设本身的外设分频(PSC)配置,从而得到最终定时器时钟频率,这个频率就是定时器每计数一次花的时间。

(5)在CubeMX中定时器的配置

        下面是对TIM2配置的实例:

                                                                        图1

         选中左侧TIM2,然后在Clock Source选择Internal Clock,在下面Parameter Settings处就会展示出相关参数,主要需要配置PSC,Mode,ARR值。

        PSC即Prescaler,预分频系数,就是上面第(4)点中提到的再次分频系数,基于第(3)点的时钟频率分频。比如要配置定时器每一微妙(最终定时器技术频率为1MHz)计数一次,那么首先看第(3)点的时钟频率是多少:

        从系统时钟树配置中可以看出,APB1总线时钟频率为72MHz,TIM2挂在APB1总线上,然后根据第(3)点的规则可知TIM2的初始频率为72MHz,那么要让TIM2的计数频率为1MHz,那么PSC就应该配置为72-1,这就是图1中72的由来。 注意这里是16bit位值,因此这个值不能超过65535,另外,STM32手册中提到这里PSC的值一定是你想要的值减1,可能是从0开始的吧,所以这里是72-1。

        Counter Mode可以选择计数模式,这里选择向上计数。

        Counter Period即上面提到的ARR值,即重装载值。即定时器计到这个值后响应一个事件(一般可以配置中断),然后重新开始计时。这个值也是有限制的,这里从图1中可以知道它是一个32bit的数。同样,由于TIM2是1us计数一次,如果我们希望500ms响应一次中断,那么就需要把ARR的值配置为500000,即TIM2计数500000次后响应中断,每次1us,500000刚好500ms。同样配置时的值是实际想要的值减1,即500000-1。

        如果要使用中断方式,需要配置中断:

         上图中可以选中TIM2的global interrupt,即使能了中断,然后根据实际应用配置中断优先级。                        

(6)Cube生成代码

        1) 开启定时器

        HAL_TIM_Base_Start_IT(&htimx); htimx是一个结构体变量,这里就是TIM2的句柄。这个函数的作用是开启定时器及溢出中断。

         HAL_TIM_Base_Stop_IT(&htimx); 这个函数是关闭定时器及溢出中断HAL库函数。

         HAL_TIM_Base_Start(&htimx); 这个函数是开启定时器,但是不开启中断的HAL库函数。

         HAL_TIM_Base_Stop(&htimx); 这个函数是关闭定时器的HAL库函数。

        2) 定时器中断处理函数

        当定时器的计数到达ARR的值后,就会产生溢出中断,最终调用到中断完成回调函数,我们一般都是会改写这个函数,在这个函数里面执行相应逻辑。根据上面的配置,这个回调函数将500ms调用一次。void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef * htim)

3. STM32的定时器典型配置之PWM输出

(1)PWM占空比

        什么是PWM呢,比如LCD背光就可以用PWM方式控制,当高电平时间比低电平时间长,那么肉眼感受到LCD亮的时间就比灭的时间长,如果继续减少低电平时间,甚至感受不到LCD有灭,那么通过这样的方式就可以实现LCD亮度控制。

        一般来说PWM都是方波,那么高电平和低电平持续时间构成一个周期,高电平持续时间处于周期*100%,就是占空比,即Duty值。

(2)定时器比较值

        一般比较值位于0到ARR重装载值之间,当定时器计数值处于0到比较值之间时,定时器的某个通道对应的GPIO输出高电平,如果计数值处于比较值到ARR重装载值之间,那么定时器的某个通道对应的GPIO输出低电平,由此可知通过改变比较值的大小就可以改变定时器的占空比。

 

(3)Cube配置

         选中左侧相应定时器,选中右侧的Activated(如果只有后Activated就选中,如果是其他选项就选中Internal Clock即可),然后选中PWM Generation CH1。

        参数那里PSC选择72-1,即计数频率是1MHz,即计数一次1us,ARR值为1000-1,即1000us响应一次中断,也就是1ms一次中断,中断频率就是1/0.1s=1000Hz。

        1000Hz的频率肉眼是看不出来的,最后就是GPIO要选择对。

(4)代码编写

        打开定时器PWM,HAL_TIM_WM_Start(&htimx,TIM_CHANNEL_2); 然后通过调用下面函数修改比较值,从而修改了占空比,从而实现亮度的控制。

        __HAL_TIM_SetCompare(&htimx,TIM_CHANNEL_2,比较值); 

相关文章:

  • 随想录一刷Day04——链表
  • 【javaweb简单教程】2.JSP实现数据传递和保存(含四大作用域及简单示例)
  • 7.ROS2笔记-节点
  • 【C++】类和对象(下篇)(万字)
  • 【牛客 - 剑指offer】JZ67 把字符串转换成整数 Java实现
  • python采集火热弹幕数据并做词云图可视化分析
  • 【小程序从0到1】模版与配置|数据绑定|事件绑定
  • NetSuite SuiteQL Query Tool
  • 功能异常强大,推荐这款 Python 时序异常检测神器
  • 串的存储结构 --王道
  • React路由规则的定义、声明式导航、编程式导航
  • Java_四种内部类
  • Java lang包简介说明
  • 推荐一款替代Navicat的MySQL数据库管理工具-HeidSQL
  • R语言使用lm函数构建分层线性回归模型(添加分组变量构建分层线性回归模型)、使用summary函数获取分层线性回归模型汇总统计信息
  • [译] 怎样写一个基础的编译器
  • Elasticsearch 参考指南(升级前重新索引)
  • es6
  • golang 发送GET和POST示例
  • Java 内存分配及垃圾回收机制初探
  • linux安装openssl、swoole等扩展的具体步骤
  • Nodejs和JavaWeb协助开发
  • ubuntu 下nginx安装 并支持https协议
  • Vue UI框架库开发介绍
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 技术胖1-4季视频复习— (看视频笔记)
  • 开源SQL-on-Hadoop系统一览
  • 扑朔迷离的属性和特性【彻底弄清】
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 微信公众号开发小记——5.python微信红包
  • scrapy中间件源码分析及常用中间件大全
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • $forceUpdate()函数
  • (1)(1.9) MSP (version 4.2)
  • (2020)Java后端开发----(面试题和笔试题)
  • (4)STL算法之比较
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (笔试题)分解质因式
  • (分布式缓存)Redis哨兵
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (六)软件测试分工
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • ***监测系统的构建(chkrootkit )
  • .NET 发展历程
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .NET/C# 避免调试器不小心提前计算本应延迟计算的值
  • .NET/C# 使用反射注册事件
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • @angular/cli项目构建--http(2)
  • @property @synthesize @dynamic 及相关属性作用探究
  • @基于大模型的旅游路线推荐方案
  • [20171101]rman to destination.txt
  • [2019.3.20]BZOJ4573 [Zjoi2016]大森林
  • [BZOJ1008][HNOI2008]越狱
  • [C++ 从入门到精通] 12.重载运算符、赋值运算符重载、析构函数