STM32F103_通用定时器“输入捕获”测量输入脉冲宽度

发布者:ByteChaser最新更新时间:2019-08-22 来源: eefocus关键字:STM32F103  通用定时器  输入捕获  脉冲宽度 手机看文章 扫描二维码
随时随地手机看文章

一、硬件设计

        选用通用定时器TIM5的CH1,其输入管脚为PA0,在开发板上PA0连接按键,当按键按下输入高电平,按键松开输入低电平,实验测量高电平的脉冲宽度。


二、软件设计

    1. 配置中断向量表的优先级


        因只使用一个中断 TIM5_IRQn,抢占优先级与子优先级可随意配置。


        代码如下:


static void  General_NVIC_Config(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

    

    NVIC_PriorityGroupConfig (NVIC_PriorityGroup_0);

    

    NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

    

    NVIC_Init(&NVIC_InitStructure);

}

    2. GPIO配置


        PA0配置为浮空输入模式。


static void General_GPIO_Gonfig(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    

    RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK , ENABLE);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;

    

    GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);    

}

    3. 定时器模式配置,其中包含时基结构体、输入捕获结构体的初始化以及中断的开启。

static void GeneralTim_Config(void)

{

  // 开启定时器时钟,即内部时钟CK_INT=72M

    GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);

 

/*--------------------时基结构体初始化-------------------------*/    

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    // 自动重装载寄存器的值,累计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_ICInitTypeDef TIM_ICInitStructure;

    // 配置输入捕获的通道,需要根据具体的GPIO来配置

    TIM_ICInitStructure.TIM_Channel = GENERAL_TIM_CHANNEL_x;

    // 输入捕获信号的极性配置

    TIM_ICInitStructure.TIM_ICPolarity = GENERAL_TIM_STRAT_ICPolarity;

    // 输入通道和捕获通道的映射关系,有直连和非直连两种

    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

    // 输入的需要被捕获的信号的分频系数

    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

    // 输入的需要被捕获的信号的滤波系数

    TIM_ICInitStructure.TIM_ICFilter = 0;

    // 定时器输入捕获初始化

    TIM_ICInit(GENERAL_TIM, &TIM_ICInitStructure);

    

    // 清除更新和捕获中断标志位

  TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update|GENERAL_TIM_IT_CCx);    

  // 开启更新和捕获中断  

    TIM_ITConfig (GENERAL_TIM, TIM_IT_Update | GENERAL_TIM_IT_CCx, ENABLE );

    

    // 使能计数器

    TIM_Cmd(GENERAL_TIM, ENABLE);

}

    4. 输入捕获初始化函数

void GeneralTim_Init(void)

{

    General_NVIC_Config();

    

    General_GPIO_Gonfig();

        

    GeneralTim_Config();

}

    5. 中断函数

        首先判断定时器是否溢出定时周期,并做处理。然后上升沿捕获时将计数器寄存器的值清零,中断改为下降沿触发。下降沿捕获中断时,读取计数值,改为上升沿触发,开始捕获标识清零,结束捕获置1,。。。。。。。。


void GENERAL_TIM_INT_FUN(void)

{

    // 当要被捕获的信号的周期大于定时器的最长定时时,定时器就会溢出,产生更新中断

    // 这个时候我们需要把这个最长的定时周期加到捕获信号的时间里面去

    if ( TIM_GetITStatus ( GENERAL_TIM, TIM_IT_Update) != RESET )               

    {    

        TIM_ICUserValueStructure.Capture_Period ++;        

        TIM_ClearITPendingBit ( GENERAL_TIM, TIM_FLAG_Update );         

    }

 

    // 上升沿捕获中断

    if ( TIM_GetITStatus (GENERAL_TIM, GENERAL_TIM_IT_CCx ) != RESET)

    {

        // 第一次捕获

        if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 )

        {

            // 计数器清0

            TIM_SetCounter ( GENERAL_TIM, 0 );

            // 自动重装载寄存器更新标志清0

            TIM_ICUserValueStructure.Capture_Period = 0;

      // 存捕获比较寄存器的值的变量的值清0            

            TIM_ICUserValueStructure.Capture_CcrValue = 0;

 

            // 当第一次捕获到上升沿之后,就把捕获边沿配置为下降沿

            GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Falling);

      // 开始捕获标准置1            

            TIM_ICUserValueStructure.Capture_StartFlag = 1;            

        }

        // 下降沿捕获中断

        else // 第二次捕获

        {

            // 获取捕获比较寄存器的值,这个值就是捕获到的高电平的时间的值

            TIM_ICUserValueStructure.Capture_CcrValue = 

            GENERAL_TIM_GetCapturex_FUN (GENERAL_TIM);

 

            // 当第二次捕获到下降沿之后,就把捕获边沿配置为上升沿,好开启新的一轮捕获

            GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Rising);

      // 开始捕获标志清0        

            TIM_ICUserValueStructure.Capture_StartFlag = 0;

      // 捕获完成标志置1            

            TIM_ICUserValueStructure.Capture_FinishFlag = 1;        

        }

 

        TIM_ClearITPendingBit (GENERAL_TIM,GENERAL_TIM_IT_CCx);        

    }        

}

     6. 主函数,计算脉冲宽度利用串口输出

         int main()

