文章导读
- 认识NE555模块
- 如何编写代码
- 如何使用NE555
在学习蓝桥杯单片机的过程中,许多同学往往忽视了 NE555 定时器模块的应用和原理。事实上,NE555 是单片机应用中不可或缺的基础知识之一,它不仅是经典的定时器、脉冲生成器,更在实际项目中扮演着至关重要的角色。从PWM信号生成到频率分频,再到定时延迟,NE555 都能为项目提供极大的灵活性和功能扩展。在蓝桥杯的竞赛中,掌握 NE555 的应用不仅能够帮助我们提高实际操作能力,也能在遇到相关考题时,快速解决问题。因此,建议同学们在备赛过程中,不要忽略这个基础而强大的模块,它将为你在竞赛中的成功奠定坚实的基础。
NE555原理图
触发和复位:
- 当引脚2 ( TR ) 的电压低于1/3 VCC时,NE555被触发,输出引脚3 ( Q ) 变为高电平。
- 当引脚4 ( R ) 被拉低时,NE555被复位,输出引脚3 ( Q ) 变为低电平。
定时和振荡:
- 通过电阻RB3、R8和电容C14、C16的组合,可以控制NE555的定时和振荡频率。
- 当引脚6 (THR) 的电压高于2/3 VCC时,NE555的定时周期结束,输出引脚3 (Q) 变为低电平。
放电:
- 引脚7 (DIS) 用于放电,当NE555处于定时周期时,该引脚会将电容C14放电。
保护和滤波:
- 二极管D2和D3用于保护电路,防止反向电压对电路造成损害。
- 电容C19和C20用于滤波,稳定电源电压,减少噪声干扰。
NE555在蓝桥杯的考点
脉冲发生器
NE555定时器在该电路中配置为产生一个脉冲输出信号。这个信号的频率取决于电阻RB3、R8和电容C14的值。NE555的输出引脚3 (Q) 会输出一个周期性的高电平和低电平信号。
配合定时器(此时定时器配置成计数器模式)读取NE555的输出频率。
连接单片机P34到NE555输出
将单片机的P34引脚连接到NE555的输出引脚3 (Q)。这样,单片机可以通过P34引脚读取NE555产生的脉冲信号。
通过这两张原理图可以看到,在使用NE555模块时要先将引脚3也就是NET_SIG与单片机的P34口通过跳线帽短接。
一般来说,比赛时板子的跳线帽有5个,一个接在J5控制按键模式(矩阵键盘或独立键盘),一个接在J13控制扩展方式(IO模式、MM模式),一个接在J6控制继电器、蜂鸣器电源,最后两个接在J2控制使用超声波模块或者红外传感模块。所以是没有多余的跳线帽来短接NE555的,这个时候,J5、J13跳线帽是一定不能拿下来的,因为题目的基本要求就是这两个要短接,没有短接扣分甚至0分,一般来说,在省赛中超声波模块和NE555是二选一的,所以我们可以摘下超声波模块的跳线帽来短接NE555。
这样做可以直接使用定时器0的计数模式来读取NE555输出脉冲的频率
在板子上配置如下:
配置定时器
定时器0
在使用NE555时,需要使用到两个定时器,一个用作计数,一个用作计时。一般我们默认定时器0计数,定时器1计时。
红色方框内的就是我们要配置的,关于为什么要配置16位不可重装载模式的问题,后续会出一篇文章详细介绍定时器的内容里面会介绍。所以配置TMOD为0000 0101也就是05H。
在stc-isp中直接生成定时器0的函数
这样生成出来的代码是需要改动的,改动如下:
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //改动处
TL0 = 0; //改动处 设置定时初始值为0,即不定时只计数
TH0 = 0; //改动处 设置定时初始值为0,即不定时只计数
TF0 = 0; //清除TF0标志
TR0 = 1; //使能定时器0中断
//EA = 1; //不用使能中断
}
定时器1
定时器1配置如下:
void Timer1_Isr(void) interrupt 3
{
}
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA = 1;//改动处
}
定时器0大概是1s溢出一次,所以在定时器1的中断服务函数中,应该定时1s执行一次测量频率。
执行完测量频率后,要及时复位TL0、TH0重新计时。
idata unsigned int Time_1000ms; //定时1s
idata unsigned int f;//NE555频率
void Timer1_Isr(void) interrupt 3
{
if(++Time_1000ms == 1000)
{
Time_1000ms = 0;
f = (TH0 << 8 | TL0);
TH0 = TL0 = 0;
}
}
完整代码
idata unsigned int f;
idata unsigned int Time_1000ms;
/* 定时器0只用于计数 */
void Timer0_Init(void) //1毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05;
TL0 = 0; //设置定时初始值
TH0 = 0; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
/* 定时器1用于计时 */
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
/* 定时器1中断服务函数 */
void Timer1_Server() interrupt 3
{
/* NE555 */
if(++Time_1s == 1000)
{
Time_1s = 0;
f = (TH0 << 8) | TL0;
TH0 = TL0 = 0;
}
}
应用
题目:通过单片机P34引脚测量NE555输出的脉冲信号频率,用数码管的后五位显示(不考虑高位熄灭问题)。
#include <STC15F2K60S2.H>
#include "Init.h"
#include "LED.h"
#include "Key.h"
#include "Seg.h"
/* 变量声明区 */
unsigned char Key_Slow; //按键减速变量 10ms
unsigned char Key_Val, Key_Down, Key_Up, Key_Old; //按键检测四件套
unsigned int Seg_Slow; //数码管减速变量 500ms
unsigned char Seg_Buf[] = {10,10,10,10,10,10,10,10,10,10};//数码管缓存数组
unsigned char Seg_Pos;//数码管缓存数组专用索引
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};//数码管小数点使能数组
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0};//LED显示数据存放数组
unsigned int Time_1s, f;
/* 按键处理函数 */
void Key_Proc()
{
if(Key_Slow) return;
Key_Slow = 1; //按键减速
Key_Val = Key();
Key_Down = Key_Val & ~Key_Old;
Key_Up = ~Key_Val & Key_Old;
Key_Old = Key_Val;
}
/* 信息处理函数 */
void Seg_Proc()
{
if(Seg_Slow) return;
Seg_Slow = 1; //数码管减速
Seg_Buf[0] = 10;
Seg_Buf[1] = 10;
Seg_Buf[2] = 10;
Seg_Buf[3] = f / 10000 % 10;
Seg_Buf[4] = f / 1000 % 10;
Seg_Buf[5] = f / 100 % 10;
Seg_Buf[6] = f / 10 % 10;
Seg_Buf[7] = f % 10;
}
/* 其他显示函数 */
void Led_Proc()
{
ucLed[0] = 1;
}
/* 定时器0只用于计数 */
void Timer0_Init(void) //1毫秒@12.000MHz
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05;
TL0 = 0; //设置定时初始值
TH0 = 0; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
/* 定时器1用于计时 */
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
/* 定时器1中断服务函数 */
void Timer1_Server() interrupt 3
{
if(++Key_Slow == 10) Key_Slow = 0; //按键延迟
if(++Seg_Slow == 100) Seg_Slow = 0; //数码管延迟
if(++Seg_Pos == 8) Seg_Pos = 0; //数码管显示
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
LED_Disp(ucLed);
/* NE555 */
if(++Time_1s == 1000)
{
Time_1s = 0;
f = (TH0 << 8) | TL0;
TH0 = TL0 = 0;
}
}
void main()
{
Init();
Timer0_Init();
Timer1_Init();
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
结果演示: