目录

14.6 使用高级定时器实现精确计时

14.6.1 实验要求

14.6.2 软件设计

14.6.3 下载验证

14.7 TIM高级定时器PWM波互补输出

14.7.1 PWM波是什么

14.7.2 实验要求

14.7.3 软件设计

14.7.4 下载验证

14.8 TIM高级定时器输入捕获

14.6.1 实验要求

14.6.2 软件设计

14.6.3 下载验证


14.6 使用高级定时器实现精确计时

14.6.1 实验要求

使用高级定时器实现LED灯和蜂鸣器状态1s翻转一次。

14.6.2 软件设计

14.6.2.1 设计思路

首先对高级定时器的时钟,周期,中断等信息进行宏定义即bsp_AdvanceTim.h文件便于之后对代码的移植,完成后需要对定时器的模式和中断优先级进行配置即bsp_AdvaceTim.c文件,配置完成过后还需要在stm32f10x_it.c文件中编写中断服务函数,以上都完成后就能够在main.c文件中编写我们所需要的功能代码了。

14.6.2.2 代码分析

bsp_AdvanceTim.h

#ifndef _BSP_ADVANCETIM_H
#define _BSP_ADVANCETIM_H#include "stm32f10x.h"#define ADVANCE_TIM1   #ifdef  ADVANCE_TIM1    //使用高级定时器1
#define ADVANCE_TIM                     TIM1
#define ADVANCE_TIM_APBxClock_FUN       RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK                 RCC_APB2Periph_TIM1
#define ADVANCE_TIM_Period              (1000-1)
#define ADVANCE_TIM_Prescaler           71
#define ADVANCE_TIM_IRQ                 TIM1_UP_IRQn
#define ADVANCE_TIM_IRQHandler          TIM1_UP_IRQHandler#else             //使用高级定时器8
#define ADVANCE_TIM                     TIM8 
#define ADVANCE_TIM_APBxClock_FUN       RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK                 RCC_APB2Periph_TIM8
#define ADVANCE_TIM_Period              (1000-1)
#define ADVANCE_TIM_Prescaler           71
#define ADVANCE_TIM_IRQ                 TIM8_UP_IRQn
#define ADVANCE_TIM_IRQHandler          TIM8_UP_IRQHandler#endifvoid ADVANCE_TIM_Init(void);#endif /*_BSP_ADVANCETIM_H*/

bsp_AdvanceTim.c

#include "bsp_AdvanceTim.h"static void ADVANCE_TIM_Mode_Config(void)
{TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;//开启定时器时钟,即内部CK_INT = 72MADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);//自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_Period = ADVANCE_TIM_Period;//时钟分频系数TIM_TimeBaseStructure.TIM_Prescaler = ADVANCE_TIM_Prescaler;//时钟分频因子,基本定时器没有不用管TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //计数器的计数模式,基本定时器只能向上计数,没有计数模式的设置TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//重复计数器的值,基本定时器没有,不用管TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;//初始化定时器TIM_TimeBaseInit(ADVANCE_TIM,&TIM_TimeBaseStructure);//清除计数器的中断标志位TIM_ClearFlag(ADVANCE_TIM,TIM_FLAG_Update);//开启计数器中断TIM_ITConfig(ADVANCE_TIM,TIM_IT_Update,ENABLE);//使能计数器TIM_Cmd(ADVANCE_TIM,ENABLE);
}static void ADVANCE_TIM_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStruct;//设置中断优先级分组位0NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//设置中断源NVIC_InitStruct.NVIC_IRQChannel = ADVANCE_TIM_IRQ;//设置主优先级为0NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//设置抢占优先级为3NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);
}void ADVANCE_TIM_Init(void)
{ADVANCE_TIM_NVIC_Config();ADVANCE_TIM_Mode_Config();
}

中断服务函数

#include "stm32f10x_it.h"
#include "bsp_AdvanceTim.h"extern volatile uint32_t time;
void ADVANCE_TIM_IRQHandler(void)
{if ( TIM_GetITStatus(ADVANCE_TIM, TIM_IT_Update) != RESET ) { time++;TIM_ClearITPendingBit(ADVANCE_TIM, TIM_FLAG_Update);        }
}

