STM32 进阶 定时器3 通用定时器 案例2:测量PWM的频率/周期
需求分析
上一个案例我们输出了PWM波,这个案例我们使用输入捕获功能,来测试PWM波的频率/周期。
把测到的结果通过串口发送到电脑,检查测试的结果。
如何测量
1、输入捕获功能主要是:测量输入通道的上升沿和下降沿
2、让第一个上升沿触发,第二个上升沿卡个事件,可以测量到周期
3、然后通过周期反推频率
输入捕获包括三个部分:
共四路,每路都有自己的输入引脚
计数器部分
捕获寄存器部分
过程
通过之前产生的方波信号,然后再配置输入对这个方波信号进行测量,用杜邦线
连接两个引脚,tim4和tim5的引脚,昨天tim5的引脚产生PWM方波,用tim4定时器用于测量。
产生中断会触发中断函数(这个函数将CNT计时器清零),但是触发中断函数之前会产生一个捕获比较事件,这个事件是将CNT的值搬到捕获比较1寄存器中。
上升沿会触发中断,产生搬用事件,并将CNT清零,
然后下一个上升沿会再次产生中断,那么会产生搬用事件将CNT计数器搬到寄存器中,可以抓取这个值,就是这个周期的事件。
设计相关寄存器
CCMR1
CC2S:选择输入
IC1F:无滤波,可以抗干扰,一般在硬件就已经抗干扰啦,这里无滤波
CCIS: 输入有三种情况
PSC:预分频 三档2/4/8分频
CCER:
CC1P:上升沿还是下降沿
CC1E: 输入使能
CR2:
TI1S:采用TIMx_CH1的线路
DIER:捕获比较中断
CC1IE:允许中断
tim4.c
#include "tim4.h"
void TIM4_Init(){
//1.GPIO
//1.1放时钟
RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;
//1.2 PB6 引脚 配置输入模式 浮空输入
GPIOB->CRL &= ~ (GPIO_CRL_CNF6_1 | GPIO_CRL_MODE6);
GPIOB->CRL |= GPIO_CRL_CNF6_0;
//2.TIM4
//2.0 先放时钟
RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;
//2.1 控制器 (不管 全部保留默认设72MHz)
//2.2 时基单元
//2.2.1 分频 计数频率就是1M 数一个数的时间就是1us
TIM4->PSC = 72 - 1;
//2.2.2 尺子越长越好
TIM4->ARR = 65535;
//2.3 输入和输出通道
//2.3.1 通道输入还是输出
TIM4->CCMR1 |= TIM_CCMR1_CC1S_0;
TIM4->CCMR1 &= ~TIM_CCMR1_CC1S_1;
//2.3.2 配置TI1复用器,选择CH1引脚直接过来的信号(默认就是)
TIM4->CR2 &= ~TIM_CR2_TI1S;
//2.3.3 配置滤波器(默认就是)
TIM4->CCMR1 &= ~ TIM_CCMR1_IC1F;
//2.3.4 配置边沿检测器(默认就是)
TIM4->CCER &= ~TIM_CCER_CC1P;
//2.3.5 预分频器(默认就是)
TIM4->CCMR1 &= ~ TIM_CCMR1_IC1PSC;
//2.3.6 中断使能
TIM4->DIER |= TIM_DIER_CC1IE;
//3 有中断就需要配置NVIC
//3.1 优先级分组
NVIC_SetPriorityGrouping(3);
//3.2 设置本中断的优先级
NVIC_SetPriority(TIM4_IRQn,6);
//3.3 对于片上外设 NVIC有一个使能控制
NVIC_EnableIRQ(TIM4_IRQn);
}
void TIM4_Start(void){
// 开启通道使能
TIM4->CCER |= TIM_CCER_CC1E;
//开启计数器使能
TIM4->CR1 |= TIM_CR1_CEN;
}
void TIM4_Stop(void){
// 关闭通道使能
TIM4->CCER &= ~TIM_CCER_CC1E;
//关闭计数器使能
TIM4->CR1 &= ~TIM_CR1_CEN;
}
uint8_t raise_edge_num = 0;
uint16_t cnt = 0;
double TIM4_GetCycleMs(void){
return cnt/1000.0;
}
double TIM4_GetFreq(void){
return 1000000.0/cnt;
}
void TIM4_IRQHandler (void){
//片上外设都有标志位
//-1 判断什么原因进入中断
//0 清0 标志位
if(TIM4->SR & TIM_SR_CC1IF){
TIM4->SR &= ~TIM_SR_CC1IF;
//业务逻辑
//1 .让编号加1
raise_edge_num ++;
//2. 分开第一个上升沿和第二个上升沿的逻辑
if (raise_edge_num == 1)
{
//3 如果第一个上升沿到来 我直接从0开始计数
TIM4->CNT = 0;
}else if (raise_edge_num == 2)
{
//4.如果第二个上升沿到来
raise_edge_num = 0;
//5.抄数,把值记录下来
cnt = TIM4->CCR1;
}
}
}
tim4.h
#ifndef __TIM4_H__
#define __TIM4_H__
#include "stm32f10x.h"
void TIM4_Init();
void TIM4_Start(void);
void TIM4_Stop(void);
double TIM4_GetCycleMs(void);
double TIM4_GetFreq(void);
#endif /* __TIM4_H__ */
main.c
我们要设置占空比,因为我们是tim5产生的pwm方波,如果没有占空比,也就没有方波产生,也就产生不了上升沿触发不了中断。
#include "usart1.h"
#include "string.h"
#include <stdio.h>
#include "m24c02.h"
#include "i2c.h"
#include "led.h"
#include "systick.h"
#include "tim6.h"
#include "tim5.h"
#include "tim4.h"
typedef enum {
LIGHT,
DARK
}LED_DIRCT;
extern uint16_t cnt;
int main(void)
{
TIM5_Init();
TIM5_PWMStart();
TIM5_SetDuty(10);
Usart1_Init();
TIM4_Init();
TIM4_Start();
// LED_DIRCT direct = LIGHT;
while (1)
{
Delay_s(2);
printf ("当前的周期时%.2fms,频率是%.2fHz",TIM4_GetCycleMs(),TIM4_GetFreq());
}
}
HAL库
前面有两个__:是宏定义,
原文地址:https://blog.csdn.net/qq_64219867/article/details/144247972
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!