4.10 51单片机-使用计数器测量NE555脉冲频率
作者:互联网
4.10 使用计数器测量NE555脉冲频率
4.10.1 原理图介绍
图4-10-1
图4-10-2
4.10.2 单片机的计数器模式介绍
STC90C51RC/RD+系列单片机内部设置的两个16位定时器/计数器T0和T1都具有计数方式和定时方式两种工作方式。对每个定时器/计数器(T0和T1),在特殊功能寄存器TMOD中都有一控制-C/T来选择T0或者T1为定时器还是计数器。定时器/计数器的核心部件是一个加法计数器,其本质是对脉冲进行计数。只是计数脉冲来源不同:如果计数脉冲来自系统时钟,则为定时方式,此时定时器/计数器每12个时钟或者每6个时钟得到一个计数脉冲,计数值加1;如果计数脉冲来自单片机外部引脚(T0为P3.3,T1为P3.3),则为计数方式,每来一个脉冲加1。
图4-10-3
4.10.3 NE555定时器介绍
555定时器是一种集成电路芯片,常被用于定时器、脉冲产生器和振荡电路。555可被作为电路中的延时器件、触发器或起振元件。
555定时器可工作在三种工作模式下:
单稳态模式:在此模式下,555功能为单次触发。应用范围包括定时器,脉冲丢失检测,反弹跳开关,轻触开关,分频器,电容测量,脉冲宽度调制(PWM)等。
无稳态模式:在此模式下,555以振荡器的方式工作。这一工作模式下的555芯片常被用于频闪灯、脉冲发生器、逻辑电路时钟、音调发生器、脉冲位置调制(PPM)等电路中。如果使用热敏电阻作为定时电阻,555可构成温度传感器,其输出信号的频率由温度决定。
双稳态模式(或称施密特触发器模式):在DIS引脚空置且不外接电容的情况下,555的工作方式类似于一个RS触发器,可用于构成锁存开关。
4.10.4 示例代码
下面代码里,配置定时器1为16位计数器模式并开启计数中断;NE555脉冲发生器接在单片机的P3.3引脚输入脉冲,通过定时器1进行计数。再配置定时器0为16位定时器模式,50毫秒超时一次,在中断服务函数里记录超时的次数,当超时20次表示1秒钟时间到达。1秒钟时间到达之后,在定时器0的中断服务函数里关闭定时器0和计数器1。在主函数里判断计数器是否停止,如何计数器停止就表示1秒钟时间到达,之后就读取1秒钟之内计数器1记录的脉冲数量,通过数码管进行显示。
用总脉冲量/总时间,就可以得出脉冲的周期。
示例代码:
#include <reg51.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); //显示脉冲个数
}
}
//共阴极数码管编码(要显示的段就输出1)
//数字0~9
code u8 LED2_Coding[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//定义38译码器的引脚
sbit HC138_A0=P2^2; //A
sbit HC138_A1=P2^3; //B
sbit HC138_A2=P2^4; //C
#define LED P0 //定义LED引脚
//设置数码管显示指定的数字
void LED_DisplayNumber(unsigned long number)
{
u16 i,j;
u8 display_data[8];//存放当前数码管显示的数据
//以下代码将number按十进制位从低到高依次提取并转为数码管显示字符
display_data[0] = LED2_Coding[number/10000000%10];
display_data[1] = LED2_Coding[number/1000000%10];
display_data[2] = LED2_Coding[number/100000%10];
display_data[3] = LED2_Coding[number/10000%10];
display_data[4] = LED2_Coding[number/1000%10];
display_data[5] = LED2_Coding[number/100%10];
display_data[6] = LED2_Coding[number/10%10];
display_data[7] = LED2_Coding[number/1%10];
for(i=0;i<8;i++)
{
switch(i) //位选,选择点亮的数码管,
{
case 0:
HC138_A0=0;HC138_A1=0;HC138_A2=0; break;//显示第0位
case 1:
HC138_A0=1;HC138_A1=0;HC138_A2=0; break;//显示第1位
case 2:
HC138_A0=0;HC138_A1=1;HC138_A2=0; break;//显示第2位
case 3:
HC138_A0=1;HC138_A1=1;HC138_A2=0; break;//显示第3位
case 4:
HC138_A0=0;HC138_A1=0;HC138_A2=1; break;//显示第4位
case 5:
HC138_A0=1;HC138_A1=0;HC138_A2=1; break;//显示第5位
case 6:
HC138_A0=0;HC138_A1=1;HC138_A2=1; break;//显示第6位
case 7:
HC138_A0=1;HC138_A1=1;HC138_A2=1; break;//显示第7位
}
LED=display_data[i]; //控制数码管的显示数据值
j = 100; //扫描间隔时间设定
while(j--){}
LED=0x00; //消隐,所有数码管都不显示
}
}
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低位重装值
}
/*
配置定时器1初始化为16位计数器模式
*/
void Timer1_16bit_CntMode_Init(void)
{
//当前实验板上的晶振实际频率为: 12MHZ
TMOD&=0x0F; //清除配置
TMOD|=0x50; //配置定时器1工作在16位计数器模式
EA=1; //开启总中断
ET1=1; //开启定时器1溢出中断
TR1=1; //启动定时器1
}
/*定时器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;
}
标签:4.10,定时器,NE555,555,void,脉冲,51,计数,计数器 来源: https://blog.csdn.net/xiaolong1126626497/article/details/121031919