检测NE555脉冲发生器产生的频率

举报
DS小龙哥 发表于 2024/07/24 09:30:15 2024/07/24
【摘要】 在许多工业应用、机械控制以及实验设备中,准确测量和监控信号的频率或转速是确保系统正常运行、提高生产效率以及实现精确控制的关键。频率作为信号的基本参数之一,直接反映了信号的变化速率,而转速则通常通过测量旋转物体的频率来间接获得。

一、前言

1.1 功能介绍

在许多工业应用、机械控制以及实验设备中,准确测量和监控信号的频率或转速是确保系统正常运行、提高生产效率以及实现精确控制的关键。频率作为信号的基本参数之一,直接反映了信号的变化速率,而转速则通常通过测量旋转物体的频率来间接获得。

为了实现对频率和转速的精确测量,本项目采用了STC90C51微控制器,结合定时器和外部中断技术,检测NE555脉冲发生器产生的脉冲信号频率。NE555作为一种广泛使用的模拟定时器芯片,能够通过配置外部电阻和电容参数产生稳定的脉冲信号,其频率可根据需要进行调整。因此,利用NE555脉冲发生器可以模拟不同频率的输入信号,用于测试STC90C51的频率测量功能。

在项目中,STC90C51微控制器通过定时器设置合适的计时周期,并利用外部中断捕捉NE555脉冲信号的上升沿或下降沿。通过记录定时器计数值和中断触发次数,可以计算出输入信号的频率。此外,根据项目需求,还可以进一步将频率信息转换为转速值,实现转速的精确测量和监控。

本项目的开发背景体现了对精确频率测量和转速监控技术的迫切需求。通过结合STC90C51微控制器和NE555脉冲发生器的技术优势,本项目实现一种高效、精确的频率和转速测量系统。该系统不仅可以用于工业生产和机械控制等领域,还可以为科学实验和教学提供有力的支持。同时,本项目的实施还将促进微控制器和定时器技术在信号处理和控制领域的应用和发展。

image-20240612133113647

image-20240612133129609

1.2 NE555介绍

NE555是一款经典的集成电路,属于555系列定时器芯片的一种型号,在1971年由Signetics Corporation发布。作为一款多功能的定时器芯片,NE555在电子领域有着广泛的应用,包括脉冲信号发生、定时控制、波形产生等场景。

  1. 基本功能

    • NE555可以作为一个脉冲发生器,通过外部电阻和电容的配置,产生稳定的脉冲信号。
    • 它还广泛应用于定时器、频率计、脉宽调制(PWM)等电子电路中。
  2. 主要特点

    • 设计简单:NE555的设计使其易于使用,且具备稳定可靠的性能。
    • 操作电源范围广:操作电源范围极大,可以与TTL、CMOS等逻辑电路配合,输出电平及输入触发电平,均能与这些系列逻辑电路的高、低电平匹配。
    • 高精度与稳定性:计时精确度高、温度稳定度佳,且价格便宜。
    • 强输出能力:输出端的供给电流大,可直接推动多种自动控制的负载。
  3. 工作原理

    • NE555的工作原理主要涉及到两个阶段:充电和放电阶段。通过内部的电压比较器和控制放大器,以及RS触发器,根据触发阈值和复位阈值的比较结果,使触发器内部的RS锁存器和复位触发器状态发生变化,从而改变输出电平。
    • 在充放电过程中,电容的充电和放电时间可以根据外部电路的设计进行控制,从而实现不同的计时和脉冲频率。
  4. 引脚功能

    • NE555是8脚时基集成电路,各引脚功能包括地线、触发点、输出、重置、控制、重置锁定、放电和正电源电压端。这些引脚允许用户通过外部电路配置来实现各种功能。
  5. 市场应用

    由于其稳定度高、精度高、温度稳定性好等优点,NE555在市场上非常受欢迎。主流品牌如TI、ST等都有生产,并且广泛应用于各种电子设备中。

NE555是一款功能强大、设计简单、稳定可靠的集成电路芯片,其作为脉冲发生器在电子领域有着广泛的应用,特别是在需要精确控制时间、频率和脉冲宽度的场景中。

二、代码实现

2.1 main.c

#include <reg51.h>
#include <INTRINS.H>
#include "delay.h"
#include "type.h"
#include "uart.h"
#include "ds1302.h"
#include "pcf8591.h"
//#include "key.h"
//#include "led.h"
#include "timer.h"
//#include "exti.h"
//#include "infrared.h"
//#include "ds18b20.h"
//#include "at24c02.h"

u32 time1_cnt=0; //记录计数器1收到的外部脉冲数量
u32 time0_cnt=0; //记录定时器0的超时时间次数
u32 Freq=0;
int main()
{
    Timer0_16bit_Init(50000); //初始化定时器0,定时50ms一次
    Timer1_16bit_CntMode_Init(); //初始化计数器1
    while(1)
    {
        if(TR0==0) //当定时器0停止时,表示1秒钟时间到达
        {
            Freq=time1_cnt+(TH1<<8|TL1); //得到1秒钟内计算的脉冲数
            time1_cnt=0;//清除脉冲计数
            TH1=0; //将计数器的值清零
			TL1=0;
            TR0=1; //开启定时器0
            TR1=1; //开启计数器1
        }
        LED_DisplayNumber(Freq);
    }
}

