外设高级定时器输出指定个数PWM实验

 高级定时器简介

高级定时器框图

高级定时器的框图和通用定时器框图很类似,只是添加了其它的一些功能,如:重复计数 器、带死区控制的互补输出通道、断路输入等。这些功能在高级定时器框图的位置如下: 上图中,框出来三个部分,这是和通用定时器不同的地方,下面来分别介绍它们。

① 重复计数器

在 F1 系列中,高级定时器 TIM1 和 TIM8 都有重复计数器。下面来介绍一下重复计数器有 什么作用?在学习基本定时器和通用定时器的时候,我们知道定时器发生上溢或者下溢时,会 直接生成更新事件。但是有重复计数器的定时器并不完全是这样的,定时器每次发生上溢或下 溢时,重复计数器的值会减一,当重复计数器的值为 0 时,再发生一次上溢或者下溢才会生成 定时器更新事件。如果我们设置重复计数器寄存器 RCR 的值为 N,那么更新事件将在定时器发 生 N+1 次上溢或下溢时发生。

这里需要注意的是重复计数器寄存器是具有影子寄存器的,所以 RCR 寄存器只是起缓冲 的作用。RCR 寄存器的值会在更新事件发生时,被转移至其影子寄存器中,从而真正生效。

重复计数器的特性,在控制生成 PWM 信号时很有用,后面会有相应的实验。

② 输出比较

高级定时器输出比较部分和通用定时器相比,多了带死区控制的互补输出功能。图 22.1.1 第②部分的 TIMx_CH1N、TIMx_CH2N 和 TIMx_CH3N 分别是定时器通道 1、通道 2 和通道 3 的互补输出通道,通道 4 是没有互补输出通道的。DTG 是死区发生器,死区时间由 DTG[7:0]位 来配置。如果不使用互补通道和死区时间控制,那么高级定时器 TIM1 和 TIM8 和通用定时器 的输出比较部分使用方法基本一样,只是要注意 MOE 位得置 1 定时器才能输出。

如果使用互补通道,那么就有一定的区别了,具体我们在高级定时器互补输出带死区控制 实验小节再来介绍。

③ 断路功能

断路功能也称刹车功能,一般用于电机控制的刹车。F1 系列有一个断路通道,断路源可以 是刹车输入引脚(TIMx_BKIN),也可以是一个时钟失败事件。时钟失败事件由复位时钟控制器 中的时钟安全系统产生。系统复位后,断路功能默认被禁止,MOE 位为低。

使能断路功能的方法:将 TIMx_BDTR 的位 BKE 置 1。断路输入引脚 TIMx_BKIN 的输入 有效电平可通过 TIMx_BDTR 寄存器的位 BKP 设置。

使能刹车功能后:由 TIMx_BDTR 的 MOE、OSSI、OSSR 位,TIMx_CR2 的 OISx、OISxN 位,TIMx_CCER 的 CCxE、CCxNE 位控制 OCx 和 OCxN 输出状态。无论何时,OCx 和 OCxN 输出都不能同时处在有效电平。

当发生断路输入后,会怎么样?

1,MOE 位被异步地清零,OCx 和 OCxN 为无效、空闲或复位状态(由 OSSI 位选择)。

2,OCx 和 OCxN 的状态:由相关控制位状态决定,当使用互补输出时:根据情况自动控 制输出电平,参考《STM32F10xxx 参考手册_V10(中文版).pdf》手册第 245 页的表 75 带刹车 功能的互补通道 Ocx 和 OcxN 的控制位。

3,BIF 位置 1,如果使能了 BIE 位,还会产生刹车中断;如果使能了 TDE 位,会产生 DMA 请求。

4,如果 AOE 位置 1,在下一个 更新事件 UEV 时,MOE 位被自动置 1。

高级定时器框图部分就简单介绍到这里,下面通过实际的实验来学习高级定时器。

高级定时器输出指定个数PWM实验原理

高级定时器输出指定个数PWM实验配置步骤

相关HAL库函数介绍 

代码

atim.c

#include "./BSP/ATIM/atim.h"

TIM_HandleTypeDef g_timx_npwm_chy_handle;/* 定时器x句柄 */

