STM32——高级定时器输出指定个数PWM波原理及实战

1.高级定时器简介(TIM8、TIM1)

相比于通用定时器特性:
1)重复计数器
2)死区时间带可编程的互补输出
3)断路输入,用于将定时器的输出信号置于用户可选的安全配置中

2.高级定时器框图

在这里插入图片描述

3.重复计数器特性及输出指定个数PWM波实战

在这里插入图片描述

4.高级定时器输出指定个数PWM波原理

在这里插入图片描述

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

1,配置定时器基础工作参数 HAL_TIM_PWM_Init()
2,定时器PWM输出MSP初始化 HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
3,配置PWM模式/比较值等 HAL_TIM_PWM_ConfigChannel()
4,设置优先级,使能中断 HAL_NVIC_SetPriority()、 HAL_NVIC_EnableIRQ()
5,使能定时器更新中断 __HAL_TIM_ENABLE_IT()
6,使能输出、主输出、计数器 HAL_TIM_PWM_Start()
7,编写中断服务函数 TIMx_IRQHandler()等  HAL_TIM_IRQHandler()
8,编写更新中断回调函数 HAL_TIM_PeriodElapsedCallback()
在这里插入图片描述

6.高级定时器输出指定个数PWM实战

1.通过定时器8通道1实现指定个数PWM输出,用于控制LED1的亮灭
2,配置输出比较模式为:PWM模式1
通道输出极性为:高电平有效
占空比:50%
代码:

6.1 atim.c

#include "./BSP/TIMER/atim.h"
#include "./BSP/LED/led.h"
//1.声明定时器句柄
TIM_HandleTypeDef  g_timx_npwm_chy_handler;
static uint32_t g_npwm_remain = 0;
/**
 * @brief       高级定时器TIMX 通道Y PWM输出指定个数PWM 初始化函数(使用PWM模式1)
 * @note
 *              高级定时器的时钟来自APB2,而PCLK =168Mhz,我们设置PPRE2不分频
 *              高级定时器的时钟 = 168Mhz
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft = 定时器工作频率,单位:Mhz
 *
 * @param       arr: 自动重装值
 * @param       psc: 预分频系数
 * @retval      无
 */
//2.配置通用定时器基本工作参数,PWM输出初始化
void atim_timx_npwm_chy_init(uint16_t arr, uint16_t psc)    /* 通用定时器 PWM初始化函数 */  
{
    //4.1定时器输出比较定时器结构体初始化
    TIM_OC_InitTypeDef tim_oc_npwm_chy = {0};
    
    //2.1通用定时器PWM输出初始化
    g_timx_npwm_chy_handler.Instance = ATIM_TIMX_NPWM;                  //定时器x
    g_timx_npwm_chy_handler.Init.Period = arr;
    g_timx_npwm_chy_handler.Init.Prescaler = psc;
    g_timx_npwm_chy_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
    g_timx_npwm_chy_handler.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; /* 使能TIMx_ARR进行缓冲 */
    g_timx_npwm_chy_handler.Init.RepetitionCounter = 0;                  /* 重复计数器初始值 */
    HAL_TIM_PWM_Init(&g_timx_npwm_chy_handler);
    
    
    //5.输出比较配置包,括PWM模式和比较值
    tim_oc_npwm_chy.OCMode = TIM_OCMODE_PWM1;          //输出比较模式 PWM1
    tim_oc_npwm_chy.Pulse = arr/2;                     //设置比较值为自动加载值的一般,则占空比为50%
    tim_oc_npwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH;   //设置输出比较的极性为高
    HAL_TIM_PWM_ConfigChannel(&g_timx_npwm_chy_handler,&tim_oc_npwm_chy,ATIM_TIMX_NPWM_CHY);
    
    //6,使能定时器更新中断
    __HAL_TIM_ENABLE_IT(&g_timx_npwm_chy_handler,TIM_IT_UPDATE);
    
    //7,开启对应PWM通道使能输出并启动计时器
    HAL_TIM_PWM_Start(&g_timx_npwm_chy_handler,ATIM_TIMX_NPWM_CHY);
 
    
}
//3.定时器PWM输出底层初始化,定时器时钟、引脚时钟使能,引脚复用配置
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef * htm)
{
    //3.1判断是否是TIM14
    if(htm->Instance ==  ATIM_TIMX_NPWM)
    {
         GPIO_InitTypeDef gpio_init_struct;
     
        //3.3使能PF引脚口时钟
        ATIM_TIMX_NPWM_CHY_GPIO_CLK_ENABLE();
        
        //3.4使能定时器时钟
        ATIM_TIMX_NPWM_CHY_CLK_ENABLE();
       
       
      //3.2通道y的GPIO初始化
      gpio_init_struct.Pin = ATIM_TIMX_NPWM_CHY_GPIO_PIN;      /* 通道Y GPIO口 */
      gpio_init_struct.Mode = GPIO_MODE_AF_PP;                /* 复用推挽输出 */
      gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
      gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */ 
      gpio_init_struct.Alternate =ATIM_TIMX_NPWM_CHY_GPIO_AF; /* 端口复用到TIM8 */ 
      HAL_GPIO_Init(ATIM_TIMX_NPWM_CHY_GPIO_PORT, &gpio_init_struct);  

      //4 设置优先级、使能中断
      HAL_NVIC_SetPriority(ATIM_TIMX_NPWM_IRQn,1,3); 
      HAL_NVIC_EnableIRQ(ATIM_TIMX_NPWM_IRQn);
    
    }
}


/* 定时器8中断服务函数 */
void ATIM_TIMX_NPWM_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_timx_npwm_chy_handler);
}

/* 定时器更新中断回调函数 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{

     if(htim->Instance == ATIM_TIMX_NPWM)  //如果是TIM8
     {
         if(g_npwm_remain)//如果重复计数值大于0,则需要发送PWM波
         {
             ///* 设置重复计数寄存器值为npwm-1, 即npwm个脉冲 */
             ATIM_TIMX_NPWM->RCR = g_npwm_remain - 1;
             //通过软件更新事件,将RCR值缓冲到影子寄存器里面
             HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handler, TIM_EVENTSOURCE_UPDATE);
             //使能计数器
             __HAL_TIM_ENABLE(&g_timx_npwm_chy_handler);
             //清零
            g_npwm_remain = 0;
         }
         else
         {
            //关闭计数器
             ATIM_TIMX_NPWM->CR1 &= ~(1 << 0);  /* 关闭定时器TIMX,使用HAL Disable会清除PWM通道信息,此处不用 */
         }
     }
}
/**
 * @brief       高级定时器TIMX NPWM设置PWM个数
 * @param       rcr: PWM的个数, 1~2^32次方个
 * @retval      无
 */
void atim_timx_npwm_chy_set(uint32_t npwm)
{
    if(npwm == 0) return ;
    
    g_npwm_remain = npwm;
    //通过软件更新事件,将RCR值缓冲到影子寄存器里面
    HAL_TIM_GenerateEvent(&g_timx_npwm_chy_handler, TIM_EVENTSOURCE_UPDATE);
    //使能计数器
    __HAL_TIM_ENABLE(&g_timx_npwm_chy_handler);

}

6.2 atim.h

#ifndef __ATIM_H
#define __ATIM_H

#include "./SYSTEM/sys/sys.h"


/******************************************************************************************/
/* 高级定时器 定义 */

 /* TIMX 输出指定个数PWM 定义 
 * 这里输出的PWM通过PC6(TIM8_CH1)输出, 我们用杜邦线连接PC6和PF10, 然后在程序里面将PF10设置成浮空输入
 * 就可以 看到TIM8_CH1控制LED1(GREEN)的亮灭, 亮灭一次表示一个PWM波
 * 默认使用的是TIM8_CH1.
 * 注意: 通过修改这几个宏定义, 可以支持TIM1/TIM8定时器, 任意一个IO口输出指定个数的PWM
 */
#define ATIM_TIMX_NPWM_CHY_GPIO_PORT            GPIOC
#define ATIM_TIMX_NPWM_CHY_GPIO_PIN             GPIO_PIN_6
#define ATIM_TIMX_NPWM_CHY_GPIO_CLK_ENABLE()    do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0) /* PC口时钟使能 */
#define ATIM_TIMX_NPWM_CHY_GPIO_AF              GPIO_AF3_TIM8

#define ATIM_TIMX_NPWM                          TIM8
#define ATIM_TIMX_NPWM_IRQn                     TIM8_UP_TIM13_IRQn
#define ATIM_TIMX_NPWM_IRQHandler               TIM8_UP_TIM13_IRQHandler
#define ATIM_TIMX_NPWM_CHY                      TIM_CHANNEL_1                               /* 通道Y,  1<= Y <=4 */
#define ATIM_TIMX_NPWM_CHY_CCRX                 TIM8->CCR1                                  /* 通道Y的输出比较寄存器 */
#define ATIM_TIMX_NPWM_CHY_CLK_ENABLE()         do{ __HAL_RCC_TIM8_CLK_ENABLE(); }while(0)  /* TIM8 时钟使能 */

void atim_timx_npwm_chy_init(uint16_t arr, uint16_t psc);   /* 高级定时器 输出指定个数PWM初始化函数 */
void atim_timx_npwm_chy_set(uint32_t npwm);                 /* 高级定时器 设置输出PWM的个数 */

#endif

6.3 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/TIMER/atim.h"


int main(void)
{
    uint8_t key = 0;
    uint8_t t = 0;
    GPIO_InitTypeDef gpio_init_struct;
    
    HAL_Init();                                 /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7);         /* 设置时钟,168Mhz */
    delay_init(168);                            /* 延时初始化 */
    usart_init(115200);                         /* 串口初始化为115200 */
    led_init();                                 /* 初始化LED */
    key_init();                                 /* 初始化按键 */
    
    /* 将 LED1 引脚设置为输入模式, 避免和PC6冲突 */
    gpio_init_struct.Pin = LED1_GPIO_PIN;                   /* LED1引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                /* 设置为输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;     /* 高速模式 */
    HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct);       /* 初始化LED1引脚 */
    
    atim_timx_npwm_chy_init(10000 - 1, 8400 - 1);           /* 20Khz的计数频率,2Hz的PWM频率. */

    ATIM_TIMX_NPWM_CHY_CCRX = 5000; /* 设置PWM占空比,50%,这样可以控制每一个PWM周期,LED1(GREEN)
                                     * 有一半时间是亮的,一半时间是灭的,LED1亮灭一次,表示一个PWM波
                                     */
    atim_timx_npwm_chy_set(5);      /* 输出5个PWM波(控制LED1(GREEN)闪烁5次) */
    
    while (1)
    {
       key = key_scan(0);

        if (key == KEY0_PRES)           /* KEY0按下 */
        {
            atim_timx_npwm_chy_set(5);  /* 输出5个PWM波(控制TIM8_CH1, 即PC6输出5个脉冲) */
        }

        t++;
        delay_ms(10);

        if (t > 50)                     /* 控制LED0闪烁, 提示程序运行状态 */
        {
            t = 0;
            LED0_TOGGLE();
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/305092.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SSM(spring+springmvc+mybatis)整合

spring与SpringMvc的常用注解 一、spring常用注解&#xff1a; Component&#xff1a;实现bean的注入&#xff08;不过获取bean需要用bean的类型来获取&#xff08;即class文件&#xff09;&#xff09; controller、Service、Repository的作用等同于Component注解的作用&…

TS中的类

目录 ES6的类 类的概念 类的构成 类的创建 声明 构造函数 定义内容 创建实例 TS中的类 类声明 构造函数 属性和方法 实例化类 继承 访问修饰符 public private protected 成员访问修饰符的使用原则 访问器 只读成员与静态成员 readonly static 修饰符总…

remote-ssh如何离线下载历史版本

remote-ssh离线下载任意历史版本方法&#xff0c;简单有效 很多小伙伴都会遇到这样的问题&#xff0c;由于内网服务器中安装的vs code版本较低&#xff0c;比如1.62.0版本&#xff0c;官网发布的version history 只展示最新的五个版本&#xff0c;还是太高了&#xff0c;导致下…

TypeScript 和 jsdom 库创建爬虫程序示例

TypeScript 简介 TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集&#xff0c;可以编译生成纯 JavaScript 代码。TypeScript 增加了可选的静态类型和针对对象的编程功能&#xff0c;使得开发更加大规模的应用容易。 jsdom 简介 jsdom 是一个…

VS中打开ui文件闪退

解决办法&#xff1a; 依次点击《扩展》-> 《Qt vs tools》-> 《options》-> 《Qt》-> 《general》 -> 《Qt Designer》 -> 《run in detached window》 -> true

用Java编写图书网站信息采集程序教程

目录 一、准备工作 二、分析目标网站结构 三、选择信息采集方式 四、安装Jsoup库 五、编写信息采集程序 六、注意事项 总结&#xff1a; 编写图书网站信息采集程序需要掌握HTML、CSS、JavaScript、Java等前端和后端技术。下面是一个简单的教程&#xff0c;介绍如何使用…

游戏开发中,你的游戏图片压缩格式使用ASTC了吗

文章目录 ASTC原理&#xff1a;使用要求 ASTC&#xff08;Adaptive Scalable Texture Compression&#xff0c;自适应可伸缩纹理压缩&#xff09;是一种高级的纹理压缩技术&#xff0c;由ARM公司开发并推广。它在图形处理领域中因其出色的压缩效率和灵活性而受到广泛关注。 AST…

上门洗衣洗鞋小程序多门店管理模式是怎么样的

做干洗店和洗鞋店的老板们很多都不止一个门店&#xff0c;多门店的管理模式下&#xff0c;去做一个上门洗衣洗鞋小程序&#xff0c;需要有哪些必要的功能才能让不同的门店管理起来不乱呢。首先需要先确定一下不同门店的管理都会面临哪些经营场景和需求。 第一&#xff0c;加盟店…

【前端素材】bootstrap4实现服装鞋饰电商平台Doron

一、需求分析 一个服装鞋饰电子商务页面是一个在线平台&#xff0c;用于展示和销售各种服装、鞋子和配饰产品。它通常具有以下功能&#xff1a; 产品展示&#xff1a;服装鞋饰电子商务页面会展示各种服装、鞋子和配饰产品的图片、描述和价格。这些产品可以按照不同的分类&#…

FreeRTOS学习总结(二)FreeRTOS任务创建和删除API函数

实现动态创建任务流程 任务控制块结构体成员介绍 typedef struct tskTaskControlBlock {volatile StackType_t * pxTopOfStack; /* 任务栈栈顶&#xff0c;必须为TCB第一个成员 */ListItem_t xStateListItem; /* 任务状态列表项 */ Li…

免费IDEA插件推荐:Apipost-Helper

IDEA插件市场中的API调试插件不是收费&#xff08;Fast Request &#xff09;就是不好用&#xff08;apidoc、apidocx等等&#xff09;今天给大家介绍一款国产的API调试插件&#xff1a;Apipost-Helper&#xff0c;完全免费且好看好用&#xff01; 这款插件由Apipost团队开发的…

llama.cpp模型推理之界面篇

目录 前言 一、llama.cpp 目录结构 二、llama.cpp 之 server 学习 1. 介绍 2. 编译部署 3. 启动服务 4、扩展或构建其他的 Web 前端 5、其他 前言 在《基于llama.cpp学习开源LLM本地部署》这篇中介绍了基于llama.cpp学习开源LLM本地部署。在最后简单介绍了API 的调用方…

什么是API网关代理?

带有API网关的代理服务显着增强了用户体验和性能。特别是对于那些使用需要频繁创建和轮换代理的工具的人来说&#xff0c;使用 API 可以节省大量时间并提高效率。 了解API API&#xff08;即应用程序编程接口&#xff09;充当服务提供商和用户之间的连接网关。通过 API 连接&a…

【仙丹秘法】如何炼制一颗稳定的仙丹

提示词始终保持不变 1&#xff1a;收集素材 制作lora_v1 2: 制作lora_v1 产生 1个人物 含 你想要的服装 导入 pose_1 到 control 1 生成人物 (white_background:1.1),front view,1boy,blue sleeveless t-shirt,blue shorts,detailed eyes,best quality,masterpiece,high res…

蓝凌EIS智慧协同平台 UniformEntry.aspx sql注入漏洞

漏洞描述&#xff1a; 蓝凌EIS智慧协同平台是一个简单、高效的工作方式专为成长型企业打造的沟通、协同、社交的移动办公平台&#xff0c;覆盖OA、沟通、客户、人事、知识等管理需求&#xff0c;集合了非常丰富的模块&#xff0c;满足组织企业在知识、项目管理系统建设等需求的…

C语言基础语法跟练

题源&#xff1a;牛客网 1、输出"Hello Nowcoder!"。开始你的编程之旅吧。 #include <stdio.h>int main() {printf("Hello Nowcoder!");return 0; } 2、KiKi学会了printf在屏幕输出信息&#xff0c;他想输出一架小飞机。请帮他编写程序输出这架小…

解析游戏开发中的ECS设计模式:实体、组件、系统的完美协同

ECS&#xff08;Entity-Component-System&#xff09;是一种设计模式&#xff0c;通常用于构建和管理具有大量实体和复杂交互的系统&#xff0c;尤其在游戏开发中得到广泛应用。这个模式的核心思想是将系统中的组件、实体和系统进行分离&#xff0c;以提高代码的可维护性、可扩…

openGauss学习笔记-189 openGauss 数据库运维-常见故障定位案例-TPCC-WAL-内存

文章目录 openGauss学习笔记-189 openGauss 数据库运维-常见故障定位案例-TPCC-WAL-内存189.1 TPCC运行时&#xff0c;注入磁盘满故障&#xff0c;TPCC卡住的问题189.1.1 问题现象189.1.2 原因分析189.1.3 处理分析 189.2 备机处于need repair(WAL)状态问题189.2.1问题现象189.…

N5224B PNA 微波网络分析仪,900 Hz/10 MHz 至 43.5 GHz

01 N5224B PNA 微波网络分析仪 产品综述&#xff1a; Keysight N5224B PNA 微波网络分析仪&#xff08;10 MHz 至 43.5 GHz&#xff09;是一款灵活的综合测试引擎&#xff0c;能够测量放大器、混频器和变频器等有源器件。 这款分析仪的工作频率范围为 900 Hz 至 43.5 GHz。 …

【代码随想录】刷题笔记Day47

前言 又过了个愉快的周末~大组会终于不用开了&#xff0c;理论上已经可以回家了&#xff01;但是我多留学校几天吧&#xff0c;回家实在太无聊了&#xff0c;也没太多学习的氛围 198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; dp[i]含义 考虑下标i&#xff08;包括…