{

        uint32_t time;

    

    // TIM 计数器的驱动时钟

    float TIM_PscCLK = 72000000.0 / (GENERAL_TIM_PSC+1);

    

    USART_Config();

    GeneralTim_Init();

        

    printf("rn ----输入捕获测量脉宽实验----rn");

    while(1)

    {

        if(TIM_ICUserValueStructure.Capture_FinishFlag == 1)

        {

            time = (TIM_ICUserValueStructure.Capture_Period * (GENERAL_TIM_PERIOD + 1)

            + TIM_ICUserValueStructure.Capture_CcrValue + 1);

            

            printf("t=%fn",time/TIM_PscCLK);

            TIM_ICUserValueStructure.Capture_FinishFlag = 0;

            

        }

        

    }

}

 

   

  7. 相关宏定义      

#define            GENERAL_TIM                   TIM5

#define            GENERAL_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd

#define            GENERAL_TIM_CLK               RCC_APB1Periph_TIM5

#define            GENERAL_TIM_PERIOD            0XFFFF

#define            GENERAL_TIM_PSC              (72-1)

 

// TIM 输入捕获通道GPIO相关宏定义

#define            GENERAL_TIM_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA

#define            GENERAL_TIM_CH1_PORT          GPIOA

#define            GENERAL_TIM_CH1_PIN           GPIO_Pin_0

#define            GENERAL_TIM_CHANNEL_x         TIM_Channel_1

 

// 中断相关宏定义

#define            GENERAL_TIM_IT_CCx            TIM_IT_CC1

#define            GENERAL_TIM_IRQ               TIM5_IRQn

#define            GENERAL_TIM_INT_FUN           TIM5_IRQHandler

 

// 获取捕获寄存器值函数宏定义

#define            GENERAL_TIM_GetCapturex_FUN                 TIM_GetCapture1

// 捕获信号极性函数宏定义

#define            GENERAL_TIM_OCxPolarityConfig_FUN           TIM_OC1PolarityConfig

 

// 测量的起始边沿

#define            GENERAL_TIM_STRAT_ICPolarity                TIM_ICPolarity_Rising

// 测量的结束边沿

#define            GENERAL_TIM_END_ICPolarity                  TIM_ICPolarity_Falling

 

 

// 定时器输入捕获用户自定义变量结构体声明

typedef struct

