本篇文章介绍触发器
触发器是这样一种电路实现,触发器有一个控制输入端和一个数据输入端,触发器的特点是可以保存数据输入的信息
SR锁存器是最简单的一类触发器,通过两个或非门实现,电路图如下:
我们再次给出或非门的输入输出逻辑关系:
输入
A
输入
B
输出
0
0
1
0
1
0
1
0
0
1
1
0
\begin{array}{|c|c|c|} \hline 输入A&输入B&输出\\ \hline 0&0&1\\ \hline 0&1&0\\ \hline 1&0&0\\ \hline 1&1&0\\ \hline \end{array}
输入A0011?输入B0101?输出1000??
SR锁存器的特点如下:
SR锁存器有两点需要注意:
SR锁存器可以简化为带有输入和输出标志的小框图:
SR锁存器最突出的特点在于,它可以记住哪个输入端的最终状态为 1。
触发器与锁存器的不同在于, 它除了置1、置0输人端以外,又增加了一个触发信号输人端。 只有当触发信号到来时,触发器才能按照输人的置 1、置0信号置成相应的状态,并保持下去。 我们将这个触发信号称为时钟信号(CLOCK),记作CLK。当系统中有多个触发器需要同时动作时,就可以用同一个时钟信号作为同步控制信号了
。
D型触发器由两个或非门组成的SR锁存器加上两个与门组成的逻辑电路
D型触发器有两个输入端:
D型触发器的特点是:只有当数据控制端为高电平时,数据输入端的状态才会被保存
。
D型触发器比SR触发器复杂一些,电路图如下:
根据D型触发器的特点我们可以想到,D型触发器可以保存数据,就是当我需要保存输入数据的时候,只需要把控制端的时钟置成高位即可。并且时钟变为低位后,输入数据不会改变已经保存的数据。
下面列出D型触发器的状态值:
关于D型触发器的思考:
D型触发器的特点决定了一个可能的情况,就是当时钟为1时,如果数据端的数据发生了改变,每次改变都会产生新的状态。对于某些情况而言,可能需要的仅仅是时钟切换到1时保存数据输入的值,然后不在改变。一个是区间,一个是即时,对于即时的改变,有一种新的触发器,叫做边沿触发器
边沿触发器的特点:
只有当时钟从0跳变到1时,才会引起输出的改变。边沿触发器与D型触发器的区别在于,在D型触发器中,当时钟输入为0时, 数据端输入的任何改变都不会影响输出;而在边沿触发器中,当时钟输入为1时,数据端输入的改变也不会影响输出。只有在时钟输入从0变到1的瞬间,数据端的输入才会影响边沿触发器的输出
。
边沿触发器是由两个D型触发器连接而成的,电路图如下:
可以推导一下边沿触发器的规则:
最后给出锁存器触发器的C语言实现
可以参考Git地址
/**
* sr锁存器的C语言实现
* s:置位项
* r:重置项
* q:输入Q
* q1:输出Q1
*/
extern void sr_lock(long s, long r,long *q,long *q1);
/**
* D型触发器
* clock:时钟输入
* data:数据输入
* q:输出Q
* q1:输出Q1
*/
extern void d_trigger(long clock, long data,long *q,long *q1);
/**
* 边沿触发器
* clock:时钟输入
* data:数据输入
* q_0:前面的D型触发器的输出数据
* q_1:前面的D型触发器的输出数据
* q:输出Q
* q1:输出Q1
*/
extern void b_trigger(long clock, long data,long *q_0,long *q_1,long *q,long *q1);
void sr_lock(long s, long r,long *q,long *q1)
{
for(int i =0;i<sizeof(long)*8;i++)
{
// 输入都是0,状态不变
if(((1<<i)&s) == 0 && ((1<<i)&r) == 0)
{
continue;
}
// 输入都是1,理论上要避免
if(((1<<i)&s) != 0 && ((1<<i)&r) != 0)
{
continue;
}
// s==1 r==0
if(((1<<i)&s) != 0)
{
(*q) |= 1<<i;
}
else// s==0 r==1
{
(*q) &= ~(1<<i);
}
}
(*q1) = ~(*q);
}
void d_trigger(long clock, long data,long *q,long *q1)
{
long in_1 = alu_and(clock, data, sizeof(long)*8);
long in_2 = alu_and(clock, ~data, sizeof(long)*8);
sr_lock(in_1,in_2,q,q1);
}
void b_trigger(long clock, long data,long *q_0,long *q_1,long *q,long *q1)
{
d_trigger(~clock,data,q_0,q_1);
long in_1 = alu_and(clock, *q_0, sizeof(long)*8);
long in_2 = alu_and(clock, *q_1, sizeof(long)*8);
sr_lock(in_1,in_2,q,q1);
}