main.c

#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_buzzer.h"
#include "bsp_AdvanceTim.h"volatile uint32_t time = 0;       //ms计时变量int main(void)
{LED_GPIO_Config();ADVANCE_TIM_Init();BUZZER_GPIO_Config();while(1){//1000 * 1ms = 1sif(time == 1000){time = 0;LED2_Toggle;BUZZER_Toggle;}}
}

14.6.3 下载验证

编译下载到开发板中能够观察到板载的LED灯和蜂鸣器亮,响一秒,反复循环此状态。

14.7 TIM高级定时器PWM波互补输出

14.7.1 PWM波是什么

PWM波(Pulse Width Modulation),即脉宽调制,是一种用于控制电子元件(如开关、电机、LED等)的技术。它通过改变脉冲的宽度和周期来控制电流或电压的大小,从而实现对目标设备的精确控制。

PWM波可以通过快速切换电源开关来产生,其中一段时间为高电平,另一段时间为低电平。这样产生的信号被称为矩形波形。改变矩形波形的频率,可以改变PWM波信号所控制器件的响应速度。当频率高于人耳能听到的范围时,人们无法感知。

通常情况下,PWM波信号被用于控制DC电机、步进电机、LED灯等。以LED为例,当PWM波信号中高电平占空比较大时,即高电平时间长且低电平时间短时,LED会发出较亮的光芒。反之,则发出弱光。因此,通过控制PWM波信号的占空比来调节LED灯的亮度。

总之,PWM波作为一种常见的控制技术,在工业生产中有着广泛应用,并得到了很好的实践效果。

14.7.2 实验要求

实现频率为1MHz占空比50%的PWM波并使用KingstLA1010逻辑分析仪或者使用Keil5自带的仿真器观察输出的波形。

14.7.3 软件设计

14.7.3.1 设计思路

首先对定时器用到的 GPIO 初始化,定时器时基结构体 TIM_TimeBaseInitTypeDef 初始化,定时器输出比较结构体 TIM_OCInitTypeDef 初始化,定时器刹车和死区结构体 TIM_BDTRInitTypeDef 初始化。

14.7.3.2 代码分析

bsp_AdvanceTim.h

#ifndef _BSP_ADVANCETIM_H
#define _BSP_ADVANCETIM_H#include "stm32f10x.h"#define ADVANCE_TIM                   TIM1
#define ADVANCE_TIM_APBxClock_FUN     RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK               RCC_APB2Periph_TIM1// PWM 信号的频率 F = TIM_CLK/{(ARR+1)*(PSC+1)}
#define ADVANCE_TIM_PERIOD            (8-1)
#define ADVANCE_TIM_PSC               (100-1)
#define ADVANCE_TIM_PULSE             4#define ADVANCE_TIM_IRQ               TIM1_UP_IRQn
#define ADVANCE_TIM_IRQHandler        TIM1_UP_IRQHandler// TIM1 输出比较通道
#define ADVANCE_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
#define ADVANCE_TIM_CH1_PORT          GPIOA
#define ADVANCE_TIM_CH1_PIN           GPIO_Pin_8// TIM1 输出比较通道的互补通道
#define ADVANCE_TIM_CH1N_GPIO_CLK      RCC_APB2Periph_GPIOB
#define ADVANCE_TIM_CH1N_PORT          GPIOB
#define ADVANCE_TIM_CH1N_PIN           GPIO_Pin_13// TIM1 输出比较通道的刹车通道
#define ADVANCE_TIM_BKIN_GPIO_CLK      RCC_APB2Periph_GPIOB
#define ADVANCE_TIM_BKIN_PORT          GPIOB
#define ADVANCE_TIM_BKIN_PIN           GPIO_Pin_12void ADVANCE_TIM_Init(void);#endif /*_BSP_ADVANCETIM_H*/

bsp_AdvanceTim.c

#include "bsp_AdvanceTim.h"static void ADVANCE_TIM_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;//输出比较通道GPIO端口初始化RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK,ENABLE);//打开端口时钟GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;       //选择对应端口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            //配置为复用推挽输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //速度为50MHzGPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);//输出比较互补通道GPIO端口初始化RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK,ENABLE);//打开端口时钟GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;     //选择对应端口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            //配置为复用推挽输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //速度为50MHzGPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);//输出比较通道刹车通道 GPIO 初始化RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK,ENABLE);//打开端口时钟GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;      //选择对应端口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;            //配置为复用推挽输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //速度为50MHzGPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);//BKIN引脚默认先输出低电平GPIO_ResetBits(ADVANCE_TIM_BKIN_PORT,ADVANCE_TIM_BKIN_PIN);
}static void ADVANCE_TIM_Mode_Config(void)
{// 开启定时器时钟,即内部时钟CK_INT=72MADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);/*--------------------时基结构体初始化-------------------------*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_PERIOD;// 驱动CNT计数器的时钟 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_PSC;// 时钟分频因子 ,配置死区时间时需要用到TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 计数器计数模式,设置为向上计数TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;// 重复计数器的值,没用到不用管TIM_TimeBaseStructure.TIM_RepetitionCounter=0; // 初始化定时器TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);/*--------------------输出比较结构体初始化-------------------*/    TIM_OCInitTypeDef  TIM_OCInitStructure;// 配置为PWM模式1TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;// 输出使能TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;// 互补输出使能TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 设置占空比大小TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE;// 输出通道电平极性配置TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 互补输出通道电平极性配置TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;// 输出通道空闲电平极性配置TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;// 互补输出通道空闲电平极性配置TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure);TIM_OC1PreloadConfig(ADVANCE_TIM, TIM_OCPreload_Enable);/*-------------------刹车和死区结构体初始化-------------------*/TIM_BDTRInitTypeDef TIM_BDTRInitStructure;// 有关刹车和死区结构体的成员具体可参考BDTR寄存器的描述TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;// 输出比较信号死区时间配置,具体如何计算可参考 BDTR:UTG[7:0]的描述// 这里配置的死区时间为152nsTIM_BDTRInitStructure.TIM_DeadTime = 11;TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;// 当BKIN引脚检测到高电平的时候,输出比较信号被禁止,就好像是刹车一样TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);// 使能计数器TIM_Cmd(ADVANCE_TIM, ENABLE);// 主输出使能,当使用的是通用定时器时,这句不需要TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE);
}void ADVANCE_TIM_Init(void)
{ADVANCE_TIM_GPIO_Config();ADVANCE_TIM_Mode_Config();
}

main.c

#include "stm32f10x.h"
#include "bsp_AdvanceTim.h"int main(void)
{//高级定时器初始化ADVANCE_TIM_Init();while(1){   }
}

14.7.4 下载验证

代码经编译后没错误后使用KingstVIS逻辑分析仪观察波形,逻辑分析仪的GND引脚接到开发板的GND引脚,开发板的PA8,PB13分别接到逻辑分析仪的CH0,CH1上,也可以使用Keil5软件自带的逻辑分析仪来观察波形,能够观察到两条互补的PWM波,频率为1MHz,占空比为50%。

14.8 TIM高级定时器输入捕获

14.6.1 实验要求

使用通用定时器来产生不同占空比的PWM波然后用高级定时器来捕获通用定时器输出的PWM波通过串口显示频率和占空比。

14.6.2 软件设计

14.6.2.1 设计思路

(1) 通用定时器产生 PWM 配置

(2) 高级定时器 PWM 输入配置

(3) 编写中断服务程序,计算测量的频率和占空比,并打印出来比较编程的要点主要分成两部分,一个是通用定时器的 PWM 信号输出,另一个是 PWM 信号输入捕获。

14.6.2.2 代码分析

bsp_GeneralTim.h

#ifndef __BSP_GENERALTIME_H
#define __BSP_GENERALTIME_H#include "stm32f10x.h"/************通用定时器TIM参数定义,只限TIM2、3、4、5************/
// 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意#define GENERAL_TIM                   TIM3
#define GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd 
#define GENERAL_TIM_CLK               RCC_APB1Periph_TIM3// 输出PWM的频率为 72M/{ (ARR+1)*(PSC+1) }
#define GENERAL_TIM_PERIOD            (100-1)
#define GENERAL_TIM_PSC               (72-1)#define GENERAL_TIM_CCR1              50
#define GENERAL_TIM_CCR2              40
#define GENERAL_TIM_CCR3              30
#define GENERAL_TIM_CCR4              20// TIM3 输出比较通道1
#define GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
#define GENERAL_TIM_CH1_PORT          GPIOA
#define GENERAL_TIM_CH1_PIN           GPIO_Pin_6// TIM3 输出比较通道2
#define GENERAL_TIM_CH2_GPIO_CLK      RCC_APB2Periph_GPIOA
#define GENERAL_TIM_CH2_PORT          GPIOA
#define GENERAL_TIM_CH2_PIN           GPIO_Pin_7// TIM3 输出比较通道3
#define GENERAL_TIM_CH3_GPIO_CLK      RCC_APB2Periph_GPIOB
#define GENERAL_TIM_CH3_PORT          GPIOB
#define GENERAL_TIM_CH3_PIN           GPIO_Pin_0// TIM3 输出比较通道4
#define GENERAL_TIM_CH4_GPIO_CLK      RCC_APB2Periph_GPIOB
#define GENERAL_TIM_CH4_PORT          GPIOB
#define GENERAL_TIM_CH4_PIN           GPIO_Pin_1/**************************函数声明********************************/void GENERAL_TIM_Init(void);#endif  /* __BSP_GENERALTIME_H */

bsp_GeneralTim.c

#include "bsp_GeneralTim.h"static void GENERAL_TIM_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;// 输出比较通道1 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);// 输出比较通道2 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH2_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH2_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GENERAL_TIM_CH2_PORT, &GPIO_InitStructure);// 输出比较通道3 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH3_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH3_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GENERAL_TIM_CH3_PORT, &GPIO_InitStructure);// 输出比较通道4 GPIO 初始化RCC_APB2PeriphClockCmd(GENERAL_TIM_CH4_GPIO_CLK, ENABLE);GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH4_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GENERAL_TIM_CH4_PORT, &GPIO_InitStructure);
}///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler            都有
// *    TIM_CounterMode              TIMx,x[6,7]没有,其他都有
// *  TIM_Period               都有
// *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
// *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef;
// *-----------------------------------------------------------------------------
// *//* ----------------   PWM信号 周期和占空比的计算--------------- */
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1)
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M
// 占空比P=CCR/(ARR+1)static void GENERAL_TIM_Mode_Config(void)
{// 开启定时器时钟,即内部时钟CK_INT=72MGENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);/*--------------------时基结构体初始化-------------------------*/TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;// 配置周期,这里配置为100K// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_PERIOD;// 驱动CNT计数器的时钟 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_PSC;// 时钟分频因子 ,配置死区时间时需要用到TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;// 计数器计数模式,设置为向上计数TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;// 重复计数器的值,没用到不用管TIM_TimeBaseStructure.TIM_RepetitionCounter=0;  // 初始化定时器TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);/*--------------------输出比较结构体初始化-------------------*/    TIM_OCInitTypeDef  TIM_OCInitStructure;// 配置为PWM模式1TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 输出使能TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;// 输出通道电平极性配置    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;// 输出比较通道 1TIM_OCInitStructure.TIM_Pulse = GENERAL_TIM_CCR1;TIM_OC1Init(GENERAL_TIM, &TIM_OCInitStructure);TIM_OC1PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);// 输出比较通道 2TIM_OCInitStructure.TIM_Pulse = GENERAL_TIM_CCR2;TIM_OC2Init(GENERAL_TIM, &TIM_OCInitStructure);TIM_OC2PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);// 输出比较通道 3TIM_OCInitStructure.TIM_Pulse = GENERAL_TIM_CCR3;TIM_OC3Init(GENERAL_TIM, &TIM_OCInitStructure);TIM_OC3PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);// 输出比较通道 4TIM_OCInitStructure.TIM_Pulse = GENERAL_TIM_CCR4;TIM_OC4Init(GENERAL_TIM, &TIM_OCInitStructure);TIM_OC4PreloadConfig(GENERAL_TIM, TIM_OCPreload_Enable);// 使能计数器TIM_Cmd(GENERAL_TIM, ENABLE);
}void GENERAL_TIM_Init(void) 
{GENERAL_TIM_GPIO_Config();GENERAL_TIM_Mode_Config();
}

bsp_AdvanceTim.h

#ifndef __BSP_ADVANCETIME_H
#define __BSP_ADVANCETIME_H#include "stm32f10x.h"/************高级定时器TIM参数定义,只限TIM1和TIM8************/
// 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意
// 这里我们使用高级控制定时器TIM1#define ADVANCE_TIM                   TIM1
#define ADVANCE_TIM_APBxClock_FUN     RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK               RCC_APB2Periph_TIM1// 输入捕获能捕获到的最小的频率为 72M/{ (ARR+1)*(PSC+1) }
#define ADVANCE_TIM_PERIOD            (1000-1)
#define ADVANCE_TIM_PSC               (72-1)// 中断相关宏定义
#define ADVANCE_TIM_IRQ               TIM1_CC_IRQn
#define ADVANCE_TIM_IRQHandler        TIM1_CC_IRQHandler// TIM1 输入捕获通道1
#define ADVANCE_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA 
#define ADVANCE_TIM_CH1_PORT          GPIOA
#define ADVANCE_TIM_CH1_PIN           GPIO_Pin_8#define ADVANCE_TIM_IC1PWM_CHANNEL    TIM_Channel_1
#define ADVANCE_TIM_IC2PWM_CHANNEL    TIM_Channel_2/**************************函数声明********************************/void ADVANCE_TIM_Init(void);#endif   /* __BSP_ADVANCETIME_H */

bsp_AdvanceTim.c

#include "bsp_AdvanceTim.h"static void ADVANCE_TIM_NVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);               // 设置中断组为0NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM_IRQ;        // 设置中断来源NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 设置抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;          // 设置子优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}static void ADVANCE_TIM_GPIO_Config(void)  
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);  //开启PA8时钟GPIO_InitStructure.GPIO_Pin =  ADVANCE_TIM_CH1_PIN;           //选择PA8端口GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;     //模式配置为浮空输入GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);
}static void ADVANCE_TIM_Mode_Config(void)
{// 开启定时器时钟,即内部时钟CK_INT=72MADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);  /*--------------------时基结构体初始化-------------------------*/TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_PERIOD;// 驱动CNT计数器的时钟 = Fck_int/(psc+1)TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_PSC;// 时钟分频因子 ,配置死区时间时需要用到    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;// 计数器计数模式,设置为向上计数 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;// 重复计数器的值,没用到不用管TIM_TimeBaseStructure.TIM_RepetitionCounter=0;       TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);  // 初始化定时器/*--------------------输入捕获结构体初始化-------------------*/
// 使用PWM输入模式时,需要占用两个捕获寄存器,一个测周期,另外一个测占空比TIM_ICInitTypeDef  TIM_ICInitStructure;// 捕获通道IC1配置TIM_ICInitStructure.TIM_Channel = ADVANCE_TIM_IC1PWM_CHANNEL;  // 选择捕获通道TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;       // 设置捕获的边沿// 设置捕获通道的信号来自于哪个输入通道,有直连和非直连两种TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;// 1分频,即捕获信号的每个有效边沿都捕获TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;         TIM_ICInitStructure.TIM_ICFilter = 0x0;                            // 不滤波// 初始化PWM输入模式TIM_PWMIConfig(ADVANCE_TIM, &TIM_ICInitStructure);           // 当工作做PWM输入模式时,只需要设置触发信号的那一路即可(用于测量周期)// 另外一路(用于测量占空比)会由硬件自带设置,不需要再配置// 捕获通道IC2配置   //TIM_ICInitStructure.TIM_Channel = ADVANCE_TIM_IC1PWM_CHANNEL;//TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;//TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI;//TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//TIM_ICInitStructure.TIM_ICFilter = 0x0;//TIM_PWMIConfig(ADVANCE_TIM, &TIM_ICInitStructure);TIM_SelectInputTrigger(ADVANCE_TIM, TIM_TS_TI1FP1);        // 选择输入捕获的触发信号// 选择从模式: 复位模式// PWM输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器CNT会被复位TIM_SelectSlaveMode(ADVANCE_TIM, TIM_SlaveMode_Reset);TIM_SelectMasterSlaveMode(ADVANCE_TIM,TIM_MasterSlaveMode_Enable); // 使能捕获中断,这个中断针对的是主捕获通道(测量周期那个)TIM_ITConfig(ADVANCE_TIM, TIM_IT_CC1, ENABLE);   // 清除中断标志位TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1);// 使能高级控制定时器,计数器开始计数TIM_Cmd(ADVANCE_TIM, ENABLE);
}void ADVANCE_TIM_Init(void)
{ADVANCE_TIM_NVIC_Config();ADVANCE_TIM_GPIO_Config();ADVANCE_TIM_Mode_Config();
}

