资讯详情

【正点原子MP157连载】第十七章 通用定时器实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南

1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码 手册 视频下载地址:http://www.openedv.com/thread-318813-1-1.html 4)正点原子官方B站:https://space.bilibili.com/394620890 5)正点原子STM32MP157技术交流群:691905614 在这里插入图片描述

第十七章 通用定时器实验

本章主要学习一般定时器,STM32MP157有10个通用定时器(TIM2TIM5,TIM12 TIM17)。我们将学习通用定时器的几个功能,即通用定时器中断实验和通用定时器PWM输出实验、通用定时器输入捕获实验和通用定时器脉冲计数实验。 本章分为以下几个部分: 17.一、一般定时器简介; 17.2.通用定时器中断实验; 17.通用定时器PWM输出实验; 17.4.通用定时器输入捕获实验; 17.5.通用定时器脉冲计数实验(外部时钟模式1); 17.6.通用定时器脉冲计数实验(外部时钟模式2);

17.1 通用定时器简介 17.1.1 STM32MP通用定时器157

  1. 定时器资源 STM32MP157有10个通用定时器,其基本特性也不同。为了更好地区分每个定时器的特性,我们列出了一个表格,如下所示:

表17.1.1. 1定时器基本特性表 从上表知道:除了TIM2和TIM5为32位计数器,其它定时器为16位。在基本定时器的基础上,通用定时器和高级定时器增加了一些额外的功能。通用定时器具有基本定时器的一些功能,并增加了递减计数PWM产生、输入捕获、输出比较等功能。高级定时器还包含了通用定时器的所有功能,并增加了互补输出、重复计数器、断路输入等功能。在上述定时器中,通用定时器数量较多,其特性也有一定差异,但基本原理相同。 2. 通用定时器框图 下面我们以TIM2/TIM3/TIM4/TIM以5的框图为例,学习通用定时器框图。其他通用定时器的框图会有所不同。因为内容很多,你可以在这里学习框图ST官方手册中的其他定时器框图将更容易理解。通过学习一般的定时器框图,我们将有一个很好的整体掌握,并对以后的编程有一个清晰的想法。

图17.1.1. 一般定时器框图 如上图所示,通用定时器的框图比基本定时器的框图复杂得多,为方便介绍,我们将其分为六个部分: ●①时钟源 以下时钟源可提供通用定时器时钟: 1)内部时钟 (CK_INT) 2)外部时钟模式 1.外部输入引脚 (TIx),x=1,2,3,4 3)外部时钟模式 2.外部触发输入 (ETR) 4)内部触发输入 (ITRx):使用定时器作为另一定时器的预分频器 内部时钟 (CK_INT) 内部时钟 (CK_INT)实际来自APB1,定时器TIM2TIM7和定时器TIM12TIM14挂在APB1总线,定时器TIM1、TIM8和TIM15~TIM17挂在APB2上。TIM2/TIM3/TIM4/TIM时钟源为5定时器APB这些定时器只能通过倍频器接收(即时钟不直接来自)APB1),当APB1的预分频系数为1时,该倍频器的倍频值为1,定时器的时钟频率等于APB1的频率;当 APB当1的预分频系数为其他值时,该倍频器的倍频值为2,定时器的时钟频率等于APB1的频率2倍。这个情况跟基本定时器的一样,请回顾基本定时器的这部分内容,最后得到TIM2/TIM3/TIM4/TIM5定时器时钟频率为2倍APB1,即209MHZ。这种情况和基本定时器一样,请回顾基本定时器的这部分,最后得到TIM2/TIM3/TIM4/TIM5定时器时钟频率为2倍APB1,即209MHZ。如下图所示,可在STM32CubeMX上动态配置时钟:

图17.1.1. 2 定时器时钟 外部时钟模式 1

