STM32自学☞输入捕获测频率和占空比案例

本文详细描述了如何使用STM32F10x的TIM模块生成PWM波,并通过PA6口捕获频率和占空比,最后在OLED屏上实时显示设置的参数。涉及到了GPIO配置、TIM时基和输出比较单元的初始化,以及频率和占空比的获取方法。
摘要由CSDN通过智能技术生成

本文是通过PA0口输出PWM波,然后通过PA6口捕获PWM波的频率和占空比,最终在oled屏上显示我们自己设置的频率和占空比。由于和前面的pwm呼吸灯代码有重合部分所以本文中的代码由前者修改而来,对于文件命名不要在意。

pwm_led.c文件

/*

编写步骤

1.RCC开启时钟(TIM、GPIO)

2.配置时基单元

3.配置输出比较单元

4.配置GPIO

5.运行控制

*/

#include "stm32f10x.h"

#include "stm32f10x_tim.h"

#include "pwm_led.h"

//初始化函数

void PWM_Init(void)

{

 /*开启时钟*/

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟

 /*GPIO初始化*/

 GPIO_InitTypeDef GPIO_InitStructure;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO_Pin_15;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_Init(GPIOA, &GPIO_InitStructure);

 /*配置时钟源*/

 TIM_InternalClockConfig(TIM2); //选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟

 /*时基单元初始化*/

 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量

 TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能

 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数

 TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //计数周期,即ARR的值

 TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //预分频器,即PSC的值

 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到

 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元

 /*输出比较初始化*/

 TIM_OCInitTypeDef TIM_OCInitStructure; //定义结构体变量

 TIM_OCStructInit(&TIM_OCInitStructure); //结构体初始化,若结构体没有完整赋值则最好执行此函数,给结构体所有成员都赋一个默认值,避免结构体初值不确定的问题

 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出比较模式,选择PWM模式1

 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性,选择为高,若选择极性为低,则输出高低电平取反

 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能

 TIM_OCInitStructure.TIM_Pulse = 0; //初始的CCR值

 TIM_OC1Init(TIM2, &TIM_OCInitStructure); //将结构体变量交给TIM_OC1Init,配置TIM2的输出比较通道1

 /*TIM使能*/

 TIM_Cmd(TIM2, ENABLE); //使能TIM2,定时器开始运行

}

/*改变占空比函数*/

void PWM_SetCompare1(uint16_t Compare)

{

 TIM_SetCompare1(TIM2, Compare); //设置CCR1的值

}

/*通过设置psc的值来调节频率*/

void PWM_SetPrescaler(uint16_t Prescaler)

{

 TIM_PrescalerConfig(TIM2,Prescaler,TIM_PSCReloadMode_Immediate); //写入一个值,立刻生效

}

pwm_led.h文件

#ifndef _PWM_LED_H

#define _PWM_LED_H

#include "stdint.h"

void PWM_Init(void);

void PWM_SetCompare1(uint16_t Compare);

void PWM_SetPrescaler(uint16_t Prescaler);

#endif

ic.c文件

#include "stm32f10x.h"

#include "stm32f10x_tim.h"

#include "ic.h"

/*初始化函数步骤

1.开启GPIO和TIM的时钟

2.GPIO初始化并把GPIO配置为输入模式

3.配置时基单元,让CNT计数器在内部时钟驱动下自增运行

4.配置输入捕获单元

5.选择从模式的触发源

6.选择触发后执行的操作

7.开启定时器

*/

void IC_Init(void)

{

 /*开启时钟*/

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //开启TIM3的时钟

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟

 /*GPIO初始化*/

 GPIO_InitTypeDef GPIO_InitStructure;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //GPIO_Pin_6;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

 GPIO_Init(GPIOA, &GPIO_InitStructure); //将PA6引脚初始化为复用推挽输出,受外设控制的引脚,均需要配置为复用模式  

 /*配置时钟源*/

 TIM_InternalClockConfig(TIM3); //选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟

 /*时基单元初始化*/

 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的值

 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到

 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元

 /*初始化输入捕获单元*/

 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);

 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_PWMIConfig(TIM3,&TIM_ICInitStruct);

 /*配置从模式的触发源*/

 TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);

 /*配置从模式为Reset*/

 TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);

 //使能

 TIM_Cmd(TIM3,ENABLE);

}

//获取频率的函数

uint32_t IC_GetFreq(void)

{

 return 1000000/(TIM_GetCapture1(TIM3)+1);

}

//获取占空比的函数

uint32_t IC_GetDuty(void)

{

 return TIM_GetCapture2(TIM3)*100/(TIM_GetCapture1(TIM3)+1);

}

ic.h文件

#ifndef _IC_H

#define _IC_H

#include "stdint.h"

void IC_Init(void);

uint32_t IC_GetFreq(void);

uint32_t IC_GetDuty(void);

#endif

main.c文件

#include "stm32f10x.h"

#include "stm32f10x_tim.h"

#include "delay.h"

#include "OLED.h"

#include "pwm_led.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(7200-1);

 PWM_SetCompare1(80);

 while(1)

 {

  OLED_ShowNum(1,6,IC_GetFreq(),5);

  OLED_ShowNum(2,6,IC_GetDuty(),2);

 }

}

 

 

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鯨觞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值