历史上的今天
返回首页

历史上的今天

今天是:2024年10月28日(星期一)

正在发生

2021年10月28日 | stm32专题二十六:输入捕获 脉宽测量

2021-10-28 来源:eefocus

硬件设计:

脉宽测量原理:


当按键没有按下时,由硬件电路自动拉低。如果按键按下,则PA0产生上升沿,我们进行脉宽测量时,首先设置为上升沿捕获,然后在第一次捕获到上升沿时,将计数器清零,并设置捕获极性为下降沿捕获。当第二次捕获到信号时,就是一个完整的高电平时间。值得注意的是,如果定时器溢出频率为72M(预分频系数71)时,最大计数值为65536us,要考虑溢出(更新中断)。


代码如下,非常简单。


bsp_GeneralTim.c


#include "bsp_GeneralTim.h"

 

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

TIM_ICUserValueTypeDef TIM_ICUserValueStructure = {0, 0, 0, 0};

 

// 中断优先级配置

static void GENERAL_TIM_NVIC_Config(void)

{

    NVIC_InitTypeDef NVIC_InitStructure; 

    // 设置中断组为0

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

// 设置中断来源

    NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQ ;

// 设置主优先级为 0

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  

  // 设置抢占优先级为3

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

}

 

static void GENERAL_TIM_GPIO_Config(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

 

  // 输入捕获通道 GPIO 初始化

RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);

  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM_CH1_PIN;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);

}

 

static void GENERAL_TIM_Mode_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);

}

 

void GENERAL_TIM_Init(void)

{

GENERAL_TIM_NVIC_Config();

GENERAL_TIM_GPIO_Config();

GENERAL_TIM_Mode_Config();

}

bsp_GeneralTim.h


#ifndef __BSP_ADVANCETIM_H

#define __BSP_ADVANCETIM_H

 

#include "stm32f10x.h"

 

/************通用定时器TIM参数定义,只限TIM2、3、4、5************/

// 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意

// 我们这里默认使用TIM5

 

#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;   // 捕获结束标志位

uint8_t   Capture_StartFlag;    // 捕获开始标志位

uint16_t  Capture_CcrValue;     // 捕获寄存器的值

uint16_t  Capture_Period;       // 自动重装载寄存器更新标志 

}TIM_ICUserValueTypeDef;

 

extern TIM_ICUserValueTypeDef TIM_ICUserValueStructure;

 

/**************************函数声明********************************/

void GENERAL_TIM_Init(void);

 

 

#endif /* __BSP_ADVANCETIM_H */

以上是一些结构体配置,然后比较重要的是中断服务函数:


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

}

}

在主函数中进行测试:


main.c


#include "stm32f10x.h"

#include "bsp_led.h"

#include "bsp_usart.h"

#include "bsp_GeneralTim.h"

#include

 

void delay(uint32_t count);

 

int main(void)

{

uint32_t time;

// TIM 计数器的驱动时钟

uint32_t TIM_PscCLK = 72000000 / (GENERAL_TIM_PSC + 1);

/* 串口初始化 */

USART_config();

 

GENERAL_TIM_Init();

printf ( "STM32 输入捕获测试rn" );

printf ( "按下K1,测试K1按下的时间rn" );

while (1)

{

if(TIM_ICUserValueStructure.Capture_FinishFlag == 1)

{

// 计算高电平时间的计数器的值

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

       (TIM_ICUserValueStructure.Capture_CcrValue+1);

// 打印高电平脉宽时间

printf ( "rn测得高电平脉宽时间:%d.%d srn",time/TIM_PscCLK,time%TIM_PscCLK );

TIM_ICUserValueStructure.Capture_FinishFlag = 0;

}

}

}


测试结果为:

推荐阅读

史海拾趣

ERP Power公司的发展小趣事

在这个故事中,我们将关注ERP Power在国际市场的拓展情况。通过与国际知名企业的合作和交流,ERP Power系统成功打入国际市场并获得了广泛认可。这一过程中,ERP Power不仅提升了自身的技术实力和服务水平还积累了丰富的国际化经验。

Belkin公司的发展小趣事

贝尔金的成功不仅仅局限于美国本土。随着全球市场的不断扩张,贝尔金也在全球范围内建立了广泛的销售网络和物流中心。位于加州洛杉矶的总部、好莱坞的工业设计中心以及纽约州罗切斯特的研发机构,共同构成了贝尔金全球业务的核心。这些机构之间的紧密合作,确保了贝尔金能够迅速响应全球市场的需求,提供高品质的产品和服务。

创世(CS)公司的发展小趣事

在电子行业中,品质控制和质量管理是企业生存和发展的关键。创世公司深知这一点,始终将品质放在首位。公司建立了严格的质量管理体系,从原材料采购到生产制造、产品检测等各个环节都严格把控品质。同时,创世公司还引进了先进的生产设备和检测仪器,确保产品的可靠性和稳定性。这种对品质的执着追求使得创世公司的产品在市场上获得了良好的口碑和广泛的认可。

Herley New York公司的发展小趣事

创世公司在SD NAND存储产品的研发过程中,不断突破技术壁垒,实现了产品的创新。例如,2018年,为满足轨道交通、航空航天、工业控制等行业类客户对存储产品的特殊需求,创世公司首家推出了第二代SD NAND产品。这一产品不仅具有更快的读写速度和更宽泛的使用环境,还能承受高低温冷热冲击、随机掉电等苛刻的操作环境。同时,创世公司还为客户提供个性化的固件定制服务,进一步满足了客户的个性化需求。

FUJIKURA公司的发展小趣事

创世公司在SD NAND存储产品的研发过程中,不断突破技术壁垒,实现了产品的创新。例如,2018年,为满足轨道交通、航空航天、工业控制等行业类客户对存储产品的特殊需求,创世公司首家推出了第二代SD NAND产品。这一产品不仅具有更快的读写速度和更宽泛的使用环境,还能承受高低温冷热冲击、随机掉电等苛刻的操作环境。同时,创世公司还为客户提供个性化的固件定制服务,进一步满足了客户的个性化需求。

高博(GBG)公司的发展小趣事

在半导体领域,技术创新是企业持续发展的关键。谷峰公司深知这一点,不断加大研发投入,致力于新技术的研发与应用。其中,SGT(Super Junction Technology)技术的成功研发,是谷峰发展历程中的一个重要里程碑。SGT技术以其低内阻、高效率的特点,成为高频应用的理想选择,极大地提升了谷峰产品的市场竞争力。此外,谷峰还推出了多款高性能的碳化硅MOSFET产品,进一步巩固了其在功率半导体领域的领先地位。

问答坊 | AI 解惑

C8051单片机原理及应用

C8051单片机原理及应用…

查看全部问答>

运算放大器、比较器设计指南

运算放大器、比较器设计指南 第十四版 运算放大器、比较器设计指南 第十六版…

查看全部问答>

100M示波器到手了,用起来超爽

本信息来自合作QQ群:AVR单片机学习与交流群(17727270) 群管理员在坛子里的ID:铜河 100M、4通道,2G采样,25k记录 据说,这个虽然是100M,但实测是200M…

查看全部问答>

求助各位大仙高手指点一下,如何在wince下实现放截屏的功能!非常感谢!

求助各位大仙高手指点一下,如何在wince下实现 防截屏 的功能!非常感谢!…

查看全部问答>

程序在执行扫描时老是在一个地方进行判断该怎么办

大家好,我的程序(不是自己写的)在执行判断扫描时老是停留在一个地方,怎么办? 程序段如下: main: nop nop nop        mov wdt_contr,#00111110B  ;喂狗              ...…

查看全部问答>

2440 CAMERA CODE DMA地址在CONFIG.BIB中设置的疑惑?

我的CONFIG.BIB一段如下: MEMORY ;NK         NK  8C200000  01D00000  RAMIMAGE ;RAM         RAM         8E800000  0 ...…

查看全部问答>

请教运算放大器的使用问题

我现在用一个运算放大器调整单片机的采样信号.放大器的型号为LF412,资料里电源连接方式是双电源供电,如接+/-15v,由于我现在的输入信号只有正的.我把负电源接地,正电源接+15v,请问这样做行吗?…

查看全部问答>

大家觉得这个4*4键盘扫描程序怎样,我修改了一点点。

这个程序不是原创的,但是我修改了一点点,理解起来轻松了很多。大家觉得怎样,如果有较好的不妨拿出来分享讨论一下吧 !                   & ...…

查看全部问答>

稳压管的用法

打算通过24V直流 串个10K电阻 然后再通过个5V稳压管接地,最后在稳压管2端取得一个接近5V的稳定电压,可行否? 稳压管要如何选择其参数,请赐教…

查看全部问答>

06.23【每周讨论】我们年轻,富有正义。对于社会中的不文明现象该怎样看待呢?

06.23【每周讨论】年轻的我们,富有正义、满怀激情。对于社会中的不文明现象该怎样看待呢?我们年轻人,富有正义、满怀激情,眼里容不下一粒沙。社会中那些不文明的现象经常在我们的周围发生,却让我们感到无可奈何。若为此感到懊恼的话,那你永远 ...…

查看全部问答>