bsp_usart.h

#ifndef _BSP_USART_H
#define _BSP_USART_H#include "stm32f10x.h"
#include <stdio.h>#define DEBUG_USART1    1
#define DEBUG_USART2    0
#define DEBUG_USART3    0
#define DEBUG_USART4    0
#define DEBUG_USART5    0#if DEBUG_USART1
//串口1-USART1
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200//USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd#define  DEBUG_USART_TX_GPIO_PORT       GPIOA
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler 
/**************************************************************/
#elif DEBUG_USART2
//串口2-USART2
#define  DEBUG_USARTx                   USART2
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART2
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200//USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd#define  DEBUG_USART_TX_GPIO_PORT       GPIOA
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_2
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_3#define  DEBUG_USART_IRQ                USART2_IRQn
#define  DEBUG_USART_IRQHandler         USART2_IRQHandler
/**************************************************************/
#elif DEBUG_USART3
//串口3-USART3
#define  DEBUG_USARTx                   USART3
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART3
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200//USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd#define  DEBUG_USART_TX_GPIO_PORT       GPIOA    
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_10
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_11#define  DEBUG_USART_IRQ                USART3_IRQn
#define  DEBUG_USART_IRQHandler         USART3_IRQHandler
/**************************************************************/
#elif DEBUG_USART4
//串口4-USART4
#define  DEBUG_USARTx                   USART4
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART4
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200//USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOC)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd#define  DEBUG_USART_TX_GPIO_PORT       GPIOC
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_10
#define  DEBUG_USART_RX_GPIO_PORT       GPIOC
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_11#define  DEBUG_USART_IRQ                USART4_IRQn
#define  DEBUG_USART_IRQHandler         USART4_IRQHandler
/**************************************************************/
#elif DEBUG_USART5
//串口5-USART5
#define  DEBUG_USARTx                   USART5
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART5
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200 //USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd#define  DEBUG_USART_TX_GPIO_PORT       GPIOA
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_12
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_2#define  DEBUG_USART_IRQ                USART5_IRQn
#define  DEBUG_USART_IRQHandler         USART5_IRQHandler
/**************************************************************/
#endifvoid USART_Config(void);
void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str);
void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data);
void Usart_SendHalfWorld(USART_TypeDef* pUSARTx, uint16_t data);
void Usart_Sendarray(USART_TypeDef* pUSARTx, uint8_t *array, uint8_t num);#endif /*_BSP_USART_H*/

bsp_usart.c

