RT-Thread Studio学习(十六)定时器计数

RT-Thread Studio学习(十六)定时器计数

  • 一、简介
  • 二、新建RT-Thread项目并使用外部时钟
  • 三、启用PWM输入捕获功能
  • 四、测试

一、简介

本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下使用定时器对输入脉冲进行计数。

硬件及开发环境如下:

  • OS WIN10
  • STM32F407VET6
  • STM32CubeMX v6.10.0
  • STM32Cube MCU Package for STM32F4 Series v1.28.0
  • RT-Thread Studio v2.2.7
  • RT-Thread Source Code v5.0.2
  • STM32F4 chip support packages v0.2.3

二、新建RT-Thread项目并使用外部时钟

打开RT-Thread Studio软件新建基于芯片的项目,并使用外部时钟系统,具体参见《RT-Thread Studio学习(一)使用外部时钟系统》。

三、启用PWM输入捕获功能

  1. 打开PWM驱动框架
    RT-Thread Setting 中借助图形化配置工具打开组件中的HWTIMER的驱动框架,如下图所示:
    在这里插入图片描述

  2. 定义TIM相关的宏
    将TIM5配置为PWM输入模式,在board.h文件中使能宏定义:

#define BSP_USING_TIM
#ifdef BSP_USING_TIM
#define BSP_USING_TIM5
#endif
  1. 复制TIM初始化函数
    双击RT-Thread Studio工程中的cubemx.ioc文件,使能TIM5。设置Slave Mode为External Clock Mode 1,设置Trigger Source为TI1FP1。具体如下图:
    在这里插入图片描述
    不要使能TIM5的全局中断!

再重新生成STM32CubeMX代码,将.\cubemx\Src\tim.c中的函数HAL_TIM_Base_MspInitHAL_TIM_MspPostInit复制到board.c的末尾。
再次复制函数HAL_TIM_Base_MspInitboard.c的末尾,并将其函数名改成HAL_TIM_PWM_MspInit

在Application文件夹中添加头文件pwm_input.h,代码如下:

#ifndef APPLICATIONS_PWM_INPUT_H_
#define APPLICATIONS_PWM_INPUT_H_

#include <rtthread.h>
#include <board.h>

extern uint16_t PWM_RisingCount;
extern uint16_t PWM_FallingCount;
extern float duty;

extern TIM_HandleTypeDef htim5;

void MX_TIM2_Init(void);
void MX_TIM5_Init(void);
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);


#endif /* APPLICATIONS_PWM_INPUT_H_ */

在上文《RT-Thread Studio学习(十五)PWM测量》的源文件pwm_input.c添加代码:

TIM_HandleTypeDef htim5;
/* TIM5 init function */
void MX_TIM5_Init(void)
{

  /* USER CODE BEGIN TIM5_Init 0 */

  /* USER CODE END TIM5_Init 0 */

  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM5_Init 1 */

  /* USER CODE END TIM5_Init 1 */
  htim5.Instance = TIM5;
  htim5.Init.Prescaler = 0;
  htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim5.Init.Period = 4294967295;
  htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim5) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_EXTERNAL1;
  sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
  sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;
  sSlaveConfig.TriggerFilter = 0;
  if (HAL_TIM_SlaveConfigSynchro(&htim5, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim5, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM5_Init 2 */
  HAL_TIM_Base_Start(&htim5);
  /* USER CODE END TIM5_Init 2 */

}

修改.\drivers\include\config\tim_config.h文件,在tim_config.h中添加代码:


#ifdef BSP_USING_TIM5
#ifndef TIM5_CONFIG
#define TIM5_CONFIG                                         \
    {                                                       \
       .tim_handle.Instance     = TIM5,                     \
       .tim_irqn                = TIM5_IRQn,                \
       .name                    = "timer5",                 \
    }
#endif /* TIM5_CONFIG */
#endif /* BSP_USING_TIM5 */
  1. 定义.\cubemx\Inc\stm32f4xx_hal_conf.h中的相关宏
#define HAL_TIM_MODULE_ENABLED

四、测试

修改main.c的代码为:

#include <rtthread.h>
#include "stm32f4xx.h"
#include <rtdevice.h>

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#include "pwm_input.h"

// PD12    ------> TIM4_CH1
// PA6     ------> TIM13_CH1
// PA7     ------> TIM14_CH1
// PA1     ------> TIM2_CH2
// PA0-WKUP------> TIM5_CH1

#define PWM4_DEV_NAME         "pwm4"   /* PWM设备名称 */
#define PWM13_DEV_NAME        "pwm13"  /* PWM设备名称 */
#define PWM14_DEV_NAME        "pwm14"  /* PWM设备名称 */
#define PWM_DEV_CHANNEL     1        /* PWM通道 */
struct rt_device_pwm *pwm_dev;      /* PWM设备句柄 */

rt_uint32_t channel[4], period[4], pulse[4];

int pwm_init(void)
{
    for (int i=0; i<2; i++)
    {
        period[i]  = 1000000;  /* 周期为1ms,单位为纳秒ns */
        pulse[i]   =  400000;  /* PWM脉冲宽度值,单位为纳秒ns */
    }

    /* 初始化设备PWM4 */
    pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM4_DEV_NAME);
    if (pwm_dev == RT_NULL)
    {
        rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM4_DEV_NAME);
        return RT_ERROR;
    }
    rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period[0], pulse[0]);
    rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);

    /* 初始化设备PWM13 */
    pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM13_DEV_NAME);
    if (pwm_dev == RT_NULL)
    {
        rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM13_DEV_NAME);
        return RT_ERROR;
    }
    rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period[0], pulse[0]);
    rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);

    /* 初始化设备PWM14 */
    pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM14_DEV_NAME);
    if (pwm_dev == RT_NULL)
    {
        rt_kprintf("pwm sample run failed! can't find %s device!\n", PWM14_DEV_NAME);
        return RT_ERROR;
    }
    rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period[1], pulse[1]);
    rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);

    return 0;
}

// 第一个参数为命令,第二个参数为 PWM 设备名称,第 3 个参数为 PWM 通道,
// 第 4 个参数为周期(单位纳秒),第 5 个参数为脉冲宽度(单位纳秒)
static int  pwm_set(int argc, char *argv[])
{
    if(argc!=5)
    {
        rt_kprintf("Usage:    pwm_set <device name> <channel> <period> <pulse>\n");
        rt_kprintf("Example:  pwm_set pwm13 1 100000 50000\n");
        return RT_ERROR;
    }

    rt_uint32_t period, pulse;
    char pwmdevname[RT_NAME_MAX];

    rt_strncpy(pwmdevname, argv[1], RT_NAME_MAX);
    if((!strcmp(argv[1], "pwm4")) || (!strcmp(argv[1], "pwm13")) || (!strcmp(argv[1], "pwm14")))
    {
        period  = atoi(argv[3]);  /* PWM period, ns */
        pulse   = atoi(argv[4]);  /* PWM pulse,  ns */
    }
    else
    {
        rt_kprintf("pwm sample run failed! can't find %s device!\n", pwmdevname);
        return RT_ERROR;
    }

    pwm_dev = (struct rt_device_pwm *)rt_device_find(pwmdevname);
    if (pwm_dev == RT_NULL)
    {
        rt_kprintf("pwm sample run failed! can't find %s device!\n", pwmdevname);
        return RT_ERROR;
    }
    rt_pwm_set(pwm_dev, PWM_DEV_CHANNEL, period, pulse);
    rt_pwm_enable(pwm_dev, PWM_DEV_CHANNEL);

    rt_kprintf("pwm_set %s channel:%d period:%dns pulse:%dns\n", pwmdevname, PWM_DEV_CHANNEL, period, pulse);

    return 0;
}

