IC输入捕获

文章详细介绍了如何使用STM32F10x系列微控制器的TIM模块进行PWM输出和输入捕获功能的初始化设置,以实现频率测量和占空比调节。通过设置TIM寄存器,可以改变PWM的频率和占空比,并利用输入捕获功能测量外部信号频率。同时,文章提供了示例代码,展示了具体的配置和操作过程。
摘要由CSDN通过智能技术生成

 

 

 

 

 

 

 

 

//IC.c
#include "stm32f10x.h"                  // Device header
void IC_Init(){
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE );
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    TIM_InternalClockConfig(TIM3);
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode= TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period= 65536-1;//ARR大一些,防止计数溢出
    TIM_TimeBaseInitStructure.TIM_Prescaler= 72-1;//PSC决定了测周法的标准频率fc = 72MHz/PSC = 1M
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter= 0 ;
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
    
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel= TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICFilter= 0xF;//0x0~0xF数越大滤波效果越好,每个数对应采样频率和次数见手册
    TIM_ICInitStructure.TIM_ICPolarity= TIM_ICPolarity_Rising;//边沿检测和极性选择,上升沿触发
    TIM_ICInitStructure.TIM_ICPrescaler= TIM_ICPSC_DIV1;//不分频
    TIM_ICInitStructure.TIM_ICSelection= TIM_ICSelection_DirectTI;//数据选择器直连or交叉通道
    TIM_ICInit(TIM3,&TIM_ICInitStructure);
    
    TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
    TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);
    
    TIM_Cmd(TIM3,ENABLE);
}
//初始化后,整个电路就能进行全自动测量,当需要查看频率时需要读取CCR进行计算,所以还需要一个函数:

uint32_t IC_GetFreq(void){
    return 1000000/TIM_GetCapture1(TIM3);//测周法fx=fc/N,fc为1M,N即为CCR的值
}

//PWM.c
//在PWM控制呼吸灯基础上微改
#include "stm32f10x.h"                  
void PWM_Init(void){
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE );
    TIM_InternalClockConfig(TIM2);
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode= TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period= 10000-1;//ARR
    TIM_TimeBaseInitStructure.TIM_Prescaler= 7200-1;//PSC
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter= 0 ;
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
    
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OCNPolarity= TIM_OCNPolarity_High;
    TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse= 0;//CCR
    TIM_OC1Init(TIM2,&TIM_OCInitStructure);
    
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    TIM_Cmd(TIM2,ENABLE);
}

void PWM_SetCompare1(uint16_t Compare){//改变CCR,以改变占空比
    TIM_SetCompare1(TIM2,Compare);
}

void PWM_SetPrescaler(uint16_t Prescaler){//不同点,单独修改PSC达到修改频率的作用
    TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate);//单独写入PSC的函数,之所以不叫TIM_SetPrescaler是因为它还有个重装模式的参数
    //immediate立刻生效:可能会在值改变时产生切断波形的现象,在频率变化时会出现不完整的周期
    //update在更新事件生效:会有一个缓存器,延迟参数写入的时间,等一个周期结束了在更新事件时,再统一改变参数,保证每个周期的完整
    //此实操案例要求不高,哪个都行
}

//main.c
#include "stm32f10x.h"   // Device header
#include "Delay.h"   
#include "OLED.h"
#include "PWM.h"
#include "IC.h"

int main(void){
    OLED_Init();
    PWM_Init();
    IC_Init();
    
    OLED_ShowString(1,1,"Freq:00000Hz");
    
    PWM_SetPrescaler(720-1);   //Freq = 72M/(PSC+1)/(ARR+1),其中ARR+1为100,所以Fre=1KHz
    PWM_SetCompare1(50);       //Duty = CCR/(ARR+1),其中ARR+1为100,所以Duty=50%
    
    while(1){
        OLED_ShowNum(1,6,IC_GetFreq(),5);//从第6列开始覆盖showString
    }
}
 

//IC.c
//与输入捕获案例上微改,不同处已标注
#include "stm32f10x.h"                 
void IC_Init(){
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE );
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    TIM_InternalClockConfig(TIM3);
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode= TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period= 65536-1;
    TIM_TimeBaseInitStructure.TIM_Prescaler= 72-1;
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter= 0 ;
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
    
    TIM_ICInitTypeDef TIM_ICInitStructure;
    TIM_ICInitStructure.TIM_Channel= TIM_Channel_1;
    TIM_ICInitStructure.TIM_ICFilter= 0xF;
    TIM_ICInitStructure.TIM_ICPolarity= TIM_ICPolarity_Rising;
    TIM_ICInitStructure.TIM_ICPrescaler= TIM_ICPSC_DIV1;
    TIM_ICInitStructure.TIM_ICSelection= TIM_ICSelection_DirectTI;
    TIM_PWMIConfig(TIM3,&TIM_ICInitStructure);//不同点,PWMI模式(交叉通道)
    /*会自动把剩下的一个通道初始化相反的配置
    比如上面配置通道1为直连、上升沿;那么这个函数就会把通道2配置为交叉、下降沿,反之同理
    这个函数只支持通道1、2,不要传入通道3、4*/
    
    
    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);//高电平计数值存在CCR2,整个周期的计数值存在CCR1,故占空比=CCR2/CCR1,*100是为了显示成百分比形式
}

//PWM.c
//在PWM控制呼吸灯基础上微改,不同处已标注
#include "stm32f10x.h"                  
void PWM_Init(void){
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE );
    TIM_InternalClockConfig(TIM2);
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode= TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_Period= 10000-1;//ARR
    TIM_TimeBaseInitStructure.TIM_Prescaler= 7200-1;//PSC
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter= 0 ;
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
    
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode= TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OCNPolarity= TIM_OCNPolarity_High;
    TIM_OCInitStructure.TIM_OutputState= TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse= 0;//CCR
    TIM_OC1Init(TIM2,&TIM_OCInitStructure);
    
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    TIM_Cmd(TIM2,ENABLE);
}

void PWM_SetCompare1(uint16_t Compare){//改变CCR,以改变占空比
    TIM_SetCompare1(TIM2,Compare);
}

void PWM_SetPrescaler(uint16_t Prescaler){//不同点,单独修改PSC达到修改频率的作用
    TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate);//单独写入PSC的函数,之所以不叫TIM_SetPrescaler是因为它还有个重装模式的参数
    //immediate立刻生效:可能会在值改变时产生切断波形的现象,在频率变化时会出现不完整的周期
    //update在更新事件生效:会有一个缓存器,延迟参数写入的时间,等一个周期结束了在更新事件时,再统一改变参数,保证每个周期的完整
    //此实操案例要求不高,哪个都行
}

//main.c
#include "stm32f10x.h"   // Device header
#include "Delay.h"   
#include "OLED.h"
#include "PWM.h"
#include "IC.h"

int main(void){
    OLED_Init();
    PWM_Init();
    IC_Init();
    
    OLED_ShowString(1,1,"Freq:00000Hz");
    OLED_ShowString(2,1,"Duty:00%");//不同点
    
    PWM_SetPrescaler(720-1);   //Freq = 72M/(PSC+1)/(ARR+1),其中ARR+1为100,所以Fre=1KHz
    PWM_SetCompare1(50);       //Duty = CCR/(ARR+1),其中ARR+1为100,所以Duty=50%
    
    while(1){
        OLED_ShowNum(1,6,IC_GetFreq(),5);
        OLED_ShowNum(2,6,IC_GetDuty(),2);//不同点
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值