Nuru_Banmian
Nuru_Banmian
Published on 2025-07-15 / 50 Visits
0
0

高级定时器_输出有限个PWM波_寄存器&HAL库实现

需求描述

用寄存器实现。输出5个周期的PWM波,频率2Hz,观察发光二极管闪烁5次,或者用示波器观察波形。

需求实现思路:使用高级定时器的重复计数器,当计数器溢出时,在溢出中断中停止定时器工作。重复计数器寄存器的值设置为4,即可输出5个周期的PWM波,发光二极管会闪烁5次。

使用到的寄存器

设置重复计数器

高级定时器-输出有限个PWM波-设置重复计数器.png

主输出使能

高级定时器-输出有限个PWM波-主输出使能-1.png

高级定时器-输出有限个PWM波-主输出使能-2.png

寄存器实现

tim1.h

#ifndef __TIM1_H
#define __TIM1_H

#include "stm32f10x.h"
#include <stdio.h>

void TIM1_Init(void);

// 将定时器的开关包装成函数
void TIM1_Start(void);
void TIM1_Stop(void);

#endif

tim1.c

#include "tim1.h"

void TIM1_Init(void)
{
    // 1. 开启时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;

    // 2. GPIO工作模式,PA8:复用推挽输出 CNF-10,MODE-11
    GPIOA->CRH |= GPIO_CRH_MODE8;
    GPIOA->CRH |= GPIO_CRH_CNF8_1;
    GPIOA->CRH &= ~GPIO_CRH_CNF8_0;

    // 定时器配置

    // 3. 时基部分
    // 3.1 预分频值 7199,得到 10000 Hz
    TIM1->PSC = 7199;

    // 3.2 重装载值,4999,每0.5s产生一次溢出
    TIM1->ARR = 4999;

    // 3.3 计数方向
    TIM1->CR1 &= ~TIM_CR1_DIR;

    // 3.4 重复计数
    TIM1->RCR = 4;

    // 4. 输出通道部分

    // 4.1 配置通道1为输出模式
    TIM1->CCMR1 &= ~TIM_CCMR1_CC1S;

    // 4.2 配置通道1为 PWM1 模式,OC1M - 110
    TIM1->CCMR1 |= TIM_CCMR1_OC1M_2;
    TIM1->CCMR1 |= TIM_CCMR1_OC1M_1;
    TIM1->CCMR1 &= ~TIM_CCMR1_OC1M_0;

    // 4.3 配置CCR,占空比50%
    TIM1->CCR1 = 2500;

    // 4.4 配置极性
    TIM1->CCER &= ~TIM_CCER_CC1P;

    // 4.5 产生一个更新事件,刷新寄存器的值
    TIM1->CR1 |= TIM_CR1_URS;
    TIM1->EGR |= TIM_EGR_UG;
    // TIM1->SR &= ~TIM_SR_UIF;

    // 4.6 通道1使能
    TIM1->CCER |= TIM_CCER_CC1E;

    // 4.7 主输出使能
    TIM1->BDTR |= TIM_BDTR_MOE;

    // 5. 中断功能
    // 5.1 更新中断使能
    TIM1->DIER |= TIM_DIER_UIE;

    // 5.2 NVIC配置
    NVIC_SetPriorityGrouping(3);
    NVIC_SetPriority(TIM1_UP_IRQn, 3);
    NVIC_EnableIRQ(TIM1_UP_IRQn);
}

// 将定时器的开关包装成函数
void TIM1_Start(void)
{
    TIM1->CR1 |= TIM_CR1_CEN;
}

void TIM1_Stop(void)
{
    TIM1->CR1 &= ~TIM_CR1_CEN;
}

// 中断服务程序
void TIM1_UP_IRQHandler(void)
{
    printf("into interrupt...\n");
    // 清除中断标志位
    TIM1->SR &= ~TIM_SR_UIF;

    // 停掉定时器
    TIM1_Stop();
}

main.c

#include "usart.h"
#include "tim1.h"
#include "delay.h"

int main(void)
{
	// 初始化
	USART_Init();
	TIM1_Init();

	printf("Hello, world!\n");

	// 开启定时器
	TIM1_Start();

	while (1)
	{
	}
}

HAL库实现

HAL库配置

高级定时器-输出有限个PWM波-HAL库配置-1.png

高级定时器-输出有限个PWM波-HAL库配置-2.png

高级定时器-输出有限个PWM波-主输出使能-3.png

tim.c

/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    /* 关闭计数器 */
    if (htim->Instance == TIM1)
    {
       //HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
       
       TIM1->CCER &= ~TIM_CCER_CC1E;
       TIM1->BDTR &= ~TIM_BDTR_MOE;
       htim->Instance->CR1 &= ~TIM_CR1_CEN;
    }
}
/* USER CODE END 1 */

main.c

int main(void)
{
  
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_TIM1_Init();
  MX_USART1_UART_Init();
    
    /*初始化的时候 UG已经被置位.  先清除中断标志位,防止一启动就进入中断 */
    __HAL_TIM_CLEAR_IT(&htim1, TIM_IT_UPDATE);
    /* 启用更新中断 */
    __HAL_TIM_ENABLE_IT(&htim1, TIM_IT_UPDATE);
    
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    while (1)

    {
    }
}


Comment