当前位置: 首页 > backend >正文

【嵌入式———通用定时器基本操作——实验需求2:案列:测量PWM的频率/周期】

通用定时器输入捕获

需求:把测到的结果通过串口发送到电脑,检查测试结果。

在溢出之前,两次上升/下降沿记录时间。
在这里插入图片描述345部分
滤波器:用来滤掉一些毛刺信息,信号质量好可以不滤波
边沿检测器:确定要捕获的是上升沿还是下降沿,CCXP(输入极性和输出极性是不一样的)
TI1经过滤波和边沿得到信号TI1FP1/TI1FP2(可以多路选择),最终得到IC1信号,也就是直通
通道1和通道2,通道3和通道4可以交叉映射。
信号从预分频器出来,信号为IC1PS
1.会产生一个捕获比较事件(这里主要是捕获)
2.将到来的信号,将当前计数器的值保存下来。立即把计数器寄存器的值存到捕获寄存器中,在下次捕获事件产生之前,捕获寄存器的值不会发生变化。
3…如果开启了中断也会产生捕获比较中断

实验假设:计数器72分频,则计数器时钟频率为1MHZ,计数器累加一次时间为1us,自动重装载值设置为65535,假设测量的信号周期小于65535us即频率大于16Hz

如果测量频率超过1MHz,超过计数器的时钟频率,第二个上升沿到了之后,计数器还没有完成一次累加,则无法测量,可以考虑测试第一个上升沿和第N个上升沿的间隔时间,最后除以N即可。
如果测量的频率太低,也就是测量波第二次上升沿还没到来,计数器就已经溢出了,那么可以计算溢出的次数,然后来计算测量波的频率。

使用TIM5通道二的输出方波,直接,硬连接TIM4的通道1
TIM5_CH2——PA1 TIM4_CH1——PB6

CCMR_IC1F,用来配置滤波(此实验不滤波)
CCER_CC1P(0,上升沿,1,下降沿)
CCER_CCIE(使能CH1通道捕获使能,0,关闭,1,开启)
TIM_DIER_CC1IE(1,允许捕获比较1中断)
IC1PSC,预分频(00不作分频)
CC1S配置:
00:CC1通道呗配置为输出
01:CC1通道被配置为输入,IC1映射载TI1上,也就是直通
10:CC1通道被配置为输入,IC1映射载TI2上,也就是交叉映射
11:CC1通道被配置为输入,IC1映射载TRC上,

在tim4.h中编写

#ifndef __TIM4_H
#define __TIM4_H#include "stm32f10x.h"void TIM4_Init(void);// 将定时器的开关包装成函数
void TIM4_Start(void);
void TIM4_Stop(void);// 获取输入信号周期的函数
double TIM4_GetPWMCycle(void);
double TIM4_GetPWMFreq(void);#endif

在tim4.c中编写

