首先,NE555定时器的名字,来源于NE555内部存在三个5KΩ的电阻分压。NE555是一个纯硬件的设计,一旦硬件电路确定了就没有可编程的部分。NE555在电子电路设计中得到广泛应用,例如用作时钟电路、脉冲发生器、脉冲宽度调制器等。
NE555有多种工作模式,但最常见的是单稳态和振荡器模式。
在单稳态模式下,NE555可以产生一个短暂的单脉冲信号。当触发端(TRIG)接收到一个低电平脉冲时,输出端(OUT)产生一个高电平脉冲,持续时间由外部的电阻和电容决定。
在振荡器模式下,NE555可以产生稳定的方波信号。通过调节外部的电阻和电容值,可以控制输出信号的频率和占空比。
在蓝桥杯的板子上我们要使用的就是振荡器模式,通过拧电阻器RB3来改变控制输出信号的频率。
所谓频率,就是在单位时间内的周期数。NE555定时器的频率的单位是Hz。那么就需要用两个定时器,一个定时器负责计时1s,另一个定时器负责在这一秒内计数。结合单片机引脚的原理图和NE555定时器的原理图我们可以看到,NE555定时器的输出脚时P3.4,刚好是定时器T0的脚,那么我们就用定时器T0来计数,定时器T1来计时。
用跳线帽将板子右侧排针的SIGNAL引脚和P3.4进行短接,也就是将NE555发生的信号输入到单片机P3.4引脚。调节电阻器RB3来调节信号的频率,将频率数据用数码管进行显示,最左边的数码管显示频率的缩写“F”进行标识。
#include
#include "Delay_ms.h"
unsigned int count_f = 0; // 测得频率
unsigned int last_count_f = 0; // 频率传递
unsigned char i = 0; // 计数值
// 不加 “code” 会影响单片机运行速度,会改变RAM,加了 code 之后內容就固定不变了,不会占用RAM
unsigned char code SMG_Duanma[19] =
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0x00
}; // 0~F - . 全部
// 带点显示的数
unsigned char code SMG_Dian[10] =
{
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10
}; // 0.~9.
// 通道选择函数
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = (P2 & 0x1f) | 0x00; // 0
break;
case 4:
P2 = (P2 & 0x1f) | 0x80; // Y4C
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; // Y5C
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; // Y6C
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; // Y7C
break;
}
}
// 初始化系统
void System_Init(void)
{
// 关闭LED灯
HC138_Init( 4 );
P0 = 0xff;
// 关闭蜂鸣器和继电器
HC138_Init( 5 );
P0 = 0xaf; // 1010 1111
// 关闭通道选择
HC138_Init( 0 );
}
void Delay_tms( unsigned int t )
{
int i;
while( t-- )
{
for( i=115 ; i>0 ; i-- )
{}
}
}
// 数码管显示
void SMG_Light( unsigned char pos , unsigned char dat)
{
HC138_Init( 6 );
P0 = 0x01 << pos;
HC138_Init( 7 );
P0 = dat;
}
// 数码管动态显示
void SMG_Show(void)
{
SMG_Light( 0 , SMG_Duanma[ 15 ] ); // F
Delay_tms( 10 );
SMG_Light( 1 , 0xff );
Delay_tms( 10 );
SMG_Light( 2 , 0xff );
Delay_tms( 10 );
if( last_count_f > 9999 ) // 最高五位数,到了几位就亮几位
{
SMG_Light( 3 , SMG_Duanma[ last_count_f / 10000 ] );
Delay_tms( 10 );
}
if( last_count_f > 999 )
{
SMG_Light( 4 , SMG_Duanma[ ( last_count_f / 1000 ) % 10 ] );
Delay_tms( 10 );
}
if( last_count_f > 99 )
{
SMG_Light( 5 , SMG_Duanma[ ( last_count_f / 100 ) % 10 ] );
Delay_tms( 10 );
}
if( last_count_f > 9 )
{
SMG_Light( 6 , SMG_Duanma[ ( last_count_f / 10 ) % 10 ] );
Delay_tms( 10 );
}
if( last_count_f > 0 )
{
SMG_Light( 7 , SMG_Duanma[ last_count_f % 10 ] );
Delay_tms( 10 );
}
}
// 定时器初始化
void Timer_Init(void)
{
TMOD = 0x16; // 0001 0110
ET0 = 1;
ET1 = 1;
EA = 1;
TR0 = 1;
TR1 = 1;
// 定时器0用作计数,8位自动重装载,只要随机外来一个脉冲信号就溢出
TH0 = 0xff;
TL0 = 0xff;
// 定时器1用作定时
TH1 = ( 65535 - 50000 ) / 256;
TL1 = ( 65535 - 50000 ) % 256;
}
// 定时器0中断函数
void Timer0() interrupt 1
{
count_f++;
}
// 定时器1中断函数
void Timer1() interrupt 3
{
TH1 = ( 65535 - 50000 ) / 256;
TL1 = ( 65535 - 50000 ) % 256;
i++;
if( i == 20 ) // 1s时间到
{
i = 0; // 计数清零
last_count_f = count_f; // 取出频率
count_f = 0; // 下一秒频率又重新测,即清零
}
}
#include
#include "Delay_ms.h"
unsigned int count_f = 0; // 测得频率
unsigned int last_count_f = 0; // 频率传递
unsigned char i = 0; // 计数值
// 不加 “code” 会影响单片机运行速度,会改变RAM,加了 code 之后內容就固定不变了,不会占用RAM
unsigned char code SMG_Duanma[19] =
{
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0x00
}; // 0~F - . 全部
// 带点显示的
unsigned char code SMG_Dian[10] =
{
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10
}; // 0.~9.
// 通道选择函数
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = (P2 & 0x1f) | 0x00; // 0
break;
case 4:
P2 = (P2 & 0x1f) | 0x80; // Y4C
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; // Y5C
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; // Y6C
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; // Y7C
break;
}
}
// 初始化系统
void System_Init(void)
{
// 关闭LED灯
HC138_Init( 4 );
P0 = 0xff;
// 关闭蜂鸣器和继电器
HC138_Init( 5 );
P0 = 0xaf; // 1010 1111
// 关闭通道选择
HC138_Init( 0 );
}
// 定时器初始化
void Timer_Init(void)
{
TMOD = 0x16; // 0001 0110
ET0 = 1;
ET1 = 1;
EA = 1;
TR0 = 1;
TR1 = 1;
// 定时器0用作计数,8位自动重装载,只要随机外来一个脉冲信号就溢出
TH0 = 0xff;
TL0 = 0xff;
// 定时器1用作定时
TH1 = ( 65535 - 50000 ) / 256;
TL1 = ( 65535 - 50000 ) % 256;
}
// 定时器0中断函数
void Timer0() interrupt 1
{
count_f++;
}
// 定时器1中断函数
void Timer1() interrupt 3
{
TH1 = ( 65535 - 50000 ) / 256;
TL1 = ( 65535 - 50000 ) % 256;
i++;
if( i == 20 ) // 1s时间到
{
i = 0; // 计数清零
last_count_f = count_f; // 取出频率
count_f = 0; // 下一秒频率又重新测,即清零
}
}
// 数码管显示
void SMG_Light( unsigned char pos , unsigned char dat )
{
HC138_Init( 6 );
P0 = 0x01 << pos;
HC138_Init( 7 );
P0 = dat;
}
// 数码管动态显示
void SMG_Show(void)
{
SMG_Light( 0 , SMG_Duanma[ 15 ] ); // F
Delay_tms( 10 );
SMG_Light( 1 , 0xff );
Delay_tms( 10 );
SMG_Light( 2 , 0xff );
Delay_tms( 10 );
if( last_count_f > 9999 ) // 最高五位数,到了几位就亮几位
{
SMG_Light( 3 , SMG_Duanma[ last_count_f / 10000 ] );
Delay_tms( 10 );
}
if( last_count_f > 999 )
{
SMG_Light( 4 , SMG_Duanma[ ( last_count_f / 1000 ) % 10 ] );
Delay_tms( 10 );
}
if( last_count_f > 99 )
{
SMG_Light( 5 , SMG_Duanma[ ( last_count_f / 100 ) % 10 ] );
Delay_tms( 10 );
}
if( last_count_f > 9 )
{
SMG_Light( 6 , SMG_Duanma[ ( last_count_f / 10 ) % 10 ] );
Delay_tms( 10 );
}
if( last_count_f > 0 )
{
SMG_Light( 7 , SMG_Duanma[ last_count_f % 10 ] );
Delay_tms( 10 );
}
}
int main(void)
{
System_Init();
Timer_Init();
while(1)
{
SMG_Show();
}
}