资深版主
 
- 积分
- 12012
- 金钱
- 12012
- 注册时间
- 2013-9-10
- 在线时间
- 427 小时
|
本帖最后由 八度空间 于 2016-5-1 01:16 编辑
最近用到定时器捕获波形频率,参考了标准库自带的例程,貌像不怎么准,有时候还很离谱,于是自己对照手册弄了一个,有不对的还请高手指点
PWM波发生由STM32F030芯片输出(PWM占空比变化输出),STM32F103进行采集。
函数捕获的原理:
1、CC1是从波形的上升沿开始捕获,当下一个上升沿来临时,所计数的就是一个波形周期的时间
2、CC2是从波形的下降沿开始捕获,当下一个下降沿来临时,所计数的就是高电平期间的时间,计算占空比用到
函数原型
[mw_shl_code=applescript,true]/**
*****************************************************************************
* PWM输入捕获
*
* (C) Copyright 2000-2020, ***
* All Rights Reserved
*****************************************************************************
*
* @File : pwm_capture.c
* @By : 陈桂东
* @Version : V1.0
* @Date : 2016 / 04 / 30
*
*****************************************************************************
*
* Update
*
* @Version : V1.*
* @By : ***
* @Date : 20** / ** / **
* @Brief : ***
*
*****************************************************************************
**/
#include "pwm_capture.h"
/******************************************************************************
定义变量
******************************************************************************/
uint16_t IC1Value = 0; //捕获值存放,可用于计算频率,占空比等
uint16_t IC2Value = 0;
/**
*****************************************************************************
* @Name : 计算捕获PWM频率、占空比
*
* @Brief : none
*
* @Input : TIMx_CLK: 定时器所在总线频率,单位Hz
*
* @Output : *Freq: 捕获的PWM频率
* *Duty: 捕获的PWM占空比
*
* @Return : none
*****************************************************************************
**/
void PWM_CaptureGetFrequency_DutyCycle(uint32_t TIMx_CLK/* 单位Hz */, uint32_t * Freq/* 单位Hz */, uint8_t * Duty)
{
uint32_t tmp = 0;
//
//得到捕获计数周期频率
//
tmp = TIMx_CLK / PWM_Capture_Prescaler; //根据分频来计算,捕获的PWM频率由这个来决定
*Freq = tmp / IC1Value; //得到频率
*Duty = (IC2Value * 100) / IC1Value; //占空比 = (IC2Value / IC1Value) * 100;
}
/**
*****************************************************************************
* @Name : PWM输入捕获初始化
*
* @Brief : none
*
* @Input : none
*
* @Output : none
*
* @Return : none
*****************************************************************************
**/
void PWM_CaptureInit(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
RCC->APB2ENR|=1<<2; //打开GPIOA时钟
RCC->APB2ENR|=1<<0; //打开AFIO时钟
RCC->APB1ENR|=1<<0; //打开TIM2时钟
//
//重映射
//
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE); //TIM2部分重映射
//
//初始化IO PA.15 --> TIM2-CH1-ETR
//
GPIOA->CRH &= 0x0FFFFFFF; //清除配置
GPIOA->CRH |= 0x40000000; //浮空输入
GPIOA->ODR |= 1<<15; //上拉
//
//配置定时器分频,计数周期
//
TIM2->ARR = PWM_Capture_Period - 1; //计数器自动重装值
TIM2-> SC = PWM_Capture_Prescaler - 1; //预分频器
//
//从模式控制寄存器
//
TIM2->SMCR |= 1<<7; //触发输入(TRGI)
TIM2->SMCR |= 5<<4; //滤波后的定时器输入1(TI1FP1)
TIM2->SMCR |= 4<<0; //复位模式 – 选中的触发输入(TRGI)的上升沿重新初始化计数器,并且产生一个更新寄存器的信号
//
//初始化捕获寄存器参数 CC1
//
TIM2->CCMR1 |= 1<<0; //CC1通道被配置为输入,IC1映射在TI1上
TIM2->CCMR1 |= 3<<4; //采样频率f SAMPLING =f CK_INT ,N=8
TIM2->CCMR1 |= 0<<2; //无预分频器,捕获输入口上检测到的每一个边沿都触发一次捕获
TIM2->CCER |= 0<<1; //不反相:捕获发生在IC1的上升沿;当用作外部触发器时,IC1不反相
TIM2->CCER |= 1<<0; //捕获使能
//
//CC2
//
TIM2->CCMR1 |= 2<<8; //CC2通道被配置为输入,IC2映射在TI1上
TIM2->CCER |= 1<<5; //CC2P = 1. 反相:捕获发生在IC2的下降沿;当用作外部触发器时,IC2反相
TIM2->CCER |= 1<<4; //捕获使能
//
//中断配置
//
TIM2->DIER |= 1<<1; //允许捕获/比较1中断
//
//使能定时器
//
TIM2->CR1 |= 1<<0;
//
//初始化中断优先级
//
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**
*****************************************************************************
* @Name : 中断服务程序
*
* @Brief : none
*
* @Input : none
*
* @Output : none
*
* @Return : none
*****************************************************************************
**/
void TIM2_IRQHandler(void)
{
IC1Value = TIM2->CCR1; //读取上一次输入捕获1事件(IC1)传输的计数器值CCR1,清CC1IF标志位
IC2Value = TIM2->CCR2; //读取上一次输入捕获2事件(IC2)传输的计数器值CCR2,清CC2IF标志位
TIM2->SR &= ~(1<<1); //清除中断标志位
}
[/mw_shl_code]
头文件内容
[mw_shl_code=applescript,true]/**
*****************************************************************************
* PWM输入捕获
*
* (C) Copyright 2000-2020, ***
* All Rights Reserved
*****************************************************************************
*
* @File : pwm_capture.h
* @By : 陈桂东
* @Version : V1.0
* @Date : 2016 / 04 / 30
*
*****************************************************************************
*
* Update
*
* @Version : V1.*
* @By : ***
* @Date : 20** / ** / **
* @Brief : ***
*
*****************************************************************************
**/
#ifndef _pwm_capture_h
#define _pwm_capture_h
/**
****************************** Support C++ **********************************
**/
#ifdef __cplusplus
extern "C"{
#endif
/**
*****************************************************************************
**/
/******************************************************************************
外部函数头文件
******************************************************************************/
#include "sys.h"
/******************************************************************************
定义捕获计数周期
******************************************************************************/
//
//注意:CCRx寄存器是16位的,分频注意大小,计数太快会爆,根据所捕获的频率设置
//
#define PWM_Capture_Prescaler (uint16_t)72 //分频:72000 000 / 72 = 1000 000Hz
#define PWM_Capture_Period (uint16_t)1000 //计数:1000 --> 1KHz
/******************************************************************************
外部调用功能函数
******************************************************************************/
void PWM_CaptureInit (void); //PWM输入捕获初始化
void PWM_CaptureGetFrequency_DutyCycle (uint32_t TIMx_CLK/* 单位Hz */, uint32_t * Freq/* 单位Hz */, uint8_t * Duty); //计算捕获PWM频率、占空比
/**
****************************** Support C++ **********************************
**/
#ifdef __cplusplus
}
#endif
/**
*****************************************************************************
**/
#endif /* end pwm_capture.h */
[/mw_shl_code]
|
|