#include "bsp_usart.h"static void USART_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;//开启GPIO时钟 DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK,ENABLE);//将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);//将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
}NVIC_InitTypeDef NVIC_InitStruct;//配置NVIC的优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置中断源:按键1NVIC_InitStruct.NVIC_IRQChannel = DEBUG_USART_IRQ;static void USART_NVIC_Config(void)
{//配置抢占优先级:1NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//配置子优先级:1NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;//使能中断通道NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct);
}void USART_Config(void)
{USART_GPIO_Config();USART_NVIC_Config();USART_InitTypeDef USART_InitStructure;//开启串口外设时钟DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);//配置波特率USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;//设置数据帧字长USART_InitStructure.USART_WordLength = USART_WordLength_8b;//配置停止位USART_InitStructure.USART_StopBits = USART_StopBits_1;//奇偶校验控制选择USART_InitStructure.USART_Parity = USART_Parity_No;//串口模式选择//使用或操作将串口模式配置为收发模式USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//硬件流控制选择USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//串口初始化USART_Init(DEBUG_USARTx, &USART_InitStructure);//使能串口接收中断USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);//使能串口USART_Cmd(DEBUG_USARTx, ENABLE);
}void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
{//发送一个字节数据到USARTUSART_SendData(pUSARTx, data);//等待发送数据寄存器为空while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}void Usart_SendHalfWorld(USART_TypeDef* pUSARTx, uint16_t data)
{uint8_t temp_h,temp_l;temp_h = (data & 0xff00) >> 8;temp_l =  data & 0x00ff;//发送一个字节数据到USARTUSART_SendData(pUSARTx, temp_h);//等待发送数据寄存器为空while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);//发送一个字节数据到USARTUSART_SendData(pUSARTx, temp_l);//等待发送数据寄存器为空while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}void Usart_Sendarray(USART_TypeDef* pUSARTx, uint8_t *array, uint8_t num)
{uint8_t i;for(i=0;i<num;i++){Usart_SendByte( pUSARTx, array[i]);}while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
}void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str)
{uint8_t i=0;do{Usart_SendByte(pUSARTx, *(str+i));i++;}while(*(str+i) != '\0');while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
}int fputc(int ch, FILE *f)
{//发送一个字节数据到USART USART_SendData(DEBUG_USARTx, (uint8_t) ch);//等待发送数据寄存器为空while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);return (ch);
}int fgetc(FILE *f)
{//等待发送数据寄存器为空while(USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);return (int)USART_ReceiveData(DEBUG_USARTx);
}

中断服务函数

#include "stm32f10x_it.h"
#include "bsp_usart.h"
#include "bsp_AdvanceTim.h" uint16_t IC2Value = 0;
uint16_t IC1Value = 0;
float DutyCycle = 0;
float Frequency = 0;/** 如果是第一个上升沿中断,计数器会被复位,锁存到CCR1寄存器的值是0,CCR2寄存器的值也是0* 无法计算频率和占空比。当第二次上升沿到来的时候,CCR1和CCR2捕获到的才是有效的值。其中 * CCR1对应的是周期,CCR2对应的是占空比。*/
void ADVANCE_TIM_IRQHandler(void)
{//清除中断标志位TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1);//获取输入捕获值IC1Value = TIM_GetCapture1(ADVANCE_TIM);IC2Value = TIM_GetCapture2(ADVANCE_TIM);// 注意:捕获寄存器CCR1和CCR2的值在计算占空比和频率的时候必须加1if (IC1Value != 0){// 占空比计算DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);// 频率计算 Frequency = (72000000/(ADVANCE_TIM_PSC+1))/(float)(IC1Value+1);printf("占空比:%0.2f%%   频率:%0.2fHz\n",DutyCycle,Frequency);}else{DutyCycle = 0;Frequency = 0;}
}

main.c

#include "stm32f10x.h"
#include "bsp_usart.h"
#include "bsp_GeneralTim.h"
#include "bsp_AdvanceTim.h"int main(void)
{//串口初始化USART_Config();//通用定时器初始化GENERAL_TIM_Init();//高级定时器初始化ADVANCE_TIM_Init();while(1){}
}

14.6.3 下载验证

PA6和PA8连接时串口调试助手显示50%占空比,频率1KHz,PA7和PA8连接时串口调试助手显示40%占空比,频率1KHz,PB0和PA8连接时串口调试助手显示30%占空比,频率1KHz,PB1和PA8连接时串口调试助手显示20%占空比,频率1KHz。

第十五章 TIM高级定时器(下)相关推荐

  1. 天龙日梅兰竹菊_第三百一十五章 梅兰竹菊

    第三百一十五章梅兰竹菊 自打应下无崖子的承诺以来,楚柏便是一直马不停蹄的赶路! 赶到西夏,在见了李秋水之后,又被李秋水拉着前往[缥缈峰],这一路,风尘仆仆的楚柏,总算是难得空闲下来了: 不得不说! [ ...

  2. 《操作系统真象还原》第十五章 ---- 实现系统交互 操作系统最终章 四十五天的不易与坚持终完结撒花 (下)(遗憾告终)

    文章目录 专栏博客链接 相关查阅博客链接 本书中错误勘误 部分缩写熟知 实现exec的思路与启发 遗憾告终 专栏博客链接 <操作系统真象还原>从零开始自制操作系统 全章节博客链接 相关查阅 ...

  3. 【正点原子MP157连载】第三十五章 设备树下的platform驱动编写-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  4. 25 linux ndk 头文件_正点原子Linux第二十五章RTC实时时钟实验

    1)资料下载:点击资料即可下载 2)对正点原子Linux感兴趣的同学可以加群讨论:935446741 3)关注正点原子公众号,获取最新资料更新 第二十五章RTC实时时钟实验 实时时钟是很常用的一个外设 ...

  5. 第十五章 Python和Web

    第十五章 Python和Web 本章讨论Python Web编程的一些方面. 三个重要的主题:屏幕抓取.CGI和mod_python. 屏幕抓取 屏幕抓取是通过程序下载网页并从中提取信息的过程. 下载 ...

  6. 《深入理解 Spring Cloud 与微服务构建》第十五章 微服务监控 Spring Boot Admin

    <深入理解 Spring Cloud 与微服务构建>第十五章 微服务监控 Spring Boot Admin 文章目录 <深入理解 Spring Cloud 与微服务构建>第十 ...

  7. 第31章 TIM—基本定时器—零死角玩转STM32-F429系列

    第31章     TIM-基本定时器 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...

  8. 《Windows核心编程》读书笔记二十五章 未处理异常,向量化异常处理与C++异常

    第二十五章  未处理异常,向量化异常处理与C++异常 本章内容 25.1 UnhandledExceptionFilter函数详解 25.2 即时调试 25.3 电子表格示例程序 25.4 向量化异常 ...

  9. 【正点原子STM32连载】第四十五章 SD卡实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

