前期准备:
STM32CubeMX
STM32RCT6核心板
IDE Keil(MDK-ARM)
STM32CubeMX部分
1. 配置时钟
选择STM32F103RCTx系列芯片,配置时钟的同时会自动配置IO口引脚
在这里插入图片描述
将HCLK设置为最大频率72MHz
在这里插入图片描述
2.配置TIM
在这里插入图片描述
Internal Clock(内部时钟)
Prtscaler (定时器分频系数) : 71
Counter Mode(计数模式) Up(向上计数模式)
Counter Period(自动重装载值) : 999
CKD(时钟分频因子) :No Division (不分频 )
auto-reload-preload(自动重装载) : Enable (使能)
在这里插入图片描述
勾选update interrupt(更新中断)
1. 定时器溢出时间计算公式:
在这里插入图片描述
Tout:中断溢出的时间
arr:自动重装载值
psc:定时器分频系数
Tclk:时钟频率
Tout = ((71+1)*(999+1))/72 us
Tout = ( 72 * 1000 ) / 72 us
1000us = 1ms
所以这里我们的定时时间为:1ms
也就是说单片机1ms进入一次定时器中断
2. 定时器计数模式:
向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
向上/向下计数模式(中央对齐模式):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
在这里插入图片描述
2. 计数时钟:
内部时钟(TIMx_CLK):
外部时钟模式1:外部捕捉比较引脚(TIx)
外部时钟模式2:外部引脚输入(TIMx_ETR)
内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
3.配置IO口
在这里插入图片描述
将PB0设置为:
低电平
Output模式
既不上拉也不下拉
响应速度低
4. 工程生成
在这里插入图片描述
在这里插入图片描述
工程管理依旧是这几个选项,然后GENERATE CODE,STM32CubeMX部分完成。
MDK 5部分
HAL_TIM_IRQHandler(htim1);//定时器中断处理函数
此函数的作用是判断中断是否正常,是哪一类定时器中断(溢出中断/捕获中断/PWM中断…),然后进入相应的中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器溢出中断回调函数
定时器中断时,每进行完一个中断,并不会立刻退出,而是会进入到中断回调函数中
点开main.c在这里插入图片描述
在如图位置上添加
HAL_TIM_Base_Start_IT(htim1);//开启定时器1
1
1
然后再tim.c文件中,添加
/* USER CODE BEGIN 0 */
uint16_t Tim_cnt = 0; //定时器计数
/* USER CODE END 0 */
1
2
3
1
2
3
然后在tim.c文件中重写
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)函数
在这里插入图片描述
/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim-Instance == htim1.Instance)
{
Tim_cnt++;
if(Tim_cnt==500) //0.5s进行一次下列代码
{
Tim_cnt=0; //清0
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
}
}
}
/* USER CODE END 1 */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
设一个全局变量,每进一次中断+1,因为1ms进入一次中断,所以当Tim_cnt=500的时候(即0.5s)写入我们需要运行的代码(不要忘记清0)
编译下载时需要选择相对应的下载器,勾选以下
在这里插入图片描述
运行即可
本期工程文档——Gitee
在这里插入图片描述
(1)STM32F40x系列总共最多有14个定时器。分有:
高级定时器:TIM1 和 TIM9;
通用定时器:TIM2~TIM5 , TIM9~TIM14;
基本定时器:TIM6 和 TIM7;
(2)计数器的三种模式:
1向上计数:计数器从零开始计数,一直计数到自动加载值(TIMx_ARR),然后重新从0开始计数,并产生一个计数器溢出事件;
2向下计数:计数器从自动装入的值(TIMx_ARR)开始,向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件;
3中央对齐模式(向上/向下计数模式):从0开始,计数到自动装入的值,产生一个计数器上溢出事件,然后向下计数到0,又产生一个计数器下溢出事件,然后又从0开始重新计数。
(1)计数器当前值寄存器 CNT
CNT是定时器的计数器,存储着当前定时器的计数值。
(2)预分频寄存器 TIMx_PSC
emsp该寄存器对时钟进行分频,然后提供给计数器,作为计数频率。PSC是16位寄存器,存储着预分频器值。计数器计数频率为时钟频率除以(PSC+1)。
注意:这里,定时器的时钟来源有4个:
1内部时钟(CK_INT)
2外部时钟模式1:外部输入脚(TIx)
3外部时钟模式2:外部触发输入(ETR)
4内部触发输入(ITRx):时钟级联,A为B提供时钟
(3)自动重装载寄存器 TIMx_ARR
ARR为要装载到实际自动重载寄存器的值。该寄存器在物理上对应着2个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,叫做“影子寄存器”。这里不做深入讨论。
(4)控制寄存器1 TIMx_CR1
16位寄存器,低10位有效。但是,我们仅关注其最低位(位0),称作CEN位,该位是计数器使能位,必须置1,才能让定时器开始计数。
(5)DMA中断使能寄存器 TIMx_DIER
16位寄存器,我们仅关心其最低位(位0),该位是更新中断允许位,要使用定时器中断的功能,那么该位要置1,来允许由于更新事件所产生的中断。
(6)状态寄存器 TIMx_SR
该寄存器用来标记当前与定时器相关的各种事件/中断是否发生。在这里,我们主要关注它的最低位(位0,UIF位),该位在发生更新事件时由硬件置1.但是需要通过软件清零。
(1)使能TIM3时钟
TIM3挂载在总线APB1之下,所以,需要使能相应的时钟。
(2)初始化定时器参数,设置自动装载值,分频系数,计数方式等
例如:
(3)设置TIM3_DIER允许更新中断
(4)中断优先级设置
(5)使能定时器
(5)编写中断服务函数
在中断产生后,通过状态寄存器的值,判断此次产生的是哪个类型的中断,然后在执行相关操作。在处理完中断之后,应该对SR寄存器的相应标志位清除。
01:中央对齐模式1 计数器交替地向上和向下计数。输出比较中断标志位,只在计数器向下计数时被设置
10:中央对齐模式2 计数器交替地向上和向下计数。输出比较中断标志位,只在计数器向上计数时被设置
11:中央对齐模式3 计数器交替地向上和向下计数。输出比较中断标志位,只在计数器向下和向上计数时均被设置
计数器三种计数模式
向上计数模式:从0开始,计到arr预设值,产生溢出事件,返回重新计时
向下计数模式:从arr预设值开始,计到0,产生溢出事件,返回重新计时
中央对齐模式:从0开始向上计数,计到arr产生溢出事件,然后向下计数,计数到1以后,又产生溢出,然后再从0开始向上计数。(此种技术方法也可叫向上/向下计数)
基本定时器(TIM6,TIM7)的主要功能:
只有最基本的定时功能,。基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动
通用定时器(TIM2~TIM5)的主要功能:
除了基本的定时器的功能外,还具有测量输入信号的脉冲长度( 输入捕获) 或者产生输出波形( 输出比较和PWM)
高级定时器(TIM1,TIM8)的主要功能:
高级定时器不但具有基本,通用定时器的所有的功能,还具有控制交直流电动机所有的功能,你比如它可以输出6路互补带死区的信号,刹车功能等等
通用定时器的时钟来源;
a:内部时钟(CK_INT)
b:外部时钟模式1:外部输入脚(TIx)
c:外部时钟模式2:外部触发输入(ETR)
d:内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器
通用定时期内部时钟的产生:
从截图可以看到通用定时器(TIM2-7)的时钟不是直接来自APB1,而是通过APB1的预分频器以后才到达定时器模块。
当APB1的预分频器系数为1时,这个倍频器就不起作用了,定时器的时钟频率等于APB1的频率;
当APB1的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个倍频器起作用,定时器的时钟频率等于APB1时钟频率的两倍。
自动装在寄存器arr值的计算:
Tout= ((arr+1)*(psc+1))/Tclk;
Tclk:TIM3的输入时钟频率(单位为Mhz)。
Tout:TIM3溢出时间(单位为us)。
计时1S,输入时钟频率为72MHz,加入PSC预分频器的值为35999,那么:
((1+psc )/72M)*(1+arr )=((1+35999)/72M)*(1+arr)=1秒
则可计算得出自动窗装载寄存器arr=1999
通用定时器PWM工作原理
以PWM模式2,定时器3向上计数,有效电平是高电平,定时器3的第3个PWM通道为例:
定时器3的第3个PWM通道对应是PB0这引脚,三角顶点的值就是TIM3_ARR寄存器的值,上图这条红线的值就TIM3_CCR3
当定时器3的计数器(TIM3_CNT)刚开始计数的时候是小于捕获/比较寄存器(TIM3_CCR3)的值,
此时PB0输出低电平,随着计数器(TIM3_CNT)值慢慢的增加,
当计数器(TIM3_CNT)大于捕获/比较寄存器(TIM3_CCR3)的值时,这时PB0电平就会翻转,输出高电平,计数器(TIM3_CNT)的值继续增加,
当TIM3_CNT=TIM3_ARR的值时,TIM3_CNT重新回到0继续计数,PB0电平翻转,输出低电平,此时一个完整的PWM信号就诞生了。
PWM输出模式;
STM32的PWM输出有两种模式:
模式1和模式2,由TIMx_CCMRx寄存器中的OCxM位确定的(“110”为模式1,“111”为模式2)。区别如下:
110:PWM模式1,在向上计数时,一旦TIMx_CNT
在向下计数时,一旦TIMx_CNT》TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
111:PWM模式2-在向上计数时,一旦TIMx_CNTTIMx_CCR1时通道1为有效电平,否则为无效电平。
由以上可知:
模式1和模式2正好互补,互为相反,所以在运用起来差别也并不太大。而从计数模式上来看,PWM也和TIMx在作定时器时一样,也有向上计数模式、向下计数模式和中心对齐模式
PWM的输出管脚:
不同的TIMx输出的引脚是不同(此处设计管脚重映射)
TIM3复用功能重映射:
注:重映射是为了PCB的设计方便。值得一提的是,其分为部分映射和全部映射
PWM输出频率的计算:
PWM输出的是一个方波信号,信号的频率是由TIMx的时钟频率和TIMx_ARR这个寄存器所决定的
输出信号的占空比则是由TIMx_CRRx寄存器确:
占空比=(TIMx_CRRx/TIMx_ARR)*100%
PWM频率的计算公式为:
其中
F就是PWM输出的频率,单位是:HZ;
ARR就是自动重装载寄存器(TIMx_ARR);
PSC 就是预分频器(TIMx_PSC);
72M就是系统的频率;
STM32 高级定时器PWM的输出
一路带死区时间的互补PWM的波形图
STM32F103VC这款单片机一共有2个高级定时器TIM1和TIM8
这2个高级定时器都可以同时产生3路互补带死区时间的PWM信号和一路单独的PWM信号,
具有刹车输入功能,在紧急的情况下这个刹车功能可以切断PWM信号的输出
还具有支持针对定位的增量(正交)编码器和霍尔传感器电路
高级控制定时器(TIM1 和TIM8) 由一个16位的自动装载计数器组成,它由一个可编程的预分频器驱动
它适合多种用途,包含测量输入信号的脉冲宽度( 输入捕获) ,或者产生输出波形(输出比较、PWM、嵌入死区时间的互补PWM等)。
使用定时器预分频器和RCC时钟控制预分频器,可以实现脉冲宽度和波形周期从几个微秒到几个毫秒的调节。
高级控制定时器(TIM1 和TIM8) 和通用定时器(TIMx) 是完全独立的,它们不共享任何资源死区时间
H桥电路为避免由于关断延迟效应造成上下桥臂直通,有必要设置死区时间死区时间可有效地避免延迟效应所造成的一个桥臂未完全关断,而另一桥臂又处于导通状态,避免直通炸开关管。
死区时间越大,电路的工作也就越可靠,但会带来输出波形的失真以及降低输出效率。死区时间小,输出波形要好一些,但是会降低系统的可靠性,一般这个死区时间设置为us级元器件死区时间是不可以改变的,它主要是取决于元器件的制作工艺和材料!
原则上死区时间当然越小越好。设置死区时间的目的,其实说白了就是为了电路的安全。最佳的设置方法是:在保证安全的前提下,设置的死区时间越小越好。以不炸功率管、输出不短路为目的。
STM32死区时间探究设置寄存器:就是刹车和死区控制寄存器(TIMx_BDTR)
这是TIM2的初始化配置,有注释。希望能帮到你。不过这个是用了函数库中的 函数的。
工程中用函数库还是比较方便的,没见过谁做工程时,配置各种东西还直接去操作寄存器的。那不累死!
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
/* ---------------------------------------------------------------
TIM2 Configuration: Output Compare Timing Mode:
TIM2CLK = 36 MHz, Prescaler = 36000, TIM2 counter clock = 1KHz
SET TTIM2 TIME 10mS
--------------------------------------------------------------- */
TIM_TimeBaseStructure.TIM_Period = 10; //计数值。 计时时间=计数值/TIM2 counter clock
TIM_TimeBaseStructure.TIM_Prescaler = 35999; //与分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //定时器时钟(CK_INT)频率与数字滤波器(ETR,TIx)使用的采样频率之间的分频比例。
//TIM_CKD_DIV1 -TDTS = Tck_tim TIM_CKD_DIV1=0x0000 //TIM_CKD_DIV1 -TDTS = Tck_tim
//TIM_CKD_DIV2 -TDTS = 2Tck_tim TIM_CKD_DIV2=0x0100 //TIM_CKD_DIV1 -TDTS = Tck_tim
//TIM_CKD_DIV4 -TDTS = 4Tck_tim TIM_CKD_DIV4=0x0200
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计算是从0计数到自动加载值,向下计算是从自动加载值计数到0
//中央对齐模式是从0计数到自动加载值(溢出),再从自动加载值计数到1(溢出)在从0开始计数。。。
//所以不管选用哪种模式,溢出的时间是不变的
TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure);
TIM_ARRPreloadConfig(TIM2,ENABLE); //预装载使能
TIM_ITConfig(TIM2,TIM_FLAG_Update,ENABLE); //TIM更新中断源
TIM_Cmd(TIM2, ENABLE); //开TIM2定时器
本文标签:stm32的中央对齐