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

**本文是通过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);

}

}

相关推荐
Miuney_MAX4 小时前
【单片机】之HC32F460中断向量选择
单片机·嵌入式硬件
XINVRY-FPGA7 小时前
XC3S1000-4FGG320I Xilinx AMD Spartan-3 SRAM-based FPGA
嵌入式硬件·机器学习·计算机视觉·fpga开发·硬件工程·dsp开发·fpga
猫猫的小茶馆9 小时前
【ARM】ARM的介绍
c语言·开发语言·arm开发·stm32·单片机·嵌入式硬件·物联网
猫猫的小茶馆10 小时前
【PCB工艺】数模电及射频电路基础
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·pcb工艺
点灯小铭10 小时前
基于单片机的智能药物盒设计与实现
数据库·单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
梓德原10 小时前
【基础】详细分析带隙型稳压电路的工作原理
单片机·嵌入式硬件·物联网
国科安芯11 小时前
航天医疗领域AS32S601芯片的性能分析与适配性探讨
大数据·网络·人工智能·单片机·嵌入式硬件·fpga开发·性能优化
小李做物联网12 小时前
【物联网毕业设计】60.1基于单片机物联网嵌入式项目程序开发之图像厨房监测系统
stm32·单片机·嵌入式硬件·物联网
贝塔实验室13 小时前
新手如何使用Altium Designer创建第一张原理图(三)
arm开发·单片机·嵌入式硬件·fpga开发·射频工程·基带工程·嵌入式实时数据库
@good_good_study13 小时前
STM32 ADC多通道采样实验
stm32·单片机·嵌入式硬件