2.2 timer.c

#include "timer.h"
/*
配置定时器0工作在16位定时器模式
51单片机标准架构下一个机器周期是 12个时钟周期,也就是12/11059200秒。(11.059200是晶振频率)
定时器每过一个机器周期的时间,也就是12/11059200秒,计数器自动加1。
通过计算得知,定时器+1的时间: 12/11.059200=1.085069us
如果定时器工作在16位模式下,最大值可以存放:0~65535
那么最大的定时时间就可以得知:65535*1.085069=71,109.996915us=71.109996915ms
如果要定时1000us,那么公式:x*1.085069=1000 ->1000/1.085069=921  ,
通过公式,计算出定时器需要+921次刚好得到1000us。
但是单片机工作在16位模式情况下,需要加满65535才能溢出,所以需要给定时器赋初值。
65535-921=64614,这样定时器就可以从64614开始计数,当计数到65535时,定时器就会溢出,
TF0就会置1,这时刚好经过1000us时间。
那么定时器就可以这样赋值:
u16 t0_data=64614;
TH0=t0_data>>8;
TL0=t0_data;
*/
u16 T0_Update_data;//定时器0的初始值
void Timer0_16bit_Init(u16 us)
{   
    //当前实验板上的晶振实际频率为: 12MHZ
    u16 val=us/(12/12); //得到计数的时间,只要整数部分
    T0_Update_data=65535-val; //得到重装载值
    TMOD&=0xF0;		//清除配置
    TMOD|=0x01;     //配置定时器0工作在16位定时器模式
    TH0=T0_Update_data>>8; //定时器0高位重装值
    TL0=T0_Update_data;    //定时器0低位重装值
    EA=1;                  //开启总中断
    ET0=1;                 //开启定时器0溢出中断
    TR0=1;                 //开启定时器0
}

//定时器0的重装值更新函数
void Timer0_Update(void)
{
    TH0=T0_Update_data>>8; //定时器0高位重装值
    TL0=T0_Update_data;    //定时器0低位重装值
}

u16 T1_Update_data;//定时器1的初始值
void Timer1_16bit_Init(u16 us)
{   
    //当前实验板上的晶振实际频率为: 11.956MHZ
    u16 val=us/(12/11.956); //得到计数的时间,只要整数部分
    T1_Update_data=65535-val; //得到重装载值
    TMOD&=0x0F;		       //清除配置
    TMOD|=0x10;            //配置定时器1工作在16位定时器模式
    TH1=T1_Update_data>>8; //定时器1高位重装值
    TL1=T1_Update_data;    //定时器1低位重装值
    EA=1;                   //开启总中断
    ET1=1;                  //开启定时器1溢出中断
    TR1=1;                 //启动定时器1
}

//定时器1的重装值更新函数
void Timer1_Update(void)
{
    TH1=T1_Update_data>>8; //定时器1高位重装值
    TL1=T1_Update_data;    //定时器1低位重装值
}

/*
配置定时器0工作在8位自动重装载模式
注意,时间不能超过定时器最大时间
255*(12/11.059200)=276us
*/
void Timer0_8bit_Init(u16 us)
{   
    //当前实验板上的晶振实际频率为: 11.956MHZ
    u16 val=us/(12/11.956); //得到计数的时间,只要整数部分
    TMOD&=0xF0;		//清除配置
    TMOD|=0x02;     //配置定时器0工作在8位自动重载模式
    TL0=TH0=255-val;//得到重装载值;
    EA=1;           //开启总中断
    ET0=1;          //开启定时器0溢出中断
    TR0=1;          //启动定时器0
}


/*
配置定时器1初始化为16位计数器模式
*/
void Timer1_16bit_CntMode_Init(void)
{   
    //当前实验板上的晶振实际频率为: 12MHZ
    TMOD&=0x0F; //清除配置
    TMOD|=0x50; //配置定时器1工作在16位计数器模式
    EA=1;       //开启总中断
    ET1=1;      //开启定时器1溢出中断
    TR1=1;      //启动定时器1
}

extern u32 time1_cnt; //记录计数器1收到的外部脉冲数量
extern u32 time0_cnt; //记录定时器0的超时时间次数

/*
定时器0的中断服务函数
*/
void TIM0_IRQHandler(void) interrupt 1
{
    time0_cnt++;
    //定时器0配置50ms超时一次,超时次数到达20次表示1秒钟时间到达
    if(time0_cnt==20)
    {
        time0_cnt=0;
        TR0=0; //关闭定时器0
		TR1=0; //关闭计数器1
    }
    Timer0_Update(); //定时器0的重装载
}

/*
定时器1的中断服务函数
*/
void TIM1_IRQHandler(void) interrupt 3  //定时器1
{
    //当前计数器配置为16位模式,进入一次中断就表示计数了65536次
    time1_cnt+=65536; 
}

2.3 timer.

#ifndef TIMER_H
#define TIMER_H
#include <reg51.h>
#include "delay.h"
#include "key.h"
#include "type.h"
#include "led.h"
#include "uart.h"
void Timer0_16bit_Init(u16 us);
void Timer0_Update(void);
void Timer1_16bit_Init(u16 us);
void Timer1_Update(void);
void Timer0_8bit_Init(u16 us);
void Timer1_16bit_CntMode_Init(void);
#endif
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。