/* g_npwm_remain表示当前还剩下多少个脉冲要发送
 * 每次最多发送256个脉冲
 */
static uint8_t g_npwm_remain = 0;

void atim_timx_npwm_chy_init(uint16_t psc, uint16_t arr)
{
    TIM_OC_InitTypeDef timx_oc_npwm_chy = {0};/* 定时器输出 */
    
    g_timx_npwm_chy_handle.Instance = TIM8;
    g_timx_npwm_chy_handle.Init.Prescaler = psc;
    g_timx_npwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    g_timx_npwm_chy_handle.Init.Period = arr;
    g_timx_npwm_chy_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; /*使能TIMx_ARR进行缓冲 */
    g_timx_npwm_chy_handle.Init.RepetitionCounter = 0;
    HAL_TIM_PWM_Init(&g_timx_npwm_chy_handle);
    
    timx_oc_npwm_chy.OCMode = TIM_OCMODE_PWM1;
    timx_oc_npwm_chy.Pulse = arr / 2;
    timx_oc_npwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH;
    HAL_TIM_PWM_ConfigChannel(&g_timx_npwm_chy_handle, &timx_oc_npwm_chy, TIM_CHANNEL_1);/* 配置TIMx通道y */
    
    __HAL_TIM_ENABLE_IT(&g_timx_npwm_chy_handle, TIM_IT_UPDATE);/* 允许更新中断 */
    HAL_TIM_PWM_Start(&g_timx_npwm_chy_handle, TIM_CHANNEL_1);/* 开启对应PWM通道 */
}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM8)
    {
        GPIO_InitTypeDef gpio_init_struct;
        __HAL_RCC_TIM8_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();
        
        gpio_init_struct.Pin = GPIO_PIN_6;
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;
        gpio_init_struct.Pull = GPIO_PULLUP;
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOC, &gpio_init_struct);
        
        HAL_NVIC_SetPriority(TIM8_UP_IRQn, 1, 3);
        HAL_NVIC_EnableIRQ(TIM8_UP_IRQn);
    }
}

void atim_timx_npwm_chy_set(uint8_t npwm)
{
    if(npwm == 0)
    {
        return;
    }
    else
    {
        g_npwm_remain = npwm;/* 保存脉冲个数 */
        HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handle, TIM_EVENTSOURCE_UPDATE);/* 产生一次更新事件,在中断里面处理脉冲输出 */
        __HAL_TIM_ENABLE(&g_timx_npwm_chy_handle);
    }
}

void TIM8_UP_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_timx_npwm_chy_handle);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM8)
    {
        if(g_npwm_remain)
        {
            TIM8->RCR = g_npwm_remain - 1;
            HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handle, TIM_EVENTSOURCE_UPDATE);
            __HAL_TIM_ENABLE(&g_timx_npwm_chy_handle);
            g_npwm_remain = 0;
        }
        else
        {
            TIM8->CR1 &= ~(1 << 0);
        }
    }
}






main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/ATIM/atim.h"

int main(void)
{
    uint8_t key;
    uint8_t t = 0;
    
    HAL_Init();                         /* 初始化 HAL 库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    usart_init(115200);                 /* 串口初始化为115200 */
    
    led_init();
    key_init();
    atim_timx_npwm_chy_init(7200 - 1, 5000 - 1); /* 10Khz的计数频率,2hz的PWM频率. */
    atim_timx_npwm_chy_set(5);/* 输出5个PWM波(控制LED1(BLUE)闪烁5次) */
    
    /* 将 LED1 引脚设置为输入模式, 避免和PC6冲突 */
    GPIO_InitTypeDef gpio_init_struct;
    __HAL_RCC_GPIOE_CLK_ENABLE();
    gpio_init_struct.Pin = GPIO_PIN_5;
    gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOE, &gpio_init_struct);
    
    while(1)
    {
        key = key_scan(0);
        if(key == KEY0_PRES)/* KEY0按下 */
        {
            atim_timx_npwm_chy_set(6);/* 输出6个PWM波(控制TIM8_CH1, 即PC6输出6个脉冲) */
        }
        
        t++;
        if(t > 20)
        {
            t=0;
            LED0_TOGGLE();
        }
        delay_ms(10);
    }
}




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值