图17.1.1. 3 TI2外部时钟连接示例 根据上图,我们做了一个简单的描述: 时钟信号 如果时钟源选择外部时钟模式 1.即时钟信号从外部输入引脚TI1TI4中的一个(即定时器的通道)TIMx_CH1 TIMx_CH4),属于触发输入TRGI。 滤波器及边缘检测 外部输入引脚输入的信号经过滤波器处理,然后通过边缘检测器输出上升或下降的有效信号。滤波器的功能,简单地说,多次检测被视为有效的,即连续N次采样检测。如果采样检测结果为高电平,则表明这是一个有效的电平信号,以过滤干扰信号。 触发源选择 触发输入源有很多,可以来自内部触发ITRx(x等于0~四、边缘检测器TI1F_ED、滤波后的定时器输入1(TI1FP1)滤波后定时器输入2(TI2FP2)外部触发输入(ETRF)其中一个。其中ITRx其他内部定时器可以产生信号,即使用定时器作为另一个定时器的预分频器,提供触发信号的定时器在主模式下工作,接收触发信号的定时器在从模式下工作。 在上图中,如果时钟信号来自外部输入引脚,则使用外部时钟模1TI2,通过配置TIMx_SMCR 寄存器的TS[4:0]= 滤波后的定时器输入可以配置触发信号 1 (TI1FP1),也可以配置TIMx_SMCR寄存器的TS[4:0]= 00100选择TI1边沿检测器(TI1F_ED)为触发源。 从模式选择 触发信号接收外部时钟模式1TRGI外部时钟模式1后,还需要配置引脚TIMx_SMCR寄存器的SMS[2:0]位= 从模式到外部时钟模式1011配置。 外部时钟模式 2

图17.1.1. 4外部时钟模式 2 根据上图,我们做了一个简单的描述: 时钟信号输入 时钟信号来自于使用外部模式2时ETR引脚,ETR例如,引脚可以为定时器提供外部时钟信号PA0可以复用为TIM2_ETR/TIM2_CH1,如果配置PA0复用为TIM2_ETR的话,那么PA0引脚作为外部时钟输入引脚,例如,其他引脚可以模拟输出脉冲或PWM波形,然后用杜邦线连接模拟输出脉冲引脚PA0,给PA提供时钟脉冲,或连接外部收集的脉冲PA0(注意IO口压范围)也可以。

图17.1.1. 5 PA0引脚可以重用ETR 如果要选择ETR作为时钟源,需要配置TIMx_AF1 寄存器中的 ETRSEL[3:0] 选对位 ETR 源(如上TIM2_ETR),并通过配置TIMx_SMCR寄存器设置预分频器、上升或下降边缘检测和外部时钟模式 2,还需要配置TIMx_CR1 寄存器的CEN=1 来使能计数器。具体配置步骤可参考参考手册。 对比上述外部时钟模式1和外部时钟模式2的框图: 时钟信号来自定时器通道TIMx_CH1~ TIMx_CH4.通过滤波、边缘检测和极性选择触发信号TRGI作为定时器的时钟源,式,作为定时器的时钟源,如下图所示。外部时钟模式2的时钟信号来自特定的ETR引脚,该信号经过极性选择、分频和滤波(分频和滤波不必要,可根据外部信号频率和信号干扰信号程度确定),无需从模式选择器,如内部时钟(CK_INT)直接进入计数器,为计数器提供时钟,如图所示。内部时钟(CK_INT)是下图中的路线3。

图17.1.1. 6通用定时器框图(部分) 关于两种模式的时钟输入引脚: 外部时钟模式1的是来自定时器通道TIMx_CH1~ TIMx_CH4,而外部时钟模式2则来自特定的ETR引脚;外部时钟模式1的时钟信号具有触发的特点,定时器工作于外部时钟模式1从模式,触发信号可以产生触发事件,从而产生中断或者DMA请求;外部时钟模式2来自ETR引脚,只是一个时钟信号,不具备触发的功能,定时器可以工作在主模式,也可以工作在从模式(复位、发、门控等)。 例如对TIM2的通道1可以配置这两种模式:

图17.1.1. 7 STM32CubeMX配置 内部触发输入(ITRx) 定时器连接来自其它定时器的触发输出,即使用一个定时器作为另一定时器的预分频器。发送触发输出信号的定时器工作于主模式,接收触发信号的定时器工作于从模式。主模式定时器可以对从模式定时器的计数器执行复位、启动、停止操作或为其提供时钟。这种模式也就是定时器的级联,如下图:

图17.1.1. 8 主/从模式示意图 接下来我们继续分析通用定时器框图部分的内容。 ●②控制器 控制器包括:从模式控制器、编码器接口和触发控制器(TRGO)。从模式控制器可以控制计数器复位、启动、递增/递减、计数。编码器接口针对编码器计数,我们没用到。触发控制器用来提供触发信号给别的外设,比如为其它定时器提供时钟或者为DAC/ADC的触发转换提供信号。 ●③时基单元 时基单元包括:计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动重载寄存器(TIMx_ARR)。这里注意的一点是这里的计数器模式有三种:递增、递减和中心对齐,并且TIM2 和TIM5是32位的。 递增计数模式在基本定时器已经讲过,递减计算模式就很好理解,就是来一个脉冲计数器减1,直到计数器值减到0,然后计数器又从自动重载寄存器ARR的值开始继续递减计数,并生成定时器下益事件。 而中心对齐计数模式字面上不好理解,该模式下,计数器从0开始递增计数,直到计数值等于自动重载寄存器ARR的值减1后,生成定时器上溢事件,然后从自动重载寄存器ARR的值开始递减计算,直到计数值等于1,并生成定时器下益事件。然后又从0开始计数,一直循环。每次发生计数器上溢和下溢事件都会生成更新事件。 ●④输入捕获 输入捕获包括:4个输入捕获通道(TIMx_CH1~ TIMx_CH4)、输入滤波和边沿检测和预分频器等部分,用于输入捕获功能,如:测量输入信号的脉冲宽度、测量 PWM 输入信号的频率和占空比等。 下面简单说一下输入捕获的工作原理:一般先设置输入捕获为上升沿检测,并记录发生上升沿时计数器寄存器(TIMx_CNT)的值。然后设置输入捕获为下降沿检测,当检测到下降沿到来时,记录此时计数器寄存器(TIMx_CNT)的值。最后,用后面记录的值减去前面记录的值,就得到此次高电平的脉冲宽度,再根据定时器的计数频率就可以计算出这个高电平脉冲的时间。低电平脉冲捕获同理。 ●⑤输入捕获和输出比较公用部分 这部分包括:4个捕获比较寄存器,后面寄存器内容再详细分析。 ●⑥输出比较 输出比较包括:4个输出比较通道和相应的输出控制器组成,用于输出比较模式或PWM输出模式。 通用定时器定时器比较多,有10个,我们这里就主要以TIM2/TIM3/TIM4/TIM5为例子进行实验讲解,其它没讲到的定时器也是类似的,具体可以查询参考手册来了解。下面分别通过四个实验来详细学习通用定时器的功能。 17.2 通用定时器中断实验 本实验配置好的实验工程已经放到了开发板光盘中,路径为:开发板光盘A-基础资料\1、程序源码\11、M4 CubeIDE裸机驱动例程\CubeIDE_project\ 10-1 GTIM。 17.2.1 TIM2/TIM3/TIM4/TIM5寄存器 下面介绍TIM2/TIM3/TIM4/TIM5的几个与定时器中断相关且重要的寄存器,其他的通用定时器的寄存器会有一些差异,请大家自行对比《STM32H7xx参考手册》第39~41章,具体如下:

  1. 控制寄存器 1(TIMx_CR1) TIM2/TIM3/TIM4/TIM5的控制寄存器1描述如下图所示:

图17.2.1. 1 TIMx_CR1寄存器 上图中我们只列出了本章需要用的一些位,其中: 位0(CEN),用于计数器使能,将该位置1表示禁止计数器,将改位置0表示使能计数器; 位4(DIR),用于控制定时器的计数方向,我们需要向上计数模式,所以设置DIR=0; 位6和位5(CMS[1:0]位),用于控制中心对齐模式,本章我们使用边沿对齐模式,所以设置为00即可; 位7(ARPE)用于控制自动重载预装载使能,0表示TIMx_ARR 寄存器不进行缓冲,1表示TIMx_ARR 寄存器进行缓冲,在基本定时器章节介绍影子寄存器时我们有讲解过。 2. 从模式控制寄存器(TIMx_SMCR) TIM2/TIM3/TIM4/TIM5的从模式控制寄存器描述如下图所示:

图17.2.1. 2 TIMx_SMCR寄存器 该寄存器的SMS[3:0]位,用于从模式选择,其实就是选择计数器输入时钟的来源。比如通用定时器中断实验我们设置SMS[3:0]=0000,禁止从模式,这样PSC预分频器的时钟就直接来自内部时钟(CK_INT),频率一般为209Mhz(APB1频率的2倍)。而通用定时器中断实验我们设置SMS[3:0]=0111,外部时钟模式1,这样就可以检测按键的脉冲当做计数器时钟。 3. TIMx DMA/中断使能寄存器 (TIMx_DIER) TIM2/TIM3/TIM4/TIM5的DMA/中断使能寄存器描述如图21.2.1.3所示:

图17.2.1. 3 TIMx_DIER寄存器 该寄存器涉及触发DMA请求、捕获/比较中断以及更新中断使能,本章实验只用到后面两个。位0(UIE)是更新中断允许位,通用定时器中断实验需要用到定时器的更新中断,所以该位要设置为1来允许由于更新事件所产生的中断。而位1到位4是捕获/比较中断使能位,分别对应四个输入输出通道,将其置1表示使能中断,清0表示禁止中断。 4. 状态寄存器(TIMx_SR)

图17.2.1. 4 TIMx_SR寄存器 该寄存器都是一些中断标志位,CC1OF~CC4OF对应捕获/比较重复捕获标志,以第9位为例,如果CC1IF位为1,表示TIMx_CCR1寄存器中已捕获到计数器值且CC1IF 标志已置1; 位6属于触发中断标志,0表示未发生触发事件,1表示触发中断挂起; 位0(UIF)表示更新中断标志,当定时器中断来到该位会由硬件置1,标志中断到来,我们需要在中断服务函数里面把该位清零。 5. 计数器寄存器(TIMx_CNT)

图17.2.1. 5 TIMx_CNT寄存器 因为定时器2和定时器5的计数器是32位的,所以当用到这两个定时器的时候,TIMx_CNT寄存器的32位都是用做计数器寄存器,其他定时器的就跟基本定时器一样,只用到低16位。 6. 预分频寄存器(TIMx_PSC)

图17.2.1. 6 TIMx_PSC寄存器 所有定时器的预分频寄存器都是16位的,即写入该寄存器的数值范围是0到65535,表示1到65536分频。比如我们要20900分频,就往该寄存器写入20899。 7. 自动重载寄存器(TIMx_ARR)

图17.2.1. 7 TIMx_ARR寄存器 该寄存器是用于存放与计数器寄存器比较的值,ARR[15:0]为自动重载值的低 16 位,ARR[31:16]为自动重载值的高 16 位,定时器2和定时器5的计数器是32位的,那该寄存器也是32位,其他定时器的就跟基本定时器一样,只用到低16位。 17.2.2 HAL库的API函数 本章节实验重要的API函数和上一章基本定时器介绍的内容差不多,这里就不再重复介绍此部分内容。 17.2.3 硬件设计

  1. 例程功能 LED0用来指示程序运行,500ms为一个周期。LED1用于定时器中断取反,指示定时器中断状态,1000ms为一个周期。
  2. 硬件资源

表17.2.3. 1 LED硬件资源 2)定时器3 3. 原理图 定时器属于STM32MP157的内部资源,只需要软件设置好即可正常工作。我们通过LED1来指示STM32MP157的定时器进入中断情况。 17.2.4 软件设计

  1. 程序流程图 下面看看本实验的程序流程图:

图17.2.4. 1通用定时器中断实验程序流程图

  1. STM32CubeMX配置 (1)配置GPIO 新建一个工程GTIM(或者直接在上一章节实验的基础上操作),进入STM32CubeMX插件配置界面后,在Pinout & Configuration处配置PI0和PF3为GPIO Output,并配置PI0和PF3给CM4内核使用,如下图所示。

图17.2.4. 2配置LED0和LED1 (2)配置时钟 本实验我们采用外部时钟HSE(也可以采用内部时钟),配置时钟树,经过PLL3相环以后,APB1的时钟频率为最大209MHz(也可以配置其它频率)。

图17.2.4. 3配置HSE 我们选择HSE,作为锁相环PLL3的时钟源,在MCU子系统时钟里输入209并回车,STM32CubeMX会自动为我们计算参数,然后再手动配置APB1DIV、APB2DIV和APB3DIV的分频值为2。当APB1DIV的分频数大于1的时候,基本定时器的倍频器倍频值始终为2,所以基本定时器的时钟频率为209MHz。

图17.2.4. 4配置系统时钟 (3)配置TIM3 本实验我们使用的是通用定时器的TIM3,如下图,按照步骤配置TIM3,其中TIM3只能给A7和M4内核两者中的某一个使用,所以,我们要把TIM3分配给M4使用。

图17.2.4. 5配置TIM3参数 如上图,按照步骤配置基本定时器。Clock Source我们选择Internal Clock,表示使用内部时钟,即来自APB1的时钟。然后配置预分频器寄存器(TIMx_PSC)的值为20900-1。计数模式是向上递增计数,前面我们提到基本定时器的计数模式只有递增(向上)计数模式,而通用定时器具有向上或者向下计数模式。对于向上计数模式,复位后计数器从0重新开始计数对于向下计数模式,复位后计数器从ARR开始向下递减计数。自动重载寄存器 (TIMx_ARR)的值为10000-1。开启自动重装载模式。 定时器3的时钟频率是209MHz,计算出计数器CK_CNT的时钟频率是

那么计数器计数10000次就会溢出产生中断,所以每次溢出时间是:

其它选项就保持默认状态,不需要配置了。例如,Slave Mode用于配置从模式(复位、触发、门控);Trigger Source用于配置选择触发源,触发源可以是ITR0~ITR3和TI1_ED中的某一个,我们前面介绍过,这几个是外部时钟模式 1的时钟源,也可以选择外部时钟源,本章节我们直接使用Channel1~Channel4表示通道,本章节实验用不到所以就不配置。 (4)配置NVIC 定时器要每秒溢出产生中断,所以我们要使能定时器全局中断,并配置中断优先级。如下图,勾选TIM3定时器全局中断:

图17.2.4. 6使能定时器全局中断 (5)配置NVIC 勾选TIM6全局中断以后,开启了定时器中断,此时中断优先级为0,即最高优先级,我们在NVIC处配置中断优先级,如下配置中断优先级分组为2,抢占优先级和子优先级为3:

图17.2.4. 7配置中断优先级 (6)配置生成独立的文件 配置生成独立的.c和.h头文件,如下图:

图17.2.4. 8配置生成独立的.c和.h文件 2. 生成工程 按下“Ctrl+S”保存修改配置,生成工程:

图17.2.4. 9生成工程 2. 添加用户代码 (1)将上一章节基本定时器的BSP文件夹拷贝到工程中:

图17.2.4. 10拷贝上一个工程的BSP文件夹 上一章节的led.c中我们是自定义了回调函数HAL_TIM_PeriodElapsedCallback,实现每次中断LED1翻转:

/** * @brief 定时器更新中断回调函数 * @param htim:定时器句柄指针 * @retval 无 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{ 
        
    if (htim == (&htim3))
        { 
        
            LED1_TOGGLE();					/* LED1翻转 */
        }
}

(2)修改main.c文件 在min.c中添加如下代码:

/* USER CODE BEGIN 2 */
 led_init();/* 关闭 LED0和LED1 */
 HAL_TIM_Base_Start_IT(&htim3);			/* 更新定时器中断和使能定时器 */
 /* USER CODE END 2 */

LED0_TOGGLE();					/* LED0翻转 */
HAL_Delay(500);					/* 延时500ms */

图17.2.4. 11添加的代码在main.c文件中的位置 3. 编译和测试 保存修改,再进行编译,编译不报错进入Debug模式验证,实验现象和上一章节的基本定时器的一样,即运行后,LED0和LED1同时点亮,LED0以500ms周期闪烁,LED1以1s周期闪烁。 17.3 通用定时器PWM输出实验 本实验配置好的实验工程已经放到了开发板光盘中,路径为:开发板光盘A-基础资料\1、程序源码\11、M4 CubeIDE裸机驱动例程\CubeIDE_project\ 10-2 GTIM_PWM。 17.3.1 定时器的PWM输出模式

  1. 脉冲宽度调制 本小节我们来学习如何使用通用定时器的PWM输出模式。 脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。 PWM通过对一系列脉冲的宽度进行调制后,等效输出一系列幅值相等的波形,它把模拟信号转化为数字电路所需要的编码。PWM 常用来做电机控制、LCD 背光亮度调节、开关电源等,在测量、通信、及功率控制等许多领域中广泛应用。如下图,一模拟信号(正弦波)经过PWM后输出一系列幅值相等的脉冲(我们称为PWM波),使用这些脉冲来代替正弦波或所需要的波形,可以通过调节这些脉冲的占空比等效控制输出电压的大小,例如,在PWM频率一定的条件下,比如占空比为100%时,输出电压为5V,占空比为0时,输出电压为0V,当我们需要输出2.5V的电压时,只要将占空比调节为50%就能实现。

图17.3.1. 1 PWM输出 注: PWM占空比就是一个脉冲周期内高电平在整个周期占的比例 如果芯片内部自带PWM输出功能模块,可以直接配置PWM实现PWM输出。如果芯片内部没有PWM功能模块,我们也可以通过定时器来控制一个IO口按照一定的时间间隔输出一高一低的电平以模拟PWM波形,例如模拟上图的波形b)。本章节我们就是使用定时器的一个通道输出PWM波形。 2. PWM输出模式 PWM有两种输出模式,分别为PWM模式1和PWM模式2。可以理解PWM模式1是与PWM模式2互补的波,PWM模式1为高电平时,PWM模式2为低电平,反之亦然。PWM模式和计数器计数模式对通道输出的PWM波电平有影响:在PWM模式1下,当计数器向上计数时,如果CNT< CCRx时,通道为有效电平,否则为无效电平;当计数器向下计数时,如果CNT>CCRx时,通道为无效电平,否则为有效电平。

表17.3.1. 1 PWM输出模式 例如一个外设是低电平有效才会运行,采用递增计数时:当CNT< CCRx时,此外设运行;当CNT> CCRx时,此外设不运行。 3. PWM 生成(边沿对齐模式) PWM波频率由自动重载寄存器(TIMx_ARR)的值决定,其占空比则由捕获/比较寄存器(TIMx_CCRx)的值决定。它们生成PWM的原理如图下图所示:

图17.3.1. 2 PWM原理示意图 上图就是一个简单的PWM原理示意图。图中,我们假定定时器工作在边沿对齐,向上计数PWM模式,且当CNT<CCRx时,输出0,当CNT>=CCRx时输出1。那么就可以得到如上的PWM示意图:当CNT值小于CCRx的时候,IO输出低电平(0),当CNT值大于等于CCRx的时候,IO输出高电平(1),当CNT达到ARR值的时候,重新归零,然后重新向上计数,依次循环。改变CCRx的值,就可以改变PWM输出的占空比,改变ARR的值,就可以改变PWM输出的频率,这就是PWM输出的原理。 4. PWM 生成(中心对齐模式) 通用定时器(包括后面我们后面会学到的高级定时器)除了支持单向的向上或向下计数模式外,还支持中心对齐计数模式,即一个计数周期内分别由向上计数和向下计数两个过程组成,中心对齐模式用来输出对称波形,比如正弦波,可以基于中心对齐模式来实现PWM输出比较功能。中心对齐模式由TIMx_CR1寄存器的CMS[1:0]位来配置,当CMS[1:0]配置: 00:边沿对齐模式。计数器根据方向位 (DIR) 递增计数或递减计数; 01:中心对齐模式 1。计数器交替进行递增计数和递减计数,输出比较中断标志位,只在计数器递减计数时被置1; 10:中心对齐模式 2。计数器交替进行递增计数和递减计数,输出比较中断标志位,只在计数器增计数时被置1; 11:中心对齐模式 3。计数器交替进行递增计数和递减计数,输出比较中断标志位,只在计数器增计数时和递减计数时均被置1。 以上列出有3种中心对齐模式,我们以PWM模式1和中心对齐模式 3为例,PWM波形图如下:

图17.3.1. 3中心对齐模式 3 如上,对于中心对齐模式3,计数器在向上计数或者向下计数时,输出比较中断标志位被置1,当CNT<CCRx时,PWM是高电平1,当CNT>CCRx时,PWM是低电平。 STM32MP157的定时器除了基本定时器TIM6和TIM7,其他的定时器都可以用来产生PWM输出。其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出!本实验我们以使用TIM5的CH4通道产生一路PWM输出来控制LED0为例进行学习,如下图是STM32MP157数据手册的部分截图,我们的开发板上PI0接的LED0,PI0可以复用为TIM5_CH4,通过配置TIM5_CH4产生PWM波形可以控制LED0工作。

