| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> STM32时钟系统和TIMER配置(溢出中断/PWM)实例 -> 正文阅读 |
|
[嵌入式]STM32时钟系统和TIMER配置(溢出中断/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输出低电平,由此可知通过改变比较值的大小就可以改变定时器的占空比。 ????????????????????????????????????????????????????????????????图2 (3)Cube配置 ? ? ? ? ?选中左侧相应定时器,选中右侧的Activated(某些定时器设置开启选项是把Clock source选择为Internal Clock),然后选中PWM Generation CH1。 ? ? ? ? 参数那里PSC选择72-1,即计数频率是1MHz,即计数一次1us,ARR值为1000-1,即1000us响应一次中断,也就是1ms一次中断,中断频率就是1/0.1s=1000Hz。 ? ? ? ? 1000Hz的频率肉眼是看不出来的,最后就是定时器某个通道对应的GPIO输出引脚要配置为TIMx_CHx,假如定时器2的通道2作为PWM输出,那么就需要把定时器2通道2对应的GPIO复用功能配置为TIM2_CH2。 (4)代码编写 ? ? ? ? 打开定时器PWM,HAL_TIM_WM_Start(&htimx,TIM_CHANNEL_2); 然后通过调用下面函数修改比较值,从而修改了占空比,从而实现亮度的控制。下面是常用读写定时器的相关函数: 重装载值ARR设置:__HAL_TIM_SetAutoreload 获取当前重装载值:__HAL_TIM_GetAutoreload 设置计数值:__HAL_TIM_SetCounter 获取当前计数值:__HAL_TIM_GetCounter 设置比较值:__HAL_TIM_SetCompare(&htimx,TIM_CHANNEL_2,比较值);? 获取当前比较值:__HAL_TIM_GetCompar ? ? ? ? 如何让LCD或LED的亮度变亮呢,只需要不断增加PWM高电平持续时间,即让duty不断增加即可。我们设置重装载值为1000,根据图2所示,只需要让比较值在0-1000之间不断增加,那么duty就会不断增加实现逐渐变亮的效果。 ? ? ? ? 同理,让比较值从1000-0不断减少,就能实现灯不断变暗。需要注意的是,如果用一个循环让比较值不断增加或减少,那么最好对每一次循环做1ms的延时,这样肉眼才容易看到灯的变亮或变暗的效果。 (5)影子寄存器 |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 | -2024/12/28 0:56:26- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |
数据统计 |