初中生
最后登录1970-1-1
在线时间 小时
注册时间2017-1-19
|
设置通用定时器3进行4路PWM输出,高级定时器8通道1捕获任意一路PWM并且显示在串口上,捕获部分程序和火哥视频教程完全一样(除了GPIO端口不同),但在串口上显示的捕获值却随着高级定时器时基结构体周期的设置变化,而且测得的结果完全不合理!代码有点长,求大神帮看看,感激不尽
general_tim.h文件
#ifndef __GENERAL_TIM_H
#define __GENERAL_TIM_H
#include "stm32f4xx.h"
//通用定时器外设宏定义
#define GENERAL_TIM TIM3
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM3
#define GENERAL_TIM_Period 1999
#define GENERAL_TIM_Prescaler 899
// TIM3 输出比较通道1
#define GENERAL_TIM_CH1_GPIO_CLK RCC_AHB1Periph_GPIOC
#define GENERAL_TIM_CH1_PORT GPIOC
#define GENERAL_TIM_CH1_PIN GPIO_Pin_6
#define GENERAL_TIM_CH1_PINSOURCE GPIO_PinSource6
#define GENERAL_TIM_CH1_AF GPIO_AF_TIM3
// TIM3 输出比较通道2
#define GENERAL_TIM_CH2_GPIO_CLK RCC_AHB1Periph_GPIOC
#define GENERAL_TIM_CH2_PORT GPIOC
#define GENERAL_TIM_CH2_PIN GPIO_Pin_7
#define GENERAL_TIM_CH2_PINSOURCE GPIO_PinSource7
#define GENERAL_TIM_CH2_AF GPIO_AF_TIM3
// TIM3 输出比较通道3
#define GENERAL_TIM_CH3_GPIO_CLK RCC_AHB1Periph_GPIOC
#define GENERAL_TIM_CH3_PORT GPIOC
#define GENERAL_TIM_CH3_PIN GPIO_Pin_8
#define GENERAL_TIM_CH3_PINSOURCE GPIO_PinSource8
#define GENERAL_TIM_CH3_AF GPIO_AF_TIM3
// TIM3 输出比较通道4
#define GENERAL_TIM_CH4_GPIO_CLK RCC_AHB1Periph_GPIOC
#define GENERAL_TIM_CH4_PORT GPIOC
#define GENERAL_TIM_CH4_PIN GPIO_Pin_9
#define GENERAL_TIM_CH4_PINSOURCE GPIO_PinSource9
#define GENERAL_TIM_CH4_AF GPIO_AF_TIM3
void GTIMx_Init(void);
#endif
general_tim.c文件
#include "general_tim.h"
//通用定时器GPIO引脚配置
static void GTIMx_GPIO_Config(void)
{
//定义一个GPIO_InitTypeDef类型的结构体
GPIO_InitTypeDef GPIO_InitStructure;
//使能通用定时器四个通道的GPIO时钟
RCC_AHB1PeriphClockCmd (GENERAL_TIM_CH1_GPIO_CLK|GENERAL_TIM_CH2_GPIO_CLK|GENERAL_TIM_CH3_GPIO_CLK|GENERAL_TIM_CH4_GPIO_CLK,ENABLE);
//定时器复用引脚
GPIO_PinAFConfig(GENERAL_TIM_CH1_PORT,GENERAL_TIM_CH1_PINSOURCE,GENERAL_TIM_CH1_AF);
GPIO_PinAFConfig(GENERAL_TIM_CH2_PORT,GENERAL_TIM_CH2_PINSOURCE,GENERAL_TIM_CH2_AF);
GPIO_PinAFConfig(GENERAL_TIM_CH3_PORT,GENERAL_TIM_CH3_PINSOURCE,GENERAL_TIM_CH3_AF);
GPIO_PinAFConfig(GENERAL_TIM_CH4_PORT,GENERAL_TIM_CH4_PINSOURCE,GENERAL_TIM_CH4_AF);
//通用定时器PWM输出引脚配置
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH2_PIN;
GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH3_PIN;
GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH4_PIN;
GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStructure);
}
//通用定时器模式配置
static void GTIMx_Mode_Config(void)
{
// 开启定时器时钟,即内部时钟CK_INT=90M
RCC_APB1PeriphClockCmd(GENERAL_TIM_CLK,ENABLE);
//时基结构体声明及输出比较结构体声明
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//时基结构体初始化
// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断,这里配置频率为50Hz
TIM_TimeBaseStructure.TIM_Period=1999;
// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
TIM_TimeBaseStructure.TIM_Prescaler= 899;
// 时钟分频因子 ,配置死区时间时需要用到
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
// 计数器计数模式,设置为向上计数
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 重复计数器的值,没用到不用管
//TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
// 初始化定时器
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
//通用定时器输出比较结构体初始化
// 占空比配置
uint16_t CCR1_Val = 150;
uint16_t CCR2_Val = 200;
uint16_t CCR3_Val = 250;
uint16_t CCR4_Val = 300;
// 配置为PWM模式1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
// 输出使能
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
// 输出通道电平极性配置
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
// 输出比较通道 1
//TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 2
//TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 3
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 输出比较通道 4
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);
// 使能计数器
TIM_Cmd(GENERAL_TIM, ENABLE);
}
//通用定时器初始化函数
void GTIMx_Init(void)
{
GTIMx_GPIO_Config();
GTIMx_Mode_Config();
}
advance_tim.h文件
#ifndef __ADVANCE_TIM_H
#define __ADVANCE_TIM_H
#include "stm32f4xx.h"
/* 高级控制定时器PWM输入捕获 */
/* PWM输入捕获引脚 */
#define ADVANCE_ICPWM_PIN GPIO_Pin_5
#define ADVANCE_ICPWM_GPIO_PORT GPIOI
#define ADVANCE_ICPWM_GPIO_CLK RCC_AHB1Periph_GPIOI
#define ADVANCE_ICPWM_PINSOURCE GPIO_PinSource5
#define ADVANCE_ICPWM_AF GPIO_AF_TIM8
#define ADVANCE_IC1PWM_CHANNEL TIM_Channel_1
#define ADVANCE_IC2PWM_CHANNEL TIM_Channel_2
/* 高级控制定时器 */
#define ADVANCE_TIM TIM8
#define ADVANCE_TIM_CLK RCC_APB2Periph_TIM8
/* 捕获/比较中断 */
#define ADVANCE_TIM_IRQn TIM8_CC_IRQn
#define ADVANCE_TIM_IRQHandler TIM8_CC_IRQHandler
void ATIMx_Init(void);
#endif
advance_tim.c文件
#include "advance_tim.h"
//高级定时器GPIO配置函数
static void ATIMx_GPIO_Config(void)
{
//定义一个GPIO_InitTypeDef类型的结构体
GPIO_InitTypeDef GPIO_InitStructure;
//开启定时器相关的GPIO外设时钟
RCC_AHB1PeriphClockCmd (ADVANCE_ICPWM_GPIO_CLK, ENABLE);
//定时器复用引脚
GPIO_PinAFConfig(ADVANCE_ICPWM_GPIO_PORT,ADVANCE_ICPWM_PINSOURCE,ADVANCE_ICPWM_AF);
//高级定时器PWM输入捕获引脚配置
GPIO_InitStructure.GPIO_Pin = ADVANCE_ICPWM_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(ADVANCE_ICPWM_GPIO_PORT, &GPIO_InitStructure);
}
//定时器中断优先级配置函数
static void TIMx_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM_IRQn;
// 设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置子优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//高级定时器模式配置函数
static void ATIMx_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
// 开启TIMx_CLK,x[1,8]
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CLK, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0xFFFF-1;
// 高级控制定时器时钟源TIMxCLK = HCLK=180MHz
// 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=100KHz
TIM_TimeBaseStructure.TIM_Prescaler = 1800-1;
// 计数方式
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
// 初始化定时器TIMx, x[1,8]
TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
/* IC1捕获:上升沿触发 TI1FP1 */
TIM_ICInitStructure.TIM_Channel = ADVANCE_IC1PWM_CHANNEL;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(ADVANCE_TIM, &TIM_ICInitStructure);
/* IC2捕获:下降沿触发 TI1FP2
TIM_ICInitStructure.TIM_Channel = ADVANCE_IC2PWM_CHANNEL;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(ADVANCE_TIM, &TIM_ICInitStructure);
*/
/* 选择定时器输入触发: TI1FP1 */
TIM_SelectInputTrigger(ADVANCE_TIM, TIM_TS_TI1FP1);
/* 选择从模式: 复位模式 不知道有啥用处,但是必不可少*/
TIM_SelectSlaveMode(ADVANCE_TIM, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(ADVANCE_TIM,TIM_MasterSlaveMode_Enable);
/* 使能高级控制定时器 */
TIM_Cmd(ADVANCE_TIM, ENABLE);
/* 使能捕获/比较2中断请求 */
TIM_ITConfig(ADVANCE_TIM, TIM_IT_CC1, ENABLE);
}
//定时器配置函数
void ATIMx_Init(void)
{
ATIMx_GPIO_Config();
TIMx_NVIC_Configuration();
ATIMx_Mode_Config();
}
中断函数
void ADVANCE_TIM_IRQHandler (void)
{
/* 清除定时器捕获/比较1中断 */
TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1);
/* 获取输入捕获值 */
IC1Value = TIM_GetCapture1(ADVANCE_TIM)+1;
IC2Value = TIM_GetCapture2(ADVANCE_TIM)+1;
//printf("IC1Value = %d IC2Value = %d ",IC1Value,IC2Value);
if (IC2backup!= IC2Value)
{
//printf("IC2backup=%d\n",IC2backup);
printf("IC1Value = %d IC2Value = %d ",IC1Value,IC2Value);
IC2backup=IC2Value;
}
if (IC1Value != 0)
{
/* 占空比计算 */
DutyCycle = (float)(IC2Value * 100) / IC1Value;
/* 频率计算 */
Frequency = 180000000/1800/(float)IC1Value;
if(DutyCycle!=Dbackup)
{
printf("占空比:%0.2f%% 频率:%0.2fHz\n",DutyCycle,Frequency);
//printf("Fbackup=%0.2fHz\n",Fbackup);
Dbackup=DutyCycle;
}
}
else
{
DutyCycle = 0;
Frequency = 0;
}
}
串口显示结果
C1Value = 61162 IC2Value = 48930 占空比:80.00% 频率:1.64Hz
IC1Value = 61162 IC2Value = 7862 占空比:12.85% 频率:1.64Hz
IC1Value = 61162 IC2Value = 33208 占空比:54.30% 频率:1.64Hz
IC1Value = 61162 IC2Value = 56794 占空比:92.86% 频率:1.64Hz
IC1Value = 61162 IC2Value = 33208 占空比:54.30% 频率:1.64Hz
IC1Value = 61162 IC2Value = 7862 占空比:12.85% 频率:1.64Hz
IC1Value = 61162 IC2Value = 48930 占空比:80.00% 频率:1.64Hz
IC1Value = 61162 IC2Value = 41072 占空比:67.15% 频率:1.64Hz
IC1Value = 61162 IC2Value = 48930 占空比:80.00% 频率:1.64Hz
IC1Value = 61162 IC2Value = 7862 占空比:12.85% 频率:1.64Hz
IC1Value = 61162 IC2Value = 33208 占空比:54.30% 频率:1.64Hz
IC1Value = 61162 IC2Value = 56794 占空比:92.86% 频率:1.64Hz
IC1Value = 61162 IC2Value = 33208 占空比:54.30% 频率:1.64Hz
IC1Value = 61162 IC2Value = 7862 占空比:12.85% 频率:1.64Hz
|
|