图17.3.1. 4 PI0可以复用为TIM5_CH4 17.3.2 TIM2/TIM3/TIM4/TIM5寄存器 要使STM32H750的通用定时器TIMx产生PWM输出,除了上一小节介绍的寄存器外,我们还会用到3个寄存器,来控制PWM。这三个寄存器分别是:捕获/比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~4)。接下来我们简单介绍一下这三个寄存器。

  1. 捕获/比较模式寄存器1/2(TIMx_CCMR1/2) TIM2/TIM3/TIM4/TIM5的捕获/比较模式寄存器(TIMx_CCMR1/2,指输出比较模式),该寄存器一般有2个:TIMx _CCMR1和TIMx _CCMR2。TIMx_CCMR1控制CH1和CH2,而TIMx_CCMR2控制CH3和CH4。TIMx_CCMR2寄存器描述如下图所示:

图17.3.2. 1 TIMx_CCMR2寄存器 该寄存器的有些位在不同模式下,功能不一样,我们现在只用到输出比较,输入捕获后面的实验再讲解。关于该寄存器的详细说明,请参考《STM32MP157参考手册》第41.4.10小节。 比如我们要让TIM5的CH4输出PWM波为例进行介绍: OC4M[3:0] 是输出比较4模式设置位,对应着通道4的输出比较4模式设置,此部分由4位组成。总共可以配置成14种模式,我们使用的是PWM模式,所以这4位必须设置为0110或者0111,分别对应PWM模式1和PWM模式2。这两种PWM模式的区别就是输出有效电平的极性相反; OC4PE是输出比较通道4的预装使能,该位需要置1; CC4S[1:0]用于设置通道1的方向(输入/输出)默认设置为0,就是设置通道作为输出使用。 2. 捕获/比较使能寄存器(TIMx_ CCER) TIM2/TIM3/TIM4/TIM5的捕获/比较使能寄存器,该寄存器控制着各个输入输出通道的开关和极性。TIMx_CCER寄存器描述如下图所示:

图17.3.2. 2 TIMx_CCER寄存器 该寄存器比较简单,要让TIM5的CH4输出PWM波,这里我们要使能CC4E位,该位是输入/捕获通道4(ch4)的使能位,要想PWM从IO口输出,这个位必须设置为1。CC4P位是设置通道4的输出极性,我们默认设置0,即OC4 高电平有效。 3. 捕获/比较寄存器1/2/3/4(TIMx_ CCR1/2/3/4) 捕获/比较寄存器(TIMx_ CCR1/2/3/4),该寄存器总共有4个,对应4个通道CH1~CH4。我们使用的是通道4,所以来看看TIMx_ CCR4寄存器描述如下图所示:

图17.3.2. 3 TIMx_ CCR1寄存器 此寄存器是捕获/比较寄存器 4 的预装载值,在输出模式下,该寄存器的值与CNT的值比较,根据比较结果产生相应动作,利用这点,我们通过修改这个寄存器的值,就可以控制PWM的输出脉宽了。注意,对于TIM2和TIM5来说,该寄存器是32位有效的,对其他定时器来说,则是16位有效位。 4.TIM1/TIM8断路和死区寄存器(TIMx_ BDTR) 如果是通用定时器,则配置以上说的寄存器就够了,但是如果是高级定时器,则还需要配置:断路和死区寄存器(TIMx_BDTR),该寄存器各位描述如图21.3.1.4所示:

图17.3.2. 4 TIMx_ BDTR寄存器 该寄存器,我们只需要关注位15(MOE),主输出使能位,要想高级定时器的PWM正常输出,则必须设置MOE位为1,否则不会有输出。注意:通用定时器不需要配置这个。该寄存器的其他位我们这里就不详细介绍了,讲到高级定时器的时候再介绍其它位。 17.3.3 定时器的HAL库驱动 定时器在HAL库中的驱动代码在前面介绍基本定时器已经介绍了部分,这里我们再介绍几个和本实验用到的函数。

  1. HAL_TIM_PWM_Init函数 定时器的PWM输出模式初始化函数,其声明如下: HAL_StatusTypeDef HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim); 函数描述: 用于初始化定时器的PWM输出模式。 函数形参: 形参1是TIM_HandleTypeDef结构体类型指针变量,基本定时器的时候已经介绍。 函数返回值: HAL_StatusTypeDef枚举类型的值。HAL_OK(成功)、HAL_ERROR(错误)、HAL_BUSY(串口忙碌)、HAL_TIMEOUT(超时) 注意事项: 该函数实现的功能以及使用方法和HAL_TIM_Base_Init都是类似的,作用都是初始化定时器的ARR和PSC等参数。为什么HAL库要提供这个函数而不直接让我们使用HAL_TIM_Base _Init函数呢?这是因为HAL库为定时器的针对PWM输出定义了单独的MSP回调函数HAL_TIM_PWM_MspInit,所以当我们调用HAL_TIM_PWM_Init进行PWM初始化之后,该函数内部会调用MSP回调函数HAL_TIM_PWM_MspInit。而当我们使用HAL_TIM_Base_Init初始化定时器参数的时候,它内部调用的回调函数为HAL_TIM_Base_MspInit,这里大家注意区分。
  2. HAL_TIM_PWM_ConfigChannel函数 定时器的PWM通道设置初始化函数。其声明如下: HAL_StatusTypeDef HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef sConfig, uint32_t Channel) 函数描述: 该函数用于设置定时器的PWM通道。 函数形参: 形参1是TIM_HandleTypeDef结构体类型指针变量,用于配置定时器基本参数。 形参2是TIM_OC_InitTypeDef结构体类型指针变量,用于配置定时器的输出比较参数。 重点了解一下TIM_OC_InitTypeDef结构体指针类型,其定义如下: typedef struct { uint32_t OCMode; / 输出比较模式选择,寄存器的时候说过了,共7种模式 / uint32_t Pulse; / 设置比较值,默认比较值为自动重装载值的一半,即占空比为50% / uint32_t OCPolarity; / 设置输出比较极性 / uint32_t OCNPolarity; / 设置互补输出比较极性 / uint32_t OCFastMode; / 使能或失能输出比较快速模式 / uint32_t OCIdleState; / 选择空闲状态下的非工作状态(OC1 输出) / uint32_t OCNIdleState; / 设置空闲状态下的非工作状态(OC1N 输出) */ } TIM_OC_InitTypeDef; 该结构体成员我们重点关注前三个。成员变量OCMode用来设置模式,这里我们设置为PWM模式1。成员变量Pulse用来设置捕获比较值。成员变量TIM_OCPolarity用来设置输出极性是高还是低。其他的参数TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState和TIM_OCNIdleState是高级定时器才用到的。 形参3是定时器通道,范围:TIM_CHANNEL_1到TIM_CHANNEL_4。这里我们使用的是定时器5的通道4,所以取值为TIM_CHANNEL_4即可。 函数返回值: HAL_StatusTypeDef枚举类型的值。HAL_OK(成功)、HAL_ERROR(错误)、HAL_BUSY(串口忙碌)、HAL_TIMEOUT(超时)
  3. HAL_TIM_PWM_Start函数 定时器的PWM输出启动函数,其声明如下: HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim,uint32_t Channel) 函数描述: 用于启动定时器的PWM输出模式。 函数形参: 形参1是TIM_HandleTypeDef结构体类型指针变量。 形参2是定时器通道,范围:TIM_CHANNEL_1到TIM_CHANNEL_4。 函数返回值: HAL_StatusTypeDef枚举类型的值。HAL_OK(成功)、HAL_ERROR(错误)、HAL_BUSY(串口忙碌)、HAL_TIMEOUT(超时) 注意事项: 对于单独使能定时器的方法,在上一章定时器实验我们已经讲解。实际上,HAL库也同样提供了单独使能定时器的输出通道函数,函数为: void TIM_CCxChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelState); HAL_TIM_PWM_Start函数内部也调用了该函数。
  4. HAL_TIM_ConfigClockSource函数 配置定时器时钟源函数,其声明如下: HAL_StatusTypeDef HAL_TIM_ConfigClockSource(TIM_HandleTypeDef *htim, \ TIM_ClockConfigTypeDef sClockSourceConfig) 函数描述: 用于配置定时器时钟源。 函数形参: 形参1是TIM_HandleTypeDef结构体类型指针变量。 形参2是TIM_ClockConfigTypeDef结构体类型指针变量,用于配置定时器时钟源参数。 TIM_ClockConfigTypeDef定义如下: typedef struct { uint32_t ClockSource; / 时钟源 / uint32_t ClockPolarity; / 时钟极性 / uint32_t ClockPrescaler; / 定时器预分频器 / uint32_t ClockFilter; / 时钟过滤器 / } TIM_ClockConfigTypeDef; 函数返回值: HAL_StatusTypeDef枚举类型的值。HAL_OK(成功)、HAL_ERROR(错误)、HAL_BUSY(串口忙碌)、HAL_TIMEOUT(超时) 注意事项: 该函数主要操作TIMx_SMCR寄存器,系统默认定时器的时钟源就是内部时钟,所以一般定时器要使用内部时钟,我们就不对定时器的时钟源就行初始化,默认即可。这里只是让大家知道有这个函数可以设定时器的时钟源。比如用HAL_TIM_ConfigClockSource初始化选择内部时钟,方法如下: TIM_HandleTypeDef timx_handle; / 定时器x句柄 / TIM_ClockConfigTypeDef sClockSourceConfig = {0}; sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; / 选择内部时钟 */ HAL_TIM_ConfigClockSource(&timx_handle, &sClockSourceConfig); 其他的时钟源请大家参考TIMx_SMCR寄存器和HAL库。后面的定时器初始化凡是用到内部时钟我们都没有去初始化,系统默认即可。
  5. 修改占空比 前面我们说过,通过修改比较值TIMx_CCRx则可以控制通道的输出占空比。继而控制LED0的亮度(本实验是使用TIM5,则可以通过控制TIM5_CCR2来控制CH4的输出占空比)。HAL库中提供一个修改占空比的宏定义:
#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__) \ (((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_4) ? ((__HANDLE__)->Instance->CCR4 = (__COMPARE__)) :\ ((__CHANNEL__) == TIM_CHANNEL_5) ? ((__HANDLE__)->Instance->CCR5 = (__COMPARE__)) :\ ((__HANDLE__)->Instance->CCR6 = (__COMPARE__)))

__HANDLE__是TIM_HandleTypeDef结构体类型指针变量,__CHANNEL__对应PWM的输出通道,_COMPARE__则是要写到捕获/比较寄存器(TIMx CCR1/2/3/4)的值。实际上该宏定义最终还是往对应的捕获/比较寄存器写入比较值来控制PWM波的占空比。如下解析: 比如我们要修改定时器5通道4的输出比较值(控制占空比),寄存器操作方法: TIM5->CCR2 = ledrpwmval; /* ledrpwmval是比较值,并且动态变化的, 所以我们要周期性调用这条语句,已达到及时修改PWM的占空比 */ __HAL_TIM_SET_COMPARE (, , )这个宏定义函数最终也是调用这个寄存器操作的,所以说我们使用HAL库的函数其实就是间接操作寄存器的。 17.3.4 硬件设计

  1. 例程功能 通过PWM控制LED0由暗变到亮,然后又从亮变到暗,每个过程大概持续时间大概为3秒钟左右。
  2. 硬件资源 1)LED灯 LED0 总线 PI0 AHB4 表17.3.4. 1 LED硬件资源 2)定时器5输出通道4(TIM5_CH4) 从核心板原理图看出,PI0和TIM5_CH4存在复用关系,我们在STM32CubeMX上把PI0配置为TIM5_CH4即可,然后程序控制TIM5_CH4输出PWM波形,从而控制LED0。

图17.3.4. 1 PI0引脚部分原理图 从《STM32MP157A&D数据手册》中也可以查阅PI0的复用关系:

图17.3.4. 2数据手册部分截图 3. 原理图 定时器属于STM32MP157的内部资源,只需要软件设置好即可正常工作。 17.3.5 软件设计 PI0引脚上接的是LED0,如果PI0上输出低电平,则LED0点亮,我们称LED0电平为低电平有效,如果PI0输出的是高电平,则LED0熄灭。PI0引脚可以复用为TIM5_CH4,即定时器5的PWM通道4,通过通道输出PWM高低电平来控制LED0点亮和熄灭,通过控制PWM的占空比来控制LED0的有效电平。本节实验配置步骤为: 1)通道选择:配置PI0引脚复用为TIM5_CH4; 2)时基配置:配置TIM5的预分频器PSC、自动重载TIMx_ARR值、计数模式、PWM模式、TIM5时钟源选择以及比较值等参数; 3)时钟树配置; 4)生成初始化代码; 5)添加用户代码,实现动态改变占空比,从而控制LED0灯的亮灭,可以实现类似呼吸灯的效果。

  1. 程序流程图

图17.3.5. 1通用定时器中断实验程序流程图 2. STM32CubeMX配置 (1)配置PI0复用为TIM5_CH4 新建一个工程GTIM_PWM(或者直接在上一章节实验的基础上操作),进入STM32CubeMX插件配置界面后,在Pinout & Configuration处配置PI0复用为TIM5_CH4,如下图所示:

图17.3.5. 2配置LED0和LED1 (2)配置时钟 本实验我们采用外部24MHz的时钟HSE(也可以采用内部时钟),配置时钟树,经过PLL3锁相环以后,APB1的时钟频率为最大209MHz(也可以配置其它频率)。

图17.3.5. 3配置HSE 我们选择HSE,作为锁相环PLL3的时钟源,在MCU子系统时钟里输入209并回车,STM32CubeMX会自动为我们计算参数,然后再手动配置APB1DIV、APB2DIV和APB3DIV的分频值为2。当APB1DIV的分频数大于1的时候,基本定时器的倍频器倍频值始终为2,所以通用定时器TIM5的时钟频率为209MHz。

图17.3.5. 4配置系统时钟 (3)配置TIM5 在TimersTIM5中配置如下,Clock Source选择Internal Clock,表示选择内部时钟,Channel4选择PWM Generation CH4,表示使用TIM5的通道4产生PWM波形,其它选项保持默认配置。

图17.3.5. 5配置TIM5为内部时钟 在Parameter Settings处配置参数如下:

图17.3.5. 6配置计数器参数以及PWM通道参数 Counter Settings用于配置计数器的参数: Prescaler:配置定时器的分频系数,这里配置209-1; Counter Mode:定时器的计数模式,我们选择UP,即向上计数模式; Counter Period:计数周期,即自动重装载值,也就是装在TIM5_ARR的值,这里配置为500-1; Internal Clock Division (CKD):内部时钟分频因子,这里就不设置分频了; auto-reload preload:这里设置为Enable,定时器自动重装载使能,即使能TIMx_ARR寄存器进行缓冲; 上述参数可以计算定时器的时钟频率为:

TIM5的溢出时间:

Trigger Output(TRGO) Parameters 用于配置触发输出(TRGO)参数,我们这里不配置。 PWM Generation Channel4用于配置通道4的参数,其中: Mode:用于配置PWM的模式,这里选择PWM mode 1,即PWM模式1。另外还有PWM模式2,可以理解PWM mode l是与PWM mode 2模式互补的波,PWM模式1为高电平时PWM模式2为低电平,反之亦然。 Pulse (32 bits value):是占空比值,即TIM5_CCR4的值,也就是有效电平的值,可以配置在0-500之间,例如配置0。这里配置250,即占空比为50%。在后面的实验中,我们会对TIMx_CCR4寄存器写入新的值来改变占空比,从而控制LED逐渐点亮和熄灭。 Output compare preload:输出比较预加载项选择Enable,即在定时器工作时是否能修改Pulse的值,如果禁用此项,表示定时器工作时不能进行修改,只能等到更新事件到来的时候才能进行修改,所以这里选择使能。 CH Polarity:输出极性,这里我们选择Low(LED0是低电平有效)。 以上配置中要注意的是输出极性和PWM模式,其中TIM5_CNT为TIM5的计数寄存器,用于计数器计数,TIM5_CCR4为TIM5的比较寄存器,其值由用户设置,如上面设置为250。 板子上的LED0是低电平有效,如果输出极性选择为Low: 在PWM模式1下当向上计数时,如果TIM5_CNT<TIM5_CCR4时,通道4为有效电平,否则为无效电平;在向下计数时,如果TIM5_CNT>TIM5_CCR4时通道4为无效电平,否则为有效电平。 如果在PWM模式2下,在向上计数时,如果TIM5_CNT<TIM5_CCR4时通道4为无效电平,否则为有效电平;在向下计数时,如果TIM5_CNT>TIM5_CCR4时通道4为有效电平,否则为无效电平。 例如配置为PWM模式2、向上计数、比较值始终为600、自动重装载值为500、输出极性为低,如果这么配置的话,计数器最大值只能为500,永远小于600,即TIM5_CNT<TIM5_CCR4,通道4电平为无效值,所以LED0灯永远不会亮。 (4)配置IO为上拉 我们配置定时器复用的IO口为上拉模式,即开启内部上拉,我们也在第12.4小节分析过为什么要开启上拉。

图17.3.5. 7配置GPIO为上拉 (5)配置生成独立的文件 配置生成独立的.c和.h头文件,如下图:

图17.3.5. 8配置生成独立的.c和.h文件 2. 生成工程 本章节这里我们不使用中断的方式,配置好后,按下“Ctrl+S”保存修改配置,生成工程:

图17.3.5. 9生成工程 3. 添加用户代码 在main.c文件中添加如下代码:

/* USER CODE BEGIN 0 */
uint16_t ledrpwmval = 0;
uint8_t dir = 1;
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_4);/* 开启PWM通道 */
/* USER CODE END 2 */
/*在while循环中添加 */
HAL_Delay(10);
if (dir)ledrpwmval++;          		/* dir==1 ledrpwmval递增 */
else ledrpwmval--;              		/* dir==0 ledrpwmval递减 */

if (ledrpwmval > 300)dir = 0;   	/* ledrpwmval达到300以后,方向为递减 */
if (ledrpwmval == 0)dir = 1;    		/* ledrpwmval递减 到0后,方向改为递增 */

