发布时间:2022-09-20 17:00
前面我们讲了用输入捕获测量了信号的脉宽,这一节我们讲输入捕获的一个特例—PWM输入。
普通的输入捕获可以使用定时器的四个通道,一路捕获占用一个捕获寄存器,而PWM输入则只能使用两个通道,即通道1和通道2,且一路PWM输入要占用两个捕获寄存器,一个用于捕获周期,一个用于捕获占空比。
在本实验中,我们用通用定时器产生的一路PWM信号,然后用高级定时器的通道1和通道2来捕获。
实验中用到两个引脚,一个是通用定时器TIM3的通道1,即PA6,用于输出PWM信号,另一个是高级定时器TIM1的通道1,即PA8,用来PWM输入捕获,实验中,用一根杜邦线短接PA6和PA8即可,同时可用示波器监控PA6的波形,看看捕获的数据是否正确。
#include "./advancedtime/bsp_advancedtime.h"
static void AdvancedTime_NVIC_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure = {0};
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = AdvancedTimeX_IRQn;//定时器1的捕获中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void AdvancedTime_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
//开启GPIO的时钟
AdvancedTimeX_CH1_RCC_APB_CLKCMD(AdvancedTimeX_CH1_RCC_CLK_Periph,ENABLE);
GPIO_InitStructure.GPIO_Pin = AdvancedTimeX_CH1_RCC_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(AdvancedTimeX_CH1_RCC_GPIO_PORT,&GPIO_InitStructure);
}
static void AdvancedTime_Mode_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};
TIM_ICInitTypeDef TIM_ICInitStructure = {0};
//开启定时器时钟
AdvancedTimeX_RCC_APB_CLKCMD(AdvancedTimeX_RCC_CLK_Periph,ENABLE);
//时基配置
TIM_TimeBaseInitStructure.TIM_Period = AdvancedTimeX_Period;
TIM_TimeBaseInitStructure.TIM_Prescaler = AdvancedTimeX_PSC;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(AdvancedTimeX,&TIM_TimeBaseInitStructure);
//输入捕获配置
TIM_ICInitStructure.TIM_Channel = AdvancedTimeX_Channel;
TIM_ICInitStructure.TIM_ICFilter = 0;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_PWMIConfig(AdvancedTimeX,&TIM_ICInitStructure);
//配置输入触发信号
TIM_SelectInputTrigger(AdvancedTimeX,TIM_TS_TI1FP1);
//选择从模式:复位模式.PWM输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器CNT会被复位
TIM_SelectSlaveMode(AdvancedTimeX, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(AdvancedTimeX,TIM_MasterSlaveMode_Enable);
//清除中断标志位
TIM_ClearITPendingBit(AdvancedTimeX,TIM_IT_CC1);
//使能捕获中断,这个中断针对的是主捕获通道(测量周期这个)
TIM_ITConfig(AdvancedTimeX,TIM_IT_CC1,ENABLE);
//使能高级定时器,计数器开始计数
TIM_Cmd(AdvancedTimeX,ENABLE);
}
void AdvancedTime_Init(void)
{
AdvancedTime_NVIC_Init();
AdvancedTime_GPIO_Init();
AdvancedTime_Mode_Init();
}
#ifndef __BSP_ADVANCEDTIME_H
#define __BSP_ADVANCEDTIME_H
#include "stm32f10x.h"
#define AdvancedTimeX TIM1
#define AdvancedTimeX_RCC_APB_CLKCMD RCC_APB2PeriphClockCmd
#define AdvancedTimeX_RCC_CLK_Periph RCC_APB2Periph_TIM1
#define AdvancedTimeX_CH1_RCC_APB_CLKCMD RCC_APB2PeriphClockCmd
#define AdvancedTimeX_CH1_RCC_CLK_Periph RCC_APB2Periph_GPIOA
#define AdvancedTimeX_CH1_RCC_GPIO_PORT GPIOA
#define AdvancedTimeX_CH1_RCC_GPIO_PIN GPIO_Pin_8
#define AdvancedTimeX_IRQn TIM1_CC_IRQn
#define AdvancedTimeX_IRQHandler TIM1_CC_IRQHandler
#define AdvancedTimeX_Period (1000-1)
#define AdvancedTimeX_PSC (72-1)
#define AdvancedTimeX_Channel TIM_Channel_1
extern void AdvancedTime_Init(void);
#endif
#include "./generaltime/bsp_generaltime.h"
//定时器的GPIO配置
static void GeneralTime_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
//开启时钟
GeneralTimX_CH1_RCC_CLKCMD(GeneralTimeX_CH1_RCC_CLK_Periph,ENABLE);
GeneralTimX_CH2_RCC_CLKCMD(GeneralTimeX_CH2_RCC_CLK_Periph,ENABLE);
GeneralTimX_CH3_RCC_CLKCMD(GeneralTimeX_CH3_RCC_CLK_Periph,ENABLE);
GeneralTimX_CH4_RCC_CLKCMD(GeneralTimeX_CH4_RCC_CLK_Periph,ENABLE);
//GPIO配置
GPIO_InitStructure.GPIO_Pin = GeneralTimX_CH1_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GeneralTimX_CH1_GPIO_PORT,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GeneralTimX_CH2_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GeneralTimX_CH2_GPIO_PORT,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GeneralTimX_CH3_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GeneralTimX_CH3_GPIO_PORT,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GeneralTimX_CH4_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GeneralTimX_CH4_GPIO_PORT,&GPIO_InitStructure);
}
//定时器的Mode配置
static void GeneralTime_Mode_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};
TIM_OCInitTypeDef TIM_OCInitStructure = {0};
//开启定时器时钟
GeneralTimeX_RCC_CLKCMD(GeneralTimeX_RCC_CLK_Periph,ENABLE);
//时基配置
TIM_TimeBaseInitStructure.TIM_Period = GeneralTimeX_Period;
TIM_TimeBaseInitStructure.TIM_Prescaler = GeneralTimeX_PSC;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(GeneralTimeX,&TIM_TimeBaseInitStructure);
//输出比较配置
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_Pulse = GeneralTimeX_CCR1;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OC1Init(GeneralTimeX,&TIM_OCInitStructure);
TIM_OC1PreloadConfig(GeneralTimeX,TIM_OCPreload_Enable);
//输入捕获通道2
TIM_OCInitStructure.TIM_Pulse = GeneralTimeX_CCR2;
TIM_OC2Init(GeneralTimeX,&TIM_OCInitStructure);
TIM_OC2PreloadConfig(GeneralTimeX,TIM_OCPreload_Enable);
//输入捕获通道3
TIM_OCInitStructure.TIM_Pulse = GeneralTimeX_CCR3;
TIM_OC2Init(GeneralTimeX,&TIM_OCInitStructure);
TIM_OC3PreloadConfig(GeneralTimeX,TIM_OCPreload_Enable);
//输入捕获通道4
TIM_OCInitStructure.TIM_Pulse = GeneralTimeX_CCR4;
TIM_OC2Init(GeneralTimeX,&TIM_OCInitStructure);
TIM_OC4PreloadConfig(GeneralTimeX,TIM_OCPreload_Enable);
//使能定时器
TIM_Cmd(GeneralTimeX,ENABLE);
}
void GeneralTime_Init(void)
{
GeneralTime_GPIO_Init();
GeneralTime_Mode_Init();
}
#ifndef __BSP_GENERALTIME_H
#define __BSP_GENERALTIME_H
#include "stm32f10x.h"
#define GeneralTimeX TIM3
#define GeneralTimeX_RCC_CLKCMD RCC_APB1PeriphClockCmd
#define GeneralTimeX_RCC_CLK_Periph RCC_APB1Periph_TIM3
#define GeneralTimeX_Period (10-1)
#define GeneralTimeX_PSC (72-1)
#define GeneralTimeX_CCR1 5
#define GeneralTimeX_CCR2 4
#define GeneralTimeX_CCR3 3
#define GeneralTimeX_CCR4 2
#define GeneralTimX_CH1_RCC_CLKCMD RCC_APB2PeriphClockCmd
#define GeneralTimeX_CH1_RCC_CLK_Periph RCC_APB2Periph_GPIOA
#define GeneralTimX_CH1_GPIO_PORT GPIOA
#define GeneralTimX_CH1_GPIO_PIN GPIO_Pin_6
#define GeneralTimX_CH2_RCC_CLKCMD RCC_APB2PeriphClockCmd
#define GeneralTimeX_CH2_RCC_CLK_Periph RCC_APB2Periph_GPIOA
#define GeneralTimX_CH2_GPIO_PORT GPIOA
#define GeneralTimX_CH2_GPIO_PIN GPIO_Pin_7
#define GeneralTimX_CH3_RCC_CLKCMD RCC_APB2PeriphClockCmd
#define GeneralTimeX_CH3_RCC_CLK_Periph RCC_APB2Periph_GPIOB
#define GeneralTimX_CH3_GPIO_PORT GPIOB
#define GeneralTimX_CH3_GPIO_PIN GPIO_Pin_0
#define GeneralTimX_CH4_RCC_CLKCMD RCC_APB2PeriphClockCmd
#define GeneralTimeX_CH4_RCC_CLK_Periph RCC_APB2Periph_GPIOB
#define GeneralTimX_CH4_GPIO_PORT GPIOB
#define GeneralTimX_CH4_GPIO_PIN GPIO_Pin_1
extern void GeneralTime_Init(void);
#endif
__IO uint16_t IC2Value = 0;
__IO uint16_t IC1Value = 0;
__IO float DutyCycle = 0;
__IO float Frequency = 0;
void SysTick_Handler(void)
{
}
void AdvancedTimeX_IRQHandler(void)
{
/* 清除中断标志位 */
TIM_ClearITPendingBit(AdvancedTimeX, TIM_IT_CC1);
//获取输入捕获值
IC1Value = TIM_GetCapture1(AdvancedTimeX);
IC2Value = TIM_GetCapture2(AdvancedTimeX);
// 注意:捕获寄存器CCR1和CCR2的值在计算占空比和频率的时候必须加1
if (IC1Value != 0)
{
/* 占空比计算 */
DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);
/* 频率计算 */
Frequency = (72000000/(AdvancedTimeX_PSC+1))/(float)(IC1Value+1);
printf("占空比:%0.2f%% 频率:%0.2fHz\n",DutyCycle,Frequency);
}
else
{
DutyCycle = 0;
Frequency = 0;
}
}
#include "stm32f10x.h"
#include "bsp_led.h"
#include "./generaltime/bsp_generaltime.h"
#include "./usart/bsp_usart.h"
#include "./advancedtime/bsp_advancedtime.h"
int main(void)
{
GeneralTime_Init();
USART_Config();
AdvancedTime_Init();
while (1)
{
}
}
学有所成,以图强国!
2021年斯坦福AI指数报告重磅出炉!中国AI期刊影响力首超美国,视频处理是新风口...
邀请函|7月10日,九章云极DataCanvas邀您相约世界人工智能大会
苹果a10处理器_苹果“芯”基建简史:自己掌握不了核心技术 乔布斯也得干着急...
springBoot学习(三)springBoot事件监听和部分注解的运用
[ROC-RK3568-PC] 手把手教你打包能使用Etcher或dd命令烧写的Ubuntu系统固件
在linux开发板上编译程序的代码,建立交叉编译环境和在开发板上实现第一个嵌入式Linux应用程序...
小米回应“被意大利机构罚款2176万元”;Win 12要来?曝微软调整Windows迭代节奏;Vite 3.0 发布|极客头条