/** @Author: wushengran* @Date: 2024-06-04 13:58:28* @Description: * * Copyright (c) 2024 by atguigu, All Rights Reserved. */
#include "tim4.h"void TIM4_Init(void)
{// 1. 开启时钟RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;// 2. GPIO工作模式,PB6:浮空输入 CNF-01,MODE-00GPIOB->CRL &= ~GPIO_CRL_MODE6;GPIOB->CRL &= ~GPIO_CRL_CNF6_1;GPIOB->CRL |= GPIO_CRL_CNF6_0;// 定时器配置// 3. 时基部分// 3.1 预分频值 71,得到1MHz/s,1usTIM4->PSC = 71;// 3.2 重装载值,65535,尽量在信号一个周期内不要产生溢出TIM4->ARR = 65535;// 3.3 计数方向TIM4->CR1 &= ~TIM_CR1_DIR;// 4. 输入通道部分// 4.1 TI1的输入选择,0TIM4->CR2 &= ~TIM_CR2_TI1S;// 4.2 输入滤波器TIM4->CCMR1 &= ~TIM_CCMR1_IC1F;// 4.3 配置极性:上升沿触发TIM4->CCER &= ~TIM_CCER_CC1P;// 4.4 选择通道1的输入映射为 TI1:CC1S - 01TIM4->CCMR1 &= ~TIM_CCMR1_CC1S_1;TIM4->CCMR1 |= TIM_CCMR1_CC1S_0;// 4.5 预分频器TIM4->CCMR1 &= ~TIM_CCMR1_IC1PSC;// 4.6 通道1输入捕获使能TIM4->CCER |= TIM_CCER_CC1E;// 4.7 开启捕获中断使能TIM4->DIER |= TIM_DIER_CC1IE;// 5. NVIC配置NVIC_SetPriorityGrouping(3);NVIC_SetPriority(TIM4_IRQn, 3);NVIC_EnableIRQ(TIM4_IRQn);
}// 将定时器的开关包装成函数
void TIM4_Start(void)
{TIM4->CR1 |= TIM_CR1_CEN;
}void TIM4_Stop(void)
{TIM4->CR1 &= ~TIM_CR1_CEN;
}// // 定义全局变量
// uint16_t cycle = 0;     // 保存信号的周期
// uint8_t count = 0;      // 保存当前上升沿到来的次数// // 在中断服务程序中,判断第几次上升沿到来,执行相应的处理
// void TIM4_IRQHandler(void)
// {
//     // 根据标志位,判断是否是CH1产生了捕获中断
//     if (TIM4->SR & TIM_SR_CC1IF)
//     {
//         // 清除中断标志位
//         TIM4->SR &= ~TIM_SR_CC1IF;//         // 上升沿个数加 1
//         count ++;//         // 判断是第几次上升沿
//         if (count == 1)
//         {
//             // 第一个上升沿到来,清零计数器
//             TIM4->CNT = 0;
//         }
//         else if (count == 2)
//         {
//             // 第二个上升沿到来,就读取CCR中的值,交给cycle
//             cycle = TIM4->CCR1;//             // 清零count,重新计数
//             count = 0;
//         }
//     }// }// // cycle单位为us,返回周期单位为ms
// double TIM4_GetPWMCycle(void)
// {
//     return cycle / 1000.0;
// }// double TIM4_GetPWMFreq(void)
// {
//     return 1000000.0 / cycle;
// }void TIM4_IRQHandler(void)
{//判断中断标志位if (TIM4->SR & TIM_SR_CC1IF){// 清除中断标志位TIM4->SR &= ~TIM_SR_CC1IF;// 直接清零计数器TIM4->CNT = 0;}}// cycle单位为us,返回周期单位为ms
double TIM4_GetPWMCycle(void)
{return TIM4->CCR1 / 1000.0;
}double TIM4_GetPWMFreq(void)
{return 1000000.0 / TIM4->CCR1;
}

在main.c中编写

/** @Author: wushengran* @Date: 2024-05-23 15:14:48* @Description:** Copyright (c) 2024 by atguigu, All Rights Reserved.*/
#include "usart.h"
#include "tim5.h"
#include "tim4.h"
#include "delay.h"int main(void)
{// 初始化USART_Init();TIM4_Init();TIM5_Init();printf("Hello, world!\n");// 开启定时器TIM5_Start();TIM4_Start();while (1){printf("T = %.2f ms, f = %.2f Hz\n", TIM4_GetPWMCycle(), TIM4_GetPWMFreq());Delay_ms(1000);}
}
http://www.xdnf.cn/news/3380.html

相关文章:

  • 用手机相册教我数组概念——照片分类术[特殊字符][特殊字符]
  • 构建现代分布式云架构的三大支柱:服务化、Service Mesh 与 Serverless
  • 第十一届蓝桥杯 2020 C/C++组 门牌制作
  • vue 常见ui库对比(element、ant、antV等)
  • 兰亭妙微:数据驱动的 B 端设计:如何用 UI 提升企业级产品体验?
  • 【Qt】网络
  • ZYNQB笔记(十六):AXI DMA 环路测试
  • FreeSWITCH 发送 sip message 的 lua 程序
  • 深挖Java基础之:变量与类型
  • 总结C++中的STL
  • 分布式事务,事务失效,TC事务协调者
  • 图数据库榜单网站
  • 算法每日一题 | 入门-顺序结构-字母转换
  • X²+1素数问题
  • DirectX12(D3D12)基础教程七 深度模板视图\剔除\谓词
  • 【数据结构与算法】跳表实现详解
  • Windows结合WSL之ext4.vhdx不断增大问题
  • 第九节:文件操作
  • C++漫游指南——字符串篇与内存分配篇
  • ganesha-DBUS
  • 人形机器人的 “灵动密码”:动作捕捉与 AI 如何为其注入活力
  • BOSS的收入 - 华为OD机试(A卷,Java题解)
  • React-Native Android 多行被截断
  • Ubuntu 22.04 的 ROS 2 和 Carla 设置指南(其一)
  • Multicore-TSNE
  • 如何用GPU Instancing来优化树木草石重复模型
  • Kubernetes 配置中的 Selector 详解
  • GPU集群搭建步骤
  • 基础术语说明
  • 前端项目问题:TypeError: Failed to fetch dynamically imported module