作者博客主页
作者 : Eterlove
一笔一画,记录我的学习生活!站在巨人的肩上Standing on Shoulders of Giants!
该文章为原创,转载请注明出处和作者
声明:这段时间较忙,相关知识点分析讲解后面抽时间补上。
1.学习记录
用定时器TIM3来产生一个PWM的波形【频率可调,占空比可调–>相对可调】,然后用TIM2的输入捕获功能测量该波形的频率。
PA1---->TIM2_CH2
PA2---->TIM2_CH3
PA6---->TIM3_CH1
PA7---->TIM3_CH2
2.产生PWM波形TIM3_CH1_PA6
/* PA6----TIM3_CH1
PA7----TIM3_CH2 */
#include "stm32f10x.h"
#include "TIM3.h"
// The TIM3 is running at 1 KHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1)
// 1 KHz = 1MHZ /1000
//ARR = (TIM3 counter clock /Frequency)-1
//PWM 信号频率可调,占空比可调 PA6
void TIM3_PWM_Output(float Duty , uint32_t Frequency)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* GPIOA clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO ,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = (1000000/Frequency)-1; //ARR = (TIM3 counter clock /Frequency)-1
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = ((1000000/Frequency)-1)*Duty;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
为什么说频率和占空比相对可调?
TIM_TimeBaseStructure.TIM_Prescaler = 71;
这里我固定了计数时钟频率72MHZ/72 =1MHZ
TIM_TimeBaseStructure.TIM_Period = (1000000/Frequency)-1; //ARR = (TIM3 counter clock /Frequency)-1
Frequency这个变量值如果非常的”奇葩“,那么TIM_Period 只能除整,会造成一点误差。同理占空比也是。所以我这样写只是方便在主函数中直接输入参数调用,具体问题具体分析,遇到一些不好处理的数值请重新配置,自己去“凑整”
TIM_OCInitStructure.TIM_Pulse = ((1000000/Frequency)-1)*Duty;
3.TIM2的输入捕获测量频率TIM2_CH2_PA1
//Input_Capture.C文件
#include "Input_Capture.h"
//PA1---->TIM2_CH2
//PA2---->TIM2_CH3
__IO uint16_t IC2ReadValue1 = 0, IC2ReadValue2 = 0;
__IO uint16_t CaptureNumber = 0;
__IO uint32_t Capture = 0;
__IO uint32_t TIM2Freq = 0;
void Input_Capture_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
//留下一个问题,这里为什么不使能AFIO??
/* 参考手册P121 对寄存器AFIO_EVCR,AFIO_MAPR和AFIO_EXTICRX进行读写操作前,应当首先打开AFIO
的时钟。参考第6.3.7节APB2外设时钟使能寄存器(RCC_APB2ENR)。 */
/* TIM2 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* GPIOA and GPIOB clock enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* TIM2 channel 2,3 pin (PA.01,PA.02) configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable the TIM2 global Interrupt */
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);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 65535 ;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
//输入捕获配置 TIM2_CH2
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
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_ICInit(TIM2, &TIM_ICInitStructure);
//输入捕获配置 TIM2_CH3
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
TIM_ICInit(TIM2, &TIM_ICInitStructure);
/* TIM enable counter */
TIM_Cmd(TIM2, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM2, TIM_IT_CC2|TIM_IT_CC3, ENABLE);
}
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET)
{
/* Clear TIM2 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
if(CaptureNumber == 0)
{
/* Get the Input Capture value */
IC2ReadValue1 = TIM_GetCapture2(TIM2);
CaptureNumber = 1;
}
else if(CaptureNumber == 1)
{
/* Get the Input Capture value */
IC2ReadValue2 = TIM_GetCapture2(TIM2);
/* Capture computation */
if (IC2ReadValue2 > IC2ReadValue1)
{
Capture = (IC2ReadValue2 - IC2ReadValue1);
}
else
{
Capture = ((0xFFFF - IC2ReadValue1) + IC2ReadValue2);
}
/* Frequency computation */
//TIM2Freq = (uint32_t) SystemCoreClock/72/ Capture;
TIM2Freq = (uint32_t)1000000 / Capture;
CaptureNumber = 0;
}
}
}
Input_Capture.C文件,这里为什么要把TIM2 /72分频 得到1MHZ的计数频率呢?
因为我们的CCRx寄存器是一个16bit的寄存器计数范围为0 到0xFFFF,即0~65535,可是当测量的矩形波周期太长,脉冲宽度太宽,二我们的计数又太快,很容易出现CCRx溢出现象,所以,我们在测量低频信号时,一定要对TIM的时钟进行分频,这样我们的计数就不会那么快了,也不会产生溢出现象.
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 65535 ;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
4.实验现象
#include "stm32f10x.h"
#include "lcd.h"
#include "stdio.h"
#include "Key.h"
#include "TIM3.h"
#include "LED.h"
#include "string.h"
#include "Input_Capture.h"
u32 TimingDelay = 0;
void Delay_Ms(u32 nTime);
u8 TIM2FreqBuffer[20] = {0};
extern __IO uint32_t TIM2Freq;
//Main Body
int main(void)
{
SysTick_Config(SystemCoreClock/1000);
Delay_Ms(200);
STM3210B_LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
Led_Init(); //LED初始化
Led_Control(LED_ALL , OFF); //LED全关
Key_Init(); //按键初始化
TIM3_PWM_Output(0.40 , 1000); //PWM 信号频率可调 ,占空比可调 PA6
Input_Capture_Init(); //定时器TIM2 捕获初始化
while(1)
{
//测得频率显示在LCD
sprintf(TIM2FreqBuffer , "TIM2Freq:%d HZ" ,TIM2Freq);
LCD_DisplayStringLine(Line5 , TIM2FreqBuffer );
}
}
//毫秒延时函数
void Delay_Ms(u32 nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
(1)例如输出为duty:40% , 1KHZ的PWM波形
TIM3_PWM_Output(0.40 , 1000); //PWM 信号频率可调 ,占空比可调 PA6
用示波器验证,测量PA6引脚输出PWM的频率,防止意外发生
Input_Capture_Init(); //定时器TIM2 捕获初始化
将PA6和PA1相连
把PWM的波形频率调高至55KHZ
TIM3_PWM_Output(0.40 , 55000); //PWM 信号频率可调 ,占空比可调 PA6
Input_Capture_Init(); //定时器TIM2 捕获初始化
感谢大家阅读!