(TIM5->CCR4)=ledrpwmval;    			/* 修改比较值,修改占空 比 */

/* 调用HAL库API函数来修改占空 比 */ //__HAL_TIM_SET_COMPARE(&htim5, TIM_CHANNEL_4, ledrpwmval);

图17.3.5. 10 main.c代码位置 以上代码中,第95行,调用HAL_TIM_PWM_Start函数来开启PWM通道,如果不添加这行代码,则PWM无法正常输出,实际上HAL_TIM_PWM_Start函数也是通过调用TIM_CcxChannelCmd函数来使能定时器的输出通道的。 第106~110行,当dir=1的时候,ledrpwmval递增,当dir=0的时候,ledrpwmval递减。ledrpwmval一开始配置为0,当其从0递增到300的时候,dir等于0,然后ledrpwmval就又递减。这几行代码就是控制ledrpwmval从0递增到300以后,再从300递减到0。 第112行,将不断变化的ledrpwmval值写入TIM5的TIMx_CCR4寄存器中实现动态修改占空比,占空比变化以后,LED0灯就会先逐渐变亮,再逐渐变暗,如此反复。 第112行的代码也可以用114行的来代替,两行代码本质是一样的,114行的是使用HAL库里封装好的API函数来实现,112行的则直接操作寄存器实现。 本小节开头我们就说过PWM波频率由自动重载寄存器(TIMx_ARR)的值决定,其占空比则由捕获/比较寄存器(TIMx_CCRx)的值决定,实验中LED0是低电平有效的,且设置为向上计数模式。下面我们取比较值ledrpwmval为100(也就是TIM5_CCR4的值)时的情况,计算看看占空比。 如果输出极性(也叫比较极性)为低,当计数器TIM5_CNT的值小于100时,通道4为有效电平,LED0亮;当计数器的值大于100时,通道4为无效电平,LED0灭:

如果输出极性为高,当计数器的值小于100时,通道4为无效电平,LED0灭;当计数器的值大于100时,通道4为有效电平,LED0亮:

可以看到输出比较极性为低和输出比较极性为高的占空比正好反过来。 感兴趣大家可以用示波器进行验证。 4. 编译测试 下载代码后,我们将看LED0不停的由暗变到亮,然后又从亮变到暗。每个过程持续时间大概为3秒钟左右(0.005s3002=3s)。 本实验也可以使用中断的方式来做,直接参考上一章节17.2小节的来做,只需要在回调函数中编写配置TIM5_CCR4变化的值即可实现,大家可以尝试,我们已经把工程放到开发板光盘A-基础资料\1、程序源码\11、M4 CubeIDE裸机驱动例程目录下了,文件夹名字为GTIM_PWM_INT。 17.3.6 工程代码分析

  1. tim.c文件 tim.c文件是用于初始化定时器的,代码如下,已经附上详细的注释:
1   #include "tim.h"
2  
3   TIM_HandleTypeDef htim5;							/* 定时器5句柄 */
4   /** 5 * @brief 通用定时器TIM5通道4 PWM输出 初始化函数(使用PWM模式1) 6 * @note 7 * 通用定时器的时钟来自APB1,当APB1DIV≥2分频的时候 8 * 通用定时器的时钟为APB1时钟的2倍, 而APB1为104.5M, 所以定时器时钟 = 209Mhz 9 * 定时器溢出时间计算方法: Tout = ((ARR + 1) * (psc + 1)) / Ft us. 10 * Ft=定时器工作频率,单位:Mhz 11 * @retval 无 12 */
13  void MX_TIM5_Init(void)
14  { 
        
15    /* 定义时钟配置结构体变量sClockSourceConfig */
16    TIM_ClockConfigTypeDef sClockSourceConfig = { 
        0};
17    /* 定义TIM主站配置结构体变量sMasterConfig */
18    TIM_MasterConfigTypeDef sMasterConfig = { 
        0};
19    /* 定义TIM输出比较配置结构体变量sConfigOC */
20    TIM_OC_InitTypeDef sConfigOC = { 
        0};
21 
22    htim5.Instance = TIM5;								/* 定时器5 */
23    htim5.Init.Prescaler = 209-1;						/* 定时器分频 */
24    /* 向上计数模式 */
25    htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
26    htim5.Init.Period = 500-1;							/* 自动重装载值 */
27    /* 时钟分频因子 */
28    htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
29    /* TIM5自动重载使能 */
30    htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
31    /* 初始化定时器时基 */
32    if (HAL_TIM_Base_Init(&htim5) != HAL_OK)
33    { 
        
34      Error_Handler();
35    }
36    /* TIM5时钟源选择,使用内部时钟 */
37    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
38    /* 初始化时钟 */
39    if (HAL_TIM_ConfigClockSource(&htim5, &sClockSourceConfig) != HAL_OK)
40    { 
        
41      Error_Handler();
42    }
43    /* 初始化PWM */
44    if (HAL_TIM_PWM_Init(&htim5) != HAL_OK)
45    { 
        
46      Error_Handler();
47    }
48    /* 主模式触发输出(TRGO)选择选择为复位 */
49    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
50    /* 主/从模式选择关闭 */
51    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
52    /* 主模式配置 */
53    if (HAL_TIMEx_MasterConfigSynchronization(&htim5, \ 																&sMasterConfig) != HAL_OK)
54    { 
        
55      Error_Handler();
56    }
57    sConfigOC.OCMode = TIM_OCMODE_PWM1;/* PWM模式1 */
58    sConfigOC.Pulse = 250;/* 占空比值 */
59    /* 输出极性,这里选择低 */
60    sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
61    /*指定快速模式状态不开启 */
62    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
63    /* 初始化PWM通道 */
64    if (HAL_TIM_PWM_ConfigChannel(&htim5, &sConfigOC, \  																	TIM_CHANNEL_4) != HAL_OK)
65    { 
        
66      Error_Handler();
67    }
68    /* 调用PWM输出通道引脚初始化函数 */
69    HAL_TIM_MspPostInit(&htim5);
70  }
71 
72  /* 使能TIM5时基 */
73  void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
74  { 
        
75    if(tim_baseHandle->Instance==TIM5)
76    { 
        
77      /* TIM5时钟使能 */
78      __HAL_RCC_TIM5_CLK_ENABLE();
79    }
80  
        标签: 100pin母头连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台