首页 > 编程知识 正文

stm32低频脉冲产生方法,stm32输入捕获频率范围

时间:2023-05-03 22:27:08 阅读:252785 作者:2718

输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32 的定时器,除了 bmdl6 和 bmdl7,其他定时器都有输入捕获功能。以下是对脉冲宽度及频率的计算。

1、脉冲宽度

如下图所示,采集该高电平脉冲的宽度,只需要进入输入捕获上升沿检测,记录当前的发生上升沿时的CNT值,再进行输入捕获下降沿检测,也记录当前发生下降沿时的CNT值,两次CNT值的差值再根据计数的频率就可以算出脉冲的宽度。

上升沿及下降沿捕获的程序具体实现如下:

bmdl8_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数

void bmdl8_UP_IRQHandler(void)

{

if((bmdl8CH4_CAPTURE_STA&0X80)==0) //还未成功捕获

{

if (bmdl_GetITStatus(bmdl8,bmdl_IT_Update) != RESET)

{

if(bmdl8CH4_CAPTURE_STA&0X40) //已经捕获到高电平了

{

if((bmdl8CH4_CAPTURE_STA&0X3F)==0X3F) //高电平太长了

{

bmdl8CH4_CAPTURE_STA|=0X80; //标记成功捕获了一次

bmdl8CH4_CAPTURE_VAL=0XFFFF;

}

else

bmdl8CH4_CAPTURE_STA++; //捕获高电平后定时器溢出的次数++

}

}

}

bmdl_ClearITPendingBit(bmdl8,bmdl_IT_Update); //清除中断标志位

}

void bmdl8_CC_IRQHandler(void)

