用STM32F107单片机的外部中断对脉冲信号计数,脉冲信号频率略高,计数就变少,为啥?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用STM32F107单片机的外部中断对脉冲信号计数,脉冲信号频率略高,计数就变少,为啥?相关的知识,希望对你有一定的参考价值。

这个脉冲信号为20HZ的时候,还能准确计数,但是200HZ的时候,计数变少了。STM32不可能连这么点频率的脉冲都处理不了吧,求指教

嘿嘿 俺来帮你解答
用 外部中断对脉冲信号计数造成丢失脉冲的原因:
1 脉冲信号频率过高 超过外部中断对脉冲信号的处理速度
2 系统其它中断会造成影响 会延迟外部中断对脉冲信号的处理时间
3 外部中断对脉冲信号的处理程序如果比较长 执行时间也长 也会影响外部中断对脉冲信号的处理速度
建议:
1 将对脉冲信号计数的外部中断的优先级设成高级中断
2 外部中断对脉冲信号的处理程序要尽量想办法缩短
3 当然建议最好使用计数器 每当计满 才中断1次 就不会丢失脉冲了
STM32F107单片机内部可是有4个定时计数器啊

呵呵 满意就给加分吧追问

整个程序中就这一个外部中断,并无其他中断了。要说频率高,其实也不过200hz就出现了计数丢失现象,这个对于stm32来说说不过去啊。中断函数里面就对计数值counter++了,其他什么也没干。望解答

追答

呵呵 为什么不用计数器啊?
按理不会的 频率不算高 硬件上脉冲传感器没问题吧

追问

要求用这个,而且碰到问题总不能回避吧

追答

那很好 你是如何判断 计数时 少了多少个脉冲的?
有准确的数值吗?

追问

这个脉冲信号由光耦的相关电路产生。我把某滚轮转一圈,固定产生20个脉冲。如果转的不快,这20个脉冲都能被计数。如果转快了,计数就丢失了。。。加Q聊吧370276468

追答

脉冲信号由光耦的相关电路产生 是你设计的吗? 有可能是硬件问题

参考技术A 公司用了这个片子做的红外遥控控制,检测红外都没啥问题。
你这个情况是不是计数器已经跑溢出了。你看到的是不确定的计数。
200HZ用中断处理应该没啥问题。
你中断出了计数还有别的东西吗?
参考技术B 这个没试过,但是用外部中断计数,未免太耗单片机资源,一直中断。。不太好。。可以试试定时器。

stc89c2单片机测频

  今天做了一下51单片机的测频法(给定一定的门限时间,来测频率个数),我的大体思路是用两个中断来控制,通过定时器0,来给定一个1s的门限时间,把待测信号输入到外部中断INT0(P3^2),然后通过外部中断进入的个数来确定信号的频率,即记的个数就是待测信号的脉冲。现在我把我的程序贴出来给大家参考一下

/*================================
 程序名称 :测频
 编者     :xxniuren
 日期     :2012 11
 程序目的 :用两个时钟来定时,第一个时钟是
 外部中断INT0 第二个时钟是产生一个一秒的门信号
===============================*/
#include <reg52.h>
#include <lcd.h>
#define uchar unsigned char
#define uint unsigned int
uchar num,flag1,flag2;
long int count1,count2;
uint zhao,s_wan,wan,qian,bai,shi,ge;
uchar code table[] = "Pinlv";
//****************显示pinlv****************
 void display()

 write_com(0x80);
 for(num = 0; num < 5; num++)
  
  write_date(table[num]);
  delay_1602(5);
  

//****************显示数字****************
 
void display_date(long int date)

 zhao = date / 1000000;
 s_wan = (date % 1000000) / 100000;
 wan = (date % 100000) / 10000;
 qian = (date % 10000) / 1000;
 bai = (date % 1000) / 100;
 shi = (date % 100) / 10;
 ge  = date % 10;
 write_com(0xc0 + 3) ;
 write_date(zhao + '0');
 delay_1602(5);
 write_date(s_wan + '0');
 delay_1602(5);
 write_date(wan + '0');
 delay_1602(5);
 write_date(qian + '0');
 delay_1602(5);
 write_date(bai + '0');
 delay_1602(5);
 write_date(shi + '0');
 delay_1602(5);
 write_date(ge + '0');
 delay_1602(5);
 write_date('H');
 delay_1602(5);
 write_date('z');
 delay_1602(5);

/************
初始化外部中断
************/
void INT0_init(void)

 EA = 1;   // 打开全局中断
 EX0 = 1;  //打开外部中断0
 IT0 = 1;  //外部中断0触发 下降沿触发

/************
初始化定时器
************/
void timer0_init(void)

 TMOD = 0x01;
 TH0 = (65536 - 45872) / 256;   
 TL0 = (65536 - 45872) % 256;
 EA = 1;
 ET0 = 1;
 TR0 = 1;


void main()

 init_lcd();
    display();
    timer0_init();//先开门限时间中断
 INT0_init();  //后开外部触发中断
 while(1)
 
  display_date(count2);
 

void T0_time() interrupt 1

 TH0 = (65536 - 45872) / 256;
 TL0 = (65536 - 45872) % 256;
 num++;
 if(num == 20)
 
  num = 0;
  flag1 = 1;
 

void  INTRPT0()interrupt 0

 count1++;
 
  if(flag1 == 1)
  
    count2 = count1;
    flag1 = 0;
    count1 = 0;
  
 

这个程序相对来说容易实现,但是测频相对来说不是太准,我测的时候100hz,显示的是92hz,20khz测出来是18360hz,所以不是很准,我后来想增加测量的周期数来提高程序的精度,但是效果不是很明显。所以还是有待改善

下面把我的1602的程序也贴出来,大家可以直接拿着试一下(注意下管脚)。如果有什么好的提高频率精度的方法 希望大家指点一下,然后相互进步。。。

/*==============================================
程序名称:lcd
编者:xxniuren
日期:2012 8
程序目的:生成一个lcd的头文件 方便调用。其中程序调用方法是
初始化--定义光标坐标--使用
===============================================*/

#include <reg52.h>
#include <lcd.h>
void delay_1602(uint xms)
 
  uint i,j;
  for (i = xms; i > 0; i--)
   for(j = 110; j > 0; j--) ;
 
void write_com(uchar com)
 
  lcdrs= 0;   //先把写命令和数据设定为写命令按钮 0位命令 1为数据  0为写  1为读
  lcd_data = com;    //给P0一个数据
  delay_1602(5);   //延时5ms
  lcden = 1;    //给使能一个高电平
  delay_1602(5);  //延时5ms
  lcden = 0;  //给一个低脉冲   从而把数据传上去
 
void write_date(uchar date)
 
 lcdrs = 1;//写入数据选择
 lcd_data = date;
 delay_1602(5);
 lcden = 1;//打开使能端
 delay_1602(5);
 lcden = 0;//给一个脉冲从而输入数据
 
void init_lcd()
 
  lcden = 0;
  lcdrw = 0;
  write_com(0x38);//设置16*2显示,5*7点阵,8位数据接口
  write_com(0x0c);//设置开显示 不显示光标
 // write_com(0x06);//写一个数据后地址指针加一
  write_com(0x01);//显示清零,数据指针清零
  
 

//lcd 1602 .h

#ifndef __lcd_H__
#define __lcd_H__

#define uchar unsigned char
#define uint unsigned int
#define lcd_data P0
sbit lcden = P1^2;  //使能
sbit lcdrs = P1^0;  //数据命令选择引脚
sbit lcdrw = P1^1;     //读写选择引脚

void delay_1602(uint xms);
void write_com(uchar com);
void write_date(uchar date);
void init_lcd();

#endif

 

 

以上是关于用STM32F107单片机的外部中断对脉冲信号计数,脉冲信号频率略高,计数就变少,为啥?的主要内容,如果未能解决你的问题,请参考以下文章

关于使用STM32单片机完成脉冲计数功能的问题

STM32f407定时器用为编码器接口模式采集脉冲,但单片机供电后,复用引脚直接有电压输出

如何在 stm32f107 芯片上禁用/启用中断?

单片机外部中断有两种信号方式,即电平方式和脉冲方式.啥叫电平方式啥叫脉冲方式

怎么用stm32监控电压,当电压低于3V时给个信号计数一次。,接的是5V电,程序不用,其中要用的是单片机STM32

STM32F103外部中断编程