一、微项目实现目标:
检测外部输入的PWM波,并且输出对应PWM波的占空比和频率
二、微项目硬件配置需求:
stm32F103C8T6核心板一块
0.96寸OLED显示,用于显示计数
三、前置知识:
1,什么是占空比:高电平占整个周期的百分比
2,如何测量占空比和频率
①在第一个上升沿时刻,开始CNT计数,在出现第一个下降沿时刻,将此时的CNT放置到CCR2寄存器中,在出现下一个上升沿时刻,将此刻的数据存放在CCR1中;
②CCR1就表示着整体的运行频率;
③CCR2/CCR1表示占空比数据;
3,PWMI模式说明
①GPIO采集信号--滤波器处理--边沿检测----给到两路通道TIM_Channel_1 TIM_Channel_2---
②时基模块,一直在运行中,当遇到第一次下降沿,数据会保存在CCR2中,用于计算占空比的数据
③第二次上升沿时刻,数据会保存在CCR1中。并且此时,触发的TI1FP1
四、代码模块分析:
①TIM2时钟开启、GPIOA时钟开启
②配置GPIO模块;
③配置时钟源-内部72MHZ
④时基模块配置
⑤输入模块配置-通道1
⑥输入模块配置-通道2
⑦从模式配置
⑧时钟开启
五、代码示例:
①TIM2时钟开启、GPIOA时钟开启
//开启GPIO、TIM的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//tim3
②配置GPIO模块;
//配置PA6端口
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode= GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
③配置时钟源-内部72MHZ
//时基单元时钟源配置--系统时钟72MHZ
TIM_InternalClockConfig(TIM3);
④时基模块配置
//时基单元配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1 ;
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up ;
TIM_TimeBaseInitStruct.TIM_Period=65536-1; //ARR
TIM_TimeBaseInitStruct.TIM_Prescaler=72-1; //PSC
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
⑤输入模块配置-通道1 (直连通道)
//配置输入捕获
TIM_ICInitTypeDef TIM_ICInitStruct;
TIM_ICInitStruct.TIM_Channel=TIM_Channel_1 ;//输入捕获的端口
TIM_ICInitStruct.TIM_ICFilter=0xf;//输入捕获的滤波器
TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Rising ;//捕获的状态 上升沿/下降沿
TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1 ;//分频器,如果是二分频,则两次输出一次
TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_DirectTI;//属于直连通道还是交叉通道
TIM_ICInit( TIM3, & TIM_ICInitStruct);
⑥输入模块配置-通道2(交叉通道)
TIM_ICInitStruct.TIM_Channel=TIM_Channel_2 ;//输入捕获的端口
TIM_ICInitStruct.TIM_ICFilter=0xf;//输入捕获的滤波器
TIM_ICInitStruct.TIM_ICPolarity=TIM_ICPolarity_Falling ;//捕获的状态 上升沿/下降沿
TIM_ICInitStruct.TIM_ICPrescaler=TIM_ICPSC_DIV1 ;//分频器,如果是二分频,则两次输出一次
TIM_ICInitStruct.TIM_ICSelection=TIM_ICSelection_IndirectTI ;//属于直连通道还是交叉通道
TIM_ICInit( TIM3, & TIM_ICInitStruct);
⑦从模式配置
//从模式触发源选择
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);
}
计算占空比
uint32_t IC_getduty(void)
{
return TIM_GetCapture2(TIM3)*100/TIM_GetCapture1(TIM3);
}
在主函数简单配置
#include "stm32f10x.h" // Device header
#include "delay.h"
#include "OLED.H"
#include "PWM.H"
#include "ic.H"
uint32_t freq=0;
int main()
{
OLED_Init();
OLED_ShowString(1,1,"freq:00000HZ");
OLED_ShowString(2,1,"duty:000%");
pwm_init();
ic_init();
pwm_setcompare(80);//duty=CCR/100 占空比
pwm_setPerscaler(7200-1); //freq=72M/(psc+1)/100 频率
while(1)
{
freq=IC_getfreq();
OLED_ShowNum(1,6,freq,5);
OLED_ShowNum(2,6,IC_getduty(),3);
}
}