{

if((bmdl8CH4_CAPTURE_STA&0X80)==0)

{

if(bmdl_GetITStatus(bmdl8,bmdl_IT_CC4) != RESET) //捕获1发生捕获事件

{

if(bmdl8CH4_CAPTURE_STA&0X40) //捕获到一个下降沿

{

bmdl8CH4_CAPTURE_STA|=0X80;//标记成功捕获到一次高电平脉宽

bmdl8CH4_CAPTURE_VAL=bmdl_GetCapture4(bmdl8);

bmdl_OC4PolarityConfig(bmdl8,bmdl_ICPolarity_Rising); //CC1P=0 设置为上升沿捕获

}

else //还未开始,第一次捕获上升沿

{

bmdl8CH4_CAPTURE_STA=0; //清空

bmdl8CH4_CAPTURE_VAL=0;

bmdl_SetCounter(bmdl8,0); //计数器清零

bmdl8CH4_CAPTURE_STA|=0X40;//标记捕获到了上升沿

bmdl_OC4PolarityConfig(bmdl8,bmdl_ICPolarity_Falling);//CC1P=1 设置为下降沿捕获

}

}

}

bmdl_ClearITPendingBit(bmdl8, bmdl_IT_CC4); //清除中断标志位

程序中定时器输入捕获配置的bmdl8CH4通道,CNT计数的频率1MHZ,即计数1个就是1us。bmdl8_UP_IRQHandler是一个定时中断函数,根据bmdl8_Cap_Init(0XFFFF,72-1)可知65536us会中断一次,所以总的脉冲宽度时间如下:

temp=bmdl8CH4_CAPTURE_STA&0X3F; //从bmdl8_UP_IRQHandler中断知中捕获上升沿及下降沿期间进行此中断的次数

temp*=65536;//溢出时间总和

temp+=bmdl8CH4_CAPTURE_VAL; //得到总的高电平时间 bmdl8CH4_CAPTURE_VAL为CNT计数的值

2、频率测量

如下图所示,测量脉冲的频率,则分别采集两次输入捕获上升沿的CNT值,脉冲的频率=f/△CNT

两次上升沿捕获的程序具体实现如下:

bmdl8_Cap_Init(0XFFFF,72-1); //以1Mhz的频率计数

void bmdl8_CC_IRQHandler(void)

{

if(bmdl_GetITStatus(bmdl8,bmdl_IT_CC4)!=RESET)

{

bmdl_ClearITPendingBit(bmdl8, bmdl_IT_CC4); //清除中断标志位

if(state==0) //捕获第一个上升沿

{

state=1;

dxhecount=bmdl_GetCapture4(bmdl8); //记录第一次上升沿的CNT值

}

else if(state==1)//捕获第二个上升沿

{

state=0;

dxhecount1=bmdl_GetCapture4(bmdl8); //记录第二次上升沿的CNT值

if(dxhecount

{

test=dxhecount1-dxhecount; //两次上升沿的差值

}

else if(dxhecount>dxhecount1)

{

test=(0xffff-dxhecount)+dxhecount1; //两次上升沿的差值

}

else

test=0;

fq=1000000/test; //脉冲的频率

}

}

}

由程序可知配置的定时器的输入捕获的计数的频率为1MHZ,两次捕获上升沿的差值test为计数器CNT计的次数,所以总的周期即为T=1us*test,所以频率就fq=1000000/test HZ;

另外,测量频率除了还可以使用定时器的外部脉冲信号计数来进行。

3、定时器的外部计数模式测频率

因为STM32有外部时钟源模式,即可以根据外部脉冲信号进行计数,然后另外设定定时器定时中断去读取计数器的值,频率=CNT/定时中断时间。程序代码实现如下:

bmdl3_Int_Init(9999,7199); //定时1s中断一次

bmdl2_Cap_Init(); //外部信号引脚脉冲检测 bmdl2_CH1_ETR

void bmdl2_Cap_Init(void) //配置 bmdl2_CH1_ETR 为外部脉冲计数

{

GPIO_InitTypeDef GPIO_InitStructure;

bmdl_TimeBaseInitTypeDef bmdl_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_bmdl2, ENABLE);//使能bmdl2时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0 清除之前设置

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0 输入

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_ResetBits(GPIOA,GPIO_Pin_0); //PA0 下拉

//初始化定时器2 bmdl2

bmdl_TimeBaseStructure.bmdl_Period = 0xFFFF; //设定计数器自动重装值

bmdl_TimeBaseStructure.bmdl_Prescaler =0; //预分频器

bmdl_TimeBaseStructure.bmdl_ClockDivision = bmdl_CKD_DIV1; //设置时钟分割:TDTS = Tck_dxh

bmdl_TimeBaseStructure.bmdl_CounterMode = bmdl_CounterMode_Up; //bmdl向上计数模式

bmdl_TimeBaseInit(bmdl2, &bmdl_TimeBaseStructure); //根据bmdl_TimeBaseInitStruct中指定的参数初始化bmdlx的时间基数单位

bmdl_ITRxExternalClockConfig(bmdl2,bmdl_TS_ETRF); //配置外部触发,否则不会计数

bmdl_ETRClockMode2Config(bmdl2, bmdl_ExtTRGPSC_OFF, bmdl_ExtTRGPolarity_NonInverted, 0);

bmdl_SetCounter(bmdl2, 0);

bmdl_Cmd(bmdl2,ENABLE ); //使能定时器2

}

/*******************************************************************************

* 名称: bmdl3_IRQHandler

* 功能: 通用定时器3中断服务函数

* 形参: 无

* 返回: 无

* 说明: 1S定时中断一次

******************************************************************************/

void bmdl3_IRQHandler(void)

{

if(bmdl_GetITStatus(bmdl3,bmdl_IT_Update)!= RESET) //检查bmdl3更新中断发生与否

{

bmdl_ClearITPendingBit(bmdl3,bmdl_IT_Update); //清除bmdlx更新中断标志

CNT=bmdl_GetCounter(bmdl2); //读取1s内计数器计的CNT值

fq=CNT; //脉冲的频率

bmdl_SetCounter(bmdl2,0);

}

}

因为知道定时中断时间为1s,所以测量的频率fq=CNT/1(HZ),频率的计算及脉冲宽度的测量有以上方法测试。

by 羊羊得亿

2017-02-24 ShenZhen

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。