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输入捕获功能
-
打开PWM驱动框架
在RT-Thread Setting
中借助图形化配置工具打开组件中的HWTIMER的驱动框架,如下图所示:
-
定义TIM相关的宏
将TIM5配置为PWM输入模式,在board.h
文件中使能宏定义:
#define BSP_USING_TIM
#ifdef BSP_USING_TIM
#define BSP_USING_TIM5
#endif
- 复制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_MspInit
和HAL_TIM_MspPostInit
复制到board.c
的末尾。
再次复制函数HAL_TIM_Base_MspInit
到board.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 */
- 定义
.\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:
相关文章:

RT-Thread Studio学习(十六)定时器计数
RT-Thread Studio学习(十六)定时器计数 一、简介二、新建RT-Thread项目并使用外部时钟三、启用PWM输入捕获功能四、测试 一、简介 本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下使用定时器对输入脉冲进行计数。 硬件及开发环境如下…...

【linux进程间通信(一)】匿名管道和命名管道
💓博主CSDN主页:杭电码农-NEO💓 ⏩专栏分类:Linux从入门到精通⏪ 🚚代码仓库:NEO的学习日记🚚 🌹关注我🫵带你学更多操作系统知识 🔝🔝 进程间通信 1. 前言2. 进程间…...
第11章 jQuery
学习目标 了解什么是jQuery,能够说出jQuery的特点 掌握jQuery的下载和引入,能够下载jQuery并且能够使用两种方式引入jQuery 掌握jQuery的简单使用,能够使用jQuery实现简单的页面效果 熟悉什么是jQuery对象,能够说出jQuery对象与DOM对象的区别 掌握利用选择器获取元素的方法…...

leetcode:1736. 替换隐藏数字得到的最晚时间(python3解法)
难度:简单 给你一个字符串 time ,格式为 hh:mm(小时:分钟),其中某几位数字被隐藏(用 ? 表示)。 有效的时间为 00:00 到 23:59 之间的所有时间,包括 00:00 和 23:59 。 …...

MySQL存储函数与存储过程习题
创建表并插入数据: 字段名 数据类型 主键 外键 非空 唯一 自增 id INT 是 否 是 是 否 name VARCHAR(50) 否 否 是 否 否 glass VARCHAR(50) 否 否 是 否 否 sch 表内容 id name glass 1 xiaommg glass 1 2 xiaojun glass 2 1、创建一个可以统计表格内记录…...

基于 Hologres+Flink 的曹操出行实时数仓建设
本文整理自曹操出行实时计算负责人林震基于 HologresFlink 的曹操出行实时数仓建设的分享,内容主要分为以下六部分: 曹操出行业务背景介绍曹操出行业务痛点分析HologresFlink 构建企业级实时数仓曹操出行实时数仓实践曹操出行业务成果分析未来展望 一、曹…...

【Docker】实战多阶段构建 Laravel 镜像
作者主页: 正函数的个人主页 文章收录专栏: Docker 欢迎大家点赞 👍 收藏 ⭐ 加关注哦! 本节适用于 PHP 开发者阅读。Laravel 基于 8.x 版本,各个版本的文件结构可能会有差异,请根据实际自行修改。 准备 新…...

【MATLAB源码-第118期】基于matlab的蜘蛛猴优化算法(SMO)无人机三维路径规划,输出做短路径图和适应度曲线。
操作环境: MATLAB 2022a 1、算法描述 蜘蛛猴优化算法(Spider Monkey Optimization, SMO)是一种灵感来源于蜘蛛猴觅食行为的群体智能优化算法。蜘蛛猴是一种生活在南美洲热带雨林中的灵长类动物,它们在寻找食物时展现出的社会行…...

【计算机组成与体系结构Ⅱ】Tomasulo 算法模拟和分析(实验)
实验5:Tomasulo 算法模拟和分析 一、实验目的 1:加深对指令级并行性及开发的理解。 2:加深对 Tomasulo 算法的理解。 3:掌握 Tomasulo 算法在指令流出、执行、写结果各阶段对浮点操作指令以及 load 和 store 指令进行了什么处…...

Nginx 简介
1、概念介绍 Nginx ("engine x") 是一个轻量级、高性能的 WEB 服务器软件和反向代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。其将源代码以类 BSD 许可证的形式发…...

C++入门学习(一)写一个helloworld
1、头文件 #include <iostream> using namespace std; 任何程序都需要这两句的,写上就好。 2、主文件 int main() {cout<<"Hello World!"<<endl;return 0; } 由于是int型数据,所以要返回一个值,即return0。…...
ChatGPT 股市知识问答
我 2024-01-17 14:16:38 股市交易的关键指标有哪些? ChatGPT 2024-01-17 14:16:38 股市交易中常用的关键指标有很多,以下是一些常见的指标: 股价指标:股价是衡量股票价格变化的重要指标,包括每股收益(EPS…...

uniapp多端评价页
如图所示:评价页 <template><view><!-- 顶部 --><view class"evaluate_head"><image class"headBg" src"/static/evaluate/head.png" mode""></image><view class"headZindex…...

行为树(Behavior Trees)
行为树(Behavior Trees)是一种在游戏开发中广泛使用的AI设计模式,主要用于描述AI的行为和决策过程,实现更加智能和自然的游戏AI。它由多个节点组成,每个节点代表一个行为或决策,按照特定的方式连接在一起&a…...
opensssl BIO方式https客户端
废话不多说,代码中使用了两种https客户端的实现方式。 #include <windows.h> #include <WinSock.h>#pragma comment(lib,"ws2_32.lib") #include "../include/openssl\ssl.h" #include "../include/openssl\err.h"#pragm…...
JavaScript之判断是否整数、取余、取整、进制、位或、ES6
MENU 方法一方式二方式三方式四方式五结束语 方法一 使用取余运算符判断,利用任何整数都会被1整除的原理,即余数是0的特点,通过这个规则来判断是否是整数。 let isInteger (val) > val % 1 0;// true isInteger(5); // false isInteger(…...

【打造你自己的Shell:编写定制化命令行体验】
本节重点: 学习进程创建,fork/vfork 学习到进程等待 学习到进程程序替换, 微型shell,重新认识shell运行原理 学习到进程终止,认识$? 一、进程创建 1.1.fork函数初识 在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程…...

PGSQL主键序列
PostgreSQL和 MySQL数据库还是有一定的区别。 下面了解一下 PGSQL的主键序列。 一、主键 1、系统自带主键序列 在 PostgreSQL 中,GENERATED BY DEFAULT 和 GENERATED ALWAYS 是用于定义自动生成的列(Generated Column)的选项。一般可作用…...

pg14.2迁移至KingbaseV8R6后部分表记录数为空
pg14.2迁移至KingbaseV8R6后部分表记录数为空 问题描述 kdts工具迁移详情里显示表数据已迁移成功,但是迁移后测试发现部份表记录数为空 分别查看源库和目标库表记录数 --源库 select count(*) from aaf_sys_param order by 1; 229条--目录库 select count(*) fr…...

【Spring 篇】深入解析SpringMVC的组件魅力
SpringMVC,这个名字在Java Web开发者的耳边仿佛是一首动听的旋律,携着轻盈的氛围,带给我们一种愉悦的编程体验。但是,当我们深入探寻这个框架时,它的魅力远不止表面的简单,它由许多组件构成,每个…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...