蓝桥杯模板TemplatePart12:NE555定时器&频率测量
● 改编自国信长天蓝桥杯官方蓝皮书例程,按照自己的习惯进行了补充和修改
一、555定时器
1、内部框图:
2、基础知识:
①GND
②Trigger:触发端,C2比较器的输入端
③Output:OutPut Stage(输出级)一般为缓冲器,为了提高电路的带负载能力。
④Reset:PNP型三极管,基级为1导通。只要Reset端使能,输出端Output立即被置为低电平,不受其他输入端状态的影响
⑤Control Voltage:可外接固定电压,或经0.01uf电容接地。当控制电压输入端(
V
c
o
V_{co}
Vco)悬空时,
V
R
1
=
2
/
3
V
C
C
V_{R1}=2/3V_{CC}
VR1=2/3VCC,
V
R
2
=
1
/
3
V
C
C
V_{R2}=1/3V_{CC}
VR2=1/3VCC;若
V
C
O
V_{CO}
VCO外接固定电压,则
V
R
1
=
V
C
O
V_{R1}=V_{CO}
VR1=VCO,
V
R
2
=
1
/
2
V
C
O
V_{R2}=1/2V_{CO}
VR2=1/2VCO。
⑥Threshold:阈值端,C1比较器的输入端
⑦Discharge:
⑧Vcc
●C1和C2的参考电压(电压比较的基准)
V
R
1
V_{R1}
VR1和
V
R
2
V_{R2}
VR2是由
V
C
C
V_{CC}
VCC经过三个电阻分压给出的。
●SR锁存器(触发器):
Q
∗
=
S
+
R
‘
Q
Q^*=S+ R^`Q
Q∗=S+R‘Q
约束条件:SR=0
二、Template:
原理图:
Notes:
●频率测量时需要将J3-15(SIGNAL)与J3-16(P34短接)。
1、定时器0初始化为计数器
void Timer0Init(void)
{
TMOD |= 0x04; //16位可重装初值的计数器
TL0 = 0;
TH0 = 0;
TR0 = 1;
}
Notes:
●频率测量:将定时器0初始化为计数模式,对输入到P34(T0)的脉冲进行计数,1s的计数值即为频率值。
●官方例程是将定时器0初始化为16位不可重装初值模式TMOD |= 0x05;
,意义不大?
●官方例程将定时器0设置为12T模式AUXR &= 0x7F;
12T和1T模式设置的是定时器 计数脉冲 的分频系数,即计数脉冲 周期是系统时钟的12倍(慢12T模式);计数脉冲为系统时钟脉冲,计数脉冲 周期等于系统时钟周期,即无分频(快,1T模式)。 这一段话里的斜体字 计数脉冲 我的理解指的是定时器工作在定时模式下(即脉冲源为系统时钟)。所以工作在计数器模式下没有 设置分频系数(12T还是1T) 这一说法。
只有在定时器工作在定时模下才有 设置分频系数(12T还是1T) 这一说法。然而,12T与1T唯一的区别就是能够定时的最大时间长度不同。
16位模式下,可最大计数65536个脉冲,而每个脉冲的周期决定了最大计数时间。最大计数时间 = 最大计数脉冲个数*脉冲周期。
12T与1T的区别就是计数的脉冲周期不同,12T模式下的脉冲周期是1T模式下的12倍,所以12T模式的最大计数时间大。
2、定时器1中断服务函数
//定时器1为1ms定时器
void Timer1_ISR(void) interrupt 3
{
……
……
if(++ui_freq_num == 1000)
{
TR0 = 0;
ui_freq = (TH0<<8) | TL0;
ui_freq_num = 0;
Timer0Init();
}
}
Notes:
●在定时器1的中断服务函数中,需要先关计数器T0,再读取TL0
,TH0
的状态值,避免动态读取。T0为16位定时器/计数器,TL0
,TH0
都是8位寄存器,左移8位!!!将1s的计数值赋给freq
后,需要将计数变量ui_freq_num
清零,并且必须将T0计数器再次初始化,即将T0的状态值TL0
,TH0
清零,开T0。
●计数器T0位16位,可计数65536个,参考其他博客用逻辑分析仪实测蓝桥杯555定时器的方波频率范围位:57Hz~24kHz。使用上述程序可得频率范围约为: 90Hz ~27kHz。
更新:用示波器测试结果:最低频率73Hz,最高频率25kHz。使用官方正版绿色开发板测试。
●将
ui_freq = TH0;
ui_freq = (ui_freq <<8) | TL0 ;
替换为
ui_freq = (TH0<<8) | TL0 ;
结果一样,以前也遇到过类似情况,左移为什么不会产生数据丢失?
经DL指点,据说程序执行时是先将TH0的值复制到16位变量ui_freq中再左移。
定时器T0初始化为定时器流程图:
三、备用拓展模板
1、一上电就显示频率,消除变量初始值0
if(ui_freq != 0)
sprintf(puc_SEG_Buf," %5u",ui_freq);