最新文章

  1. js和html邮箱注册的正则,js邮箱正则表达式
  2. java 柱状图下载_(JFreeChart)Java图表制作
  3. [转]/tomcat/conf/server.xml配置文件的源码解析
  4. MySQL之备份恢复
  5. python组合数据分类_Python 数据可视化:分类特征统计图
  6. python:数据库连接操作入门
  7. 安全专家教你如何利用Uber系统漏洞无限制的免费乘坐?
  8. 如何改善虚幻引擎中的游戏线程CPU性能表现
  9. 神奇的for循环,让你的for循环执行100w + 1比100w次快200w倍
  10. Windows 2003 网络负载均衡的详细配置文档
  11. PHP中file_exists()判断中文文件名无效的解决方法
  12. php中如何判断目录是否存在文件_PHP判断指定目录下是否存在文件
  13. Gallery of Processor Cache Effects
  14. Unity中的几个”近义词”
  15. 一个简单LEGv8处理器的Verilog实现【三】【工具使用和编程规范】
  16. 离散求边缘密度_密度梯度理论简介——半导体器件仿真
  17. 一文读懂中国历代龙纹演变(推荐收藏)
  18. 比较两个路径的几种方式
  19. 良心录屏工具Captura
  20. 记忆化搜索 (蒟蒻练习生)

热门文章

  1. RHI_Shader Compare(HLSL、GLSL、MSL 、WGSL、OpenCL) Debug All
  2. TextRank算法介绍及实现
  3. 假设函数、损失函数、 成本函数
  4. EV代码签名申请步骤
  5. idea 字体行间距_idea
  6. 三年硬件工程师薪水_硬件工程师薪资虚高,你认可吗?
  7. 携程python工程师_携程面试之后的一些感想
  8. 近千万播放量,却一单不出,TikTok带货常见思维误区
  9. iphone的操作系统介绍_操作系统介绍
  10. 解释SAR/INSAR/DINSAR的概念