上一篇有讲到输入捕获测量频率的代码,这篇的代码只需要把输入捕获的部分进行升级,设置成两个通道捕获同一个引脚的功能,这样子就同时显示一个通道的频率和占空比了。
更改捕获单元的思路:
(1)把通道初始化部分的代码复制一份,通道1还是直连输入和上升沿触发;通道2配置为交叉输入,下降沿触发。
(2)利用上一个文章讲到的TIM_PWMIConfig函数配置。
下面我们开始配置。
配置流程
1.RCC开启时钟(打开GPIO和TIM的时钟打开)
(1)void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
(2)void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
根据外设挂载的总线选择使用的函数。
2.GPIO初始化,将GPIO配置为输入模式(一般选择上拉输入或浮空输入)
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
作用:配置GPIO初始化
3.配置时基单元(使CNT在内部时钟的驱动下自增运行)
这一部分前面文章有写,不懂的可以参考一下上一篇的内容,此处不多赘述了。
原文链接:https://blog.csdn.net/m0_74246768/article/details/139048136
4.配置输入捕获单元(包括滤波器、极性、分频器等参数)
(1)void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
作用:用结构体配置输入捕获单元的函数
TIMx:选择哪个定时器
TIM_ICInitStruct:包含各个配置的结构体
补充:输入捕获和输出比较都有四个通道,前面文章有写到输出比较的四个通道的库函数,有4个。而输入捕获只有一个函数,是4个通道共用一个函数,在结构体内会额外有个参数去选择配置哪个通道
(2)void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
和上一个函数一样都是初始化输入捕获单元的,上一个函数只能配置一个通道,这个函数可配置两个通道。使用这个函数,只需要传入一个通道的参数,这个函数会自动把剩下的一个通道初始化成相反的配置。
注意:TIM_PWMIConfig函数只支持通道1和通道2的配置,不能配置通道3和通道4.
5.选择从模式的触发源(触发源选择为TI1FP1,调用一个库函数后直接给一个参数就行了)
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
作用:选择输入触发源TRGI。
6.选择触发之后执行的操作(执行Reset操作,直接调用库函数即可)
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
作用:选择从模式。
7.调用TIM_Cmd函数定时器。
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
作用:启动定时器。
配置好后,当我们需要读取最新一个周期的频率时,直接读取CCR寄存器,按照fc/N(测周法)计算一下即可。
获取频率
获取输入频率
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);
作用:分别读取四个通道的CCR。和TIM_SetCompare函数作用是一样的,都是读取CCR寄存器。输入比较模式下,CCR是只写,用TIM_SetCompare写入;输入捕获模式下,CCR只读,要用TIM_GetCapture读出。
获取占空比
高电平的计数值存在CCR2里,整个周期的计数值存在CCR1里。用CCR2/CCR1就能得到占空比。
代码显示
IC.c
#include "stm32f10x.h" // Device header
void IC_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
TIM_Cmd(TIM3, ENABLE);
}
uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}
uint32_t IC_GetDuty(void)
{
return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
//*100可以直接显示百分比的值,+1是因为实测发现误差相差1,通过+1可以解决这个误差
}
IC.h
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);
uint32_t IC_GetDuty(void);
#endif
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
int main(void)
{
OLED_Init();
PWM_Init();
IC_Init();
OLED_ShowString(1, 1, "Freq:00000Hz");
OLED_ShowString(2, 1, "Duty:00%");
PWM_SetPrescaler(720 - 1); //Freq = 72M / (PSC + 1) / 100
PWM_SetCompare1(50); //Duty = CCR / 100
while (1)
{
OLED_ShowNum(1, 6, IC_GetFreq(), 5);
OLED_ShowNum(2, 6, IC_GetDuty(), 2);
}
}
PWM模块与上一节相同,需要的同学可以在前面的文章里面看一下。
原文链接:https://blog.csdn.net/m0_74246768/article/details/139050032
补充:
测频率的范围:
下限:目前代码中给到的预分频器是72-1,所以标准频率是1MHz,那计数器最大只能计到65535,所测到的最低频率是1M/65535,大概是15Hz,信号频率再低就会导致计数器溢出。可通过加大预分频器的值,就可使标准频率降低,所支持的最低频率也就可以更低。
上限:随着待测频率增大,误差也会增大。如果频率超过1MHz,信号频率高于标准频率,误差会很大。(没有实际固定的上限,最大频率根据你对误差的要求决定),提高频率上限可通过降低PSC的值以提高标准频率,就可以提高上限。更高的频率使用测频法(测频法适合高频)