int main(void)
{
    int count = 1;
    LOG_D("Hello RT-Thread! 2024.1.17");
    LOG_D("System CLock information");
    LOG_D("SYSCLK_Frequency = %d", HAL_RCC_GetSysClockFreq());
    LOG_D("HCLK_Frequency   = %d", HAL_RCC_GetHCLKFreq());
    LOG_D("PCLK1_Frequency  = %d", HAL_RCC_GetPCLK1Freq());
    LOG_D("PCLK2_Frequency  = %d", HAL_RCC_GetPCLK2Freq());
    LOG_D("SysTick->LOAD    = %d", SysTick->LOAD);
    LOG_D("Current tick     = %d", rt_tick_get());
    pwm_init();
    MX_TIM2_Init();
    MX_TIM5_Init();
	
    while (count++)
    {
        if(count%60 == 0) LOG_D("Hello RT-Thread! %d", rt_tick_get());
        if(count%20 == 0)
        {
            rt_kprintf("PWM_Duty=%d% ",(int)duty);
            rt_kprintf(" FCNT=%d RCNT=%d \r\n", PWM_FallingCount, PWM_RisingCount);
        }
        if(count%2 == 0)
        {
            rt_kprintf("ETRCNT=%d \r\n", __HAL_TIM_GET_COUNTER(&htim5));
        }
        rt_thread_mdelay(1000);
    }

    return RT_EOK;
}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pwm_set, set pwm4 period/pulse. Usage: pwm_set pwm4 1 10000 5000);

在工程中,还使能了TIM4、TIM13和TIM14为PWM输出,TIM2为PWM输入。操作参见《RT-Thread Studio学习(三)PWM》 和《RT-Thread Studio学习(十五)PWM测量》 。

将PWM输入引脚PA1和PWM输出引脚PD12短接,将PA1和PA0短接,运行结果如下:
在这里插入图片描述

用逻辑分析仪查看3个PWM的输出引脚PA6、PA7和PD12:
在这里插入图片描述

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

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

相关文章

使用pyechart创建折线图

import json from pyecharts.charts import Line from pyecharts import options# 首先使用文件打开数据 f_us open(Desktop/python/Project/数据可视化/美国.txt,r,encoding"UTF-8") f_rb open(Desktop/python/Project/数据可视化/日本.txt,r,encoding"UTF-8…

springboot106大学城水电管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的大学城水电管理系统 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 …

密码学学习笔记(二十四):TCP/IP协议栈

TCP/IP协议栈的基础结构包括应用层、传输层、网络层、数据链路层和物理层。 应用层 应用层位于TCP/IP协议栈的最顶层&#xff0c;是用户与网络通信的接口。这一层包括了各种高级应用协议&#xff0c;如HTTP&#xff08;用于网页浏览&#xff09;、FTP&#xff08;用于文件传输…

c# 自定义 滑块TrackBar

辛苦半天做出来的&#xff0c;如果觉得好用&#xff0c;记得点赞 效果图如下&#xff1a; 具体操作&#xff1a; 1 、添加代码&#xff08;代码在下面&#xff09;&#xff0c;重新生成下整个工程&#xff0c;在工具栏中就出现控件&#xff0c;将控件拖到窗体中 2、只需要调整…

【Qt5】QString的成员函数trimmed

2024年1月19日&#xff0c;周五下午 QString 的 trimmed 方法是用于移除字符串两端的空白字符&#xff08;空格、制表符、换行符等&#xff09;的方法。它返回一个新的字符串&#xff0c;该字符串是原始字符串去除两端空白后的结果。 下面是一个简单的示例&#xff1a; #incl…

瑞_Java开发手册_(六)工程结构

文章目录 工程结构的意义(一) 应用分层(二) 二方库依赖(三) 服务器 &#x1f64a;前言&#xff1a;本文章为瑞_系列专栏之《Java开发手册》的工程结构篇&#xff0c;主要介绍应用分层、二方库依赖、服务器。由于博主是从阿里的《Java开发手册》学习到Java的编程规约&#xff0c…

往docker中cloudbeaver的容器添加达梦数据库、impala数据库连接支持(cloudbeaver添加自定义数据连接)

cloudbeaver默认没有开放impala连接&#xff0c;更不会支持国产数据库了 docker安装运行cloudbeaver可以参考文章&#xff1a;docker安装运行CloudBeaver并设置默认语言为中文 本文跳过cloudbeaver镜像拉取&#xff0c;直接就开始实现自定义数据库连接功能 1、初始化cloudbe…

MLILY梦百合上榜“2023中国家居行业价值100公司”

2024年1月16日,由搜狐焦点家居联合搜狐财经、搜狐科技、搜狐时尚等主流频道主办的“2023中国家居行业价值100公司”榜单正式公布。MLILY梦百合作为头部睡眠科技品牌,经线上投票和专家评审,凭借强大的创新力、产品力、品牌力、服务力,从千家候选企业中脱颖而出,并最终荣获“2023…