{   

    uint8_t   Capture_FinishFlag;   // 捕获结束标志位

[1] [2]
关键字:STM32F103  通用定时器  输入捕获  脉冲宽度 引用地址:STM32F103_通用定时器“输入捕获”测量输入脉冲宽度

上一篇:STM32F103_ADC单通道电压采集中断读取初始化配置步骤
下一篇:STM32F103_SD卡FatFs文件系统移植

推荐阅读最新更新时间:2024-11-13 20:25

基于stm32f103zet6的RTC学习
RTC配置 一、秒中断的配置,RTC就是一个定时器而已,没什么大不了的! 1、NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_PriorityGroup,: specifies the priority grouping bits length. This parameter can be one of the following values: NVIC_PriorityGroup_0: 0 bits for pre-emption priority 4 bits for subpriority NVIC_PriorityGroup_1: 1 bits for pre-e
[单片机]
STM32之通用定时器编码器模式
1、编码器原理 如果两个信号相位差为90度,则这两个信号称为正交。由于两个信号相差90度,因此可以根据两个信号哪个先哪个后来判断方向、根据每个信号脉冲数量的多少及整个编码轮的周长就可以算出当前行走的距离、如果再加上定时器的话还可以计算出速度。 2、为什么要用编码器 从上图可以看出,由于TI,T2一前一后有个90度的相位差,所以当出现这个相位差时就表示轮子旋转了一个角度。但有人会问了:既然都是脉冲,为什么不用普通IO中断?实际上如果是轮子一直正常旋转当然没有问题。仔细观察上图,如果出现了毛刺呢?这就是需要我们在软件中编写算法进行改正。于是,我们就会想到如果有个硬件能够处理这种情况那不是挺好吗? 3、stm32编码器
[单片机]
STM32之<font color='red'>通用</font><font color='red'>定时器</font>编码器模式
基于STM32F103VCT6单片机的微位移控制系统设计
为实现X-Y-Z三维工作台的精确定位,设计了一种基于STM32F103VCT6单片机和步进电机的三维微位移控制系统。该系统可与上位机实现串口通信,接收上位机命令并把处理结果反馈给上位机;根据光栅传感器提供的位置反馈信息,系统可以通过对步进电机的方向、速度调节来实现精确定位;采用匀加速和匀减速方式对步进电机的速度进行调节,避免了因步进电机的突然加速和急停所带来的丢步和冲击现象。控制系统的测量实验结果表明,步进电机运行平稳,噪音低,定位精度高,控制系统性能稳定可靠。 微位移控制系统是一种集机械、光学、电子和计算机等多种技术于一体的智能化仪器。在先进制造技术与科学研究中有着极其广泛的应用,也是现代工业检测、质量控制和制造技术
[单片机]
基于<font color='red'>STM32F103</font>VCT6单片机的微位移控制系统设计
两种方法实现STM32F103向串口一直发送数据
串口是STM32最为重要的资源,在平时的硬件调试和软件调试中都是不可或缺的工具,最近在测试一块板子的通信功能是否正常,我打算用板子A的串口USART1一直向串口发送数据,用板子B的串口1接收数据,并将接收到的数据经过处理后显示在LCD液晶上。所以就写了下面的串口发送程序,发送的是数组函数。 Main.c #include led.h #include delay.h #include key.h #include sys.h #include usart.h u8 USART_fasong_Buf ={12,35,00,12,12,34,90,00}; // 接收缓冲区字节长度200 //u16 res=9; v
[单片机]
精英STM32F103开发板试用体验:+OLED屏显示功能的实现
鉴于STM32F103开发板没有配置显示屏,因此要显示一些信息除了借助串行通讯,就必须为其添加相应的显示器件了。在初步掌握GPIO口的基础上,最好是以OLED屏为显示器件。 OLED屏有多种类型,按色彩分有单色屏、双色屏及彩色屏;按接口方式分有并口屏、SPI接口屏及IIC接口屏。这里所选用的IIC接口的双色OLED屏,该显示屏在工作时只需占用2个GPIO口,所以该器件很有特色,图1是其显示效果。 图1OLED屏显示效果 在STM32F103开发板所配的光盘中,也有OLED屏显示例程但它是并口屏,并与OV7670摄像头共用同一接口,其接口的原理图如图2所示。 图2接口原理图 在IIC接口的使用方式中,我们只用到PC0和
[单片机]
精英<font color='red'>STM32F103</font>开发板试用体验:+OLED屏显示功能的实现
STM32 通用定时器
STM32 的定时器功能十分强大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5 等通用定时器,还有 TIME6 和TIME7 等基本定时器。 STM32 的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成。STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。 STM3 的通用 TIMx (TIM2、TIM3、TIM4 和 TIM5)定
[单片机]
si4438使用stm32f103配置调试成功!
刚拿到si4438时候在网上找了一大波资源,发现能使用的并没有多少,于是自己配置一发。经过不懈努力配置成功,现在将一些配置过程分享给大家!源码已上传。尽情下载! 1.首先打开工程文件,app下的si4438即是驱动si4438的一些库函数,都已经封装完成,只需要直接使用即可。 2.si4438在接受到数据时会IRQ引脚会产生下降沿,需要将接IRQ引脚的单片机IO配置为下降沿中断才行,当进入中断时通过自定义函数(在.c文件中)读取接收的包,接受的数据存到数组中,只需要定义一个数据,取出数据即可。 3.spi配置:使用硬件的spi,速率不能超过200khz,nss引脚配置成软件管理,读取数据从第二个时钟沿开始读取数据。
[单片机]
stm32f103系列芯片P15端口当做普通IO使用
在调试板子时发现在PA15口上无论输出高还是低都只有一个电平3.3V,后来搞得程序都下不了,如果是禁用了端口,可以参考我的博客 下面上整个代码,实测可以,就是不能进行仿真 在示波器上可以看到,电平不断变化。 #include stm32f10x.h #include bsp_usart.h void delay_ms(u16 time) { u16 i=0; while(time--) { i=12000; while(i--); } } void Relay_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStruc
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved