细说MCU通过定时器输出PWM波形的实现方法

目录

一、硬件及工程

二、建立工程

三、代码修改

1、重定义回调函数

2、启动定时器中断

四、下载运行


一、硬件及工程

         文章依赖的硬件及工程配置参考本文作者的其他文章:细说ARM MCU的串口接收数据的实现过程-CSDN博客 细说ARM MCU的串口接收数据的实现过程-CSDN博客文章浏览阅读1.2k次,点赞35次,收藏10次。重定义串口中断接收的回调函数HAL_UART_RxCpltCallback()。这个函数已经在stm32g4xx_ hal_uart.c中有定义,只不过被定义为弱函数,实际就是一个空函数。需要重写它。与写EXTI的回调函数类似,也将该函数写在main.c中。串口有数据送来,会执行中断服务函数USART2_IRQHandler(),然后该函数又会调用函数HAL_UART_IRQHandler()。https://wenchm.blog.csdn.net/article/details/139541112

        STM32G474RET6的定时器 

        TIM3有4个通道,所以可配置4个PWM输出:TIM3_CH1、TIM3_CH2、TIM3_CH3和TIM3_CH4。由于STM32有引脚复用功能,信号具体从哪一个引脚输出,是需要配置的。不过,输出的引脚也不是任意的,需要选择特定的引脚。譬如TIM3_CH1这个PWM输出,STM32G474RE中,可通过PA6、PB4和PC6送出。其他通道也分别有对应的可选引脚。当然,对TIM3_CH1而言,虽然可由这三个引脚输出,但最终只能选择其中的一个。对TIM3的这4个PWM信号,选择输出引脚对应关系如下:

TIM3_CH1——PB4
TIM3_CH2——PB5
TIM3_CH3——PB0
TIM3_CH4——PB1

二、建立工程

        通过PB4输出配置一个通道TIM3_CH1。同时也配置了TIM3的中断,并在中断时控制一个GPIO输出脉冲信号,该GPIO可选用PC3引脚。用示波器进行观察PC3和PB4引脚的输出信号波形。

        将PC3配置为输出(GPIO_Output)。在NUCLEO-G474RE板上,PC3通过CN7端子的第37引脚引出。

        在GPIO模式和配置界面中选中PC3,output level =High、GPIO mode=PP、Pull_up、High speed;

        外部时钟、Serial Wire;

         配置定时器:在TIM3的模式(Mode)配置界面,将时钟源设置为Internal Clock;选择PWM Generation CH1。然后,将预分频因子(Prescaler)和计数器周期(Counter Period)分别设置为999和8499(这两个参数从0开始计数),计数模式(Counter Mode)设置为升模式(Up),并使能自动重载(auto-reload preload)。

        预分频因子决定着两次计数之间的时间间隔,这里设置的1000(999+1),是将时钟脉冲分频1000倍。假如时钟频率为170 MHz,则分频1000倍后就是170 kHz。

        将计数周期设置为8499,也就是计数到8499后,重新从0开始计。在计数频率170 kHz之下,计数器的周期为(1/170×10³)×8500≈50(ms),对应的频率为20 Hz。在PWM Generation Channel 1的参数配置中,选择PWM mode 1,脉冲数(Pulse)设置为2125(该参数从1开始),通道极性设置为High。通道极性参数用于指定在Pulse个计数期间,输出的是高电平还是低电平。这里脉冲数Pulse决定着占空比,这里设为2125,是计数器周期的1/4,所以占空比刚好为25%。

        使能TIM3的全局中断。将其抢占式优先级设为1,响应优先级设为0。将System tick timer的抢占式优先级设为最高(0级)。

        将系统时钟(SYSCLK)频率配置为170 MHz。

三、代码修改

        硬件配置完成后,编译、自动生成代码。

        由于配置了TIM3中断,希望在中断发生后通过PC3引脚送出一个脉冲信号,因此,需要重定义TIM3中断的回调函数HAL_TIM_PeriodElapsedCallback()。

1、重定义回调函数

        将回调函数的定义放到main.c后面的注释对中,实现代码如下:

/* USER CODE BEGIN 4 */
/* 定时器中断回调函数操纵GPIO PC3输出波形 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_RESET);
	HAL_Delay(12);
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_3,GPIO_PIN_SET);
}
/* USER CODE END 4 */

2、启动定时器中断

        在定时器中断的例子中通过.ioc文件配置了定时器中断,但在默认情况下并没有开启,所以需要在主程序的初始化代码部分调用库函数HAL_TIM_Base_Start_IT() 以启动定时器中断。

        对定时器的PWM输出而言,配置完成之后,自动生成的代码就已经具备产生PWM信号的条件了,但还是要在初始化时使能PWM。为此,可以调用库函数HAL_TIM_PWM_Start()。该函数有两个参数,一个是指定定时器句柄,另一个是指定需要开启的PWM通道。

        将上述两个库函数放到main函数中,位于while(1)前与TIM3初始化函数MX_TIM3_Init()之间的注释对中:

/* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start_IT(&htim3);
  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
/* USER CODE END 2 */

四、下载运行

        示波器的通道1是PC3输出的波形,该波形是PC3在TIM3中断的控制下产生的一个约12 ms的脉冲(低电平脉冲)。由于在前面配置GPIO参数时,将PC3配置为上拉,即通常情况下是高电平输出,并且在TIM3的中断回调函数中,先让PC3输出0,延时12 ms,随后又输出1,所以最终产生了此波形。

        示波器的通道2是PB4 PWM的输出波形。这是一个正脉冲,高电平所占时间为12.5 ms,周期实际为50 ms,占空比为25%,与前面设置的参数保持一致。这里的PWM之所以是正脉冲,是因为前面配置PWM输出通道极性时选择了High,如果选择的是Low,则这个波形会刚好反过来,类似于通道1中的波形。

 

相关推荐

  1. 细说MCU定时器中断实现方法

    2024-06-18 16:10:02       8 阅读
  2. 【国产MCU】-CH32V307-通用定时器(GPTM)-PWM输出

    2024-06-18 16:10:02       39 阅读
  3. GD32F4xx 通用定时器输出PWM

    2024-06-18 16:10:02       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-18 16:10:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-18 16:10:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-18 16:10:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-18 16:10:02       20 阅读

热门阅读

  1. Docker 仓库管理

    2024-06-18 16:10:02       6 阅读
  2. HTML|02HTML标签

    2024-06-18 16:10:02       9 阅读
  3. 通用大模型VS垂直大模型对比

    2024-06-18 16:10:02       6 阅读
  4. 206. 反转链表

    2024-06-18 16:10:02       8 阅读
  5. 编程旋转代码怎么编程:深入探索与实用指南

    2024-06-18 16:10:02       6 阅读
  6. 43.139.152.26 P2315 分数计算

    2024-06-18 16:10:02       7 阅读
  7. 银河粒子InsCode

    2024-06-18 16:10:02       5 阅读