TLP184(GR-TPL,SE 晶体管输出光电耦合器的特性与概述

TLP184(GR-TPL,SE 是一种交流输入型光电耦合器&#xff0c;由一个光电晶体管组成&#xff0c;该光电晶体管与两个砷化镓红外发射二极管光学耦合。 TLP184(GR-TPL,SE封装在非常小且薄的SO6封装中&#xff0c;具有高抗噪声性和高隔离电压。 由于TLP184(GR-TPL,SE比DIP封装更小&…

navigateTo失效-跳转不了页面解决办法!uniapp\vue

改了一个小时多的错误&#xff0c;跳转页面无论怎么样都跳转不了&#xff0c;有2个问题&#xff1a; 注意&#xff1a;uniapp的报错可以在console里检查&#xff01; 1.pages.json文件没有配置路径&#xff0c; 在pages:[ ]里面加 &#xff08;根据自己的路径进行修改 {&qu…

嵌入式操作教程:7-1 基于CMOS数字摄像头的灰度转换实验

一、实验目的 学习灰度转换的原理&#xff0c;掌握OV2640 摄像头和VPIF总线的工作原理&#xff0c;实现OV2640 摄像头采集图像并进行实时灰度转换显示在 LCD 上。 二、实验原理 OV2640摄像头 OV2640 是世界上第一个 1/4 英寸 2 百万像素视频传感器&#xff0c;同时是 OmniV…

SCSI/UFS储存架构/协议/电源管理/命令处理流程

UFS子系统架构 1.UFS协议 无论是ufs host controller部分还是ufs device部分&#xff0c;他们都将遵循统一的UFS规范 UFS Application Layer(UAP)应用层 1.UFS command set (UCS) UCS处理命令集&#xff0c;如读、写命令等&#xff0c;.使用的命令是简化的SCSI命令&#xff08;…

【01】mapbox js api加载arcgis切片服务

需求&#xff1a; 第三方的mapbox js api加载arcgis切片服务&#xff0c;同时叠加在天地图上&#xff0c;天地图坐标系web墨卡托。 效果图&#xff1a; 形如这种地址去加载http://zjq2022.gis.com:8080/demo/loadmapboxtdt.html 思路&#xff1a; 需要制作一个和天地图比例…

2023年度因子大盘点

基本信息: 指标说明: 2023年市场表现最佳 2023年市场单项最佳 2023年各分域最佳因子

【昇思技术公开课笔记-大模型】Bert理论知识

NLP中的预训练模型 语言模型演变经历的几个阶段 word2vec/Glove将离散的文本数据转换为固定长度的静态词向量&#xff0c;后根据下游任务训练不同的语言模型ELMo预训练模型将文本数据结合上下文信息&#xff0c;转换为动态词向量&#xff0c;后根据下游任务训练不同的语言模…

从数据到决策:项目管理和度量领域必备技能

0、引言 “效率”作为得物技术部的关键词之一&#xff0c;大家在研发效能、会议效率、协作效率、办公效率等方面一直进行着持续地探索。在实际落地的过程中&#xff0c;为了更好地评估应用效果&#xff0c;往往需要将定性描述转换为可量化的数据指标。这些数据指标可以帮助我们…

【大咖云集】2024年机械应用与机器视觉研究国际会议(ICMAMVR 2024)

2024年机械应用与机器视觉研究国际会议(ICMAMVR 2024) 2024 International Conference on Mechanical Applications and Machine Vision Research 数据库&#xff1a;EI,CPCI,CNKI,Google Scholar等检索 一、【会议简介】 2024年机械应用与机器视觉研究国际会议(ICMAMVR 2024)将…

C和指针课后答案

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 第八章课后答案 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参…

C语言:预处理详解

创作不易&#xff0c;来个三连呗&#xff01; 一、预定义符号 C语⾔设置了⼀些预定义符号&#xff0c;可以直接使⽤&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编…

python—01虚拟环境

文档结构 1、概念简介2、环境配置2.1、多版本解释器2.2、指令创建虚拟环境2.3、idea创建虚拟环境2.3.1、pycharm 1、概念简介 虚拟环境 在某些场景下&#xff0c;不同的项目需要基于不同版本的Python解释器来开发&#xff0c;或者不同的项目需要的第三方包或模块版本也不同。当…