我决定在C中使用编程触发器。我曾尝试过D和JK触发器(没有预设和清晰的部分)。
我正在测试是否通过级联它们,我可以让它们产生一个简单的4位纹波计数器。在编写我的代码并运行它之后,它似乎以下列形式产生了一些非常奇怪的结果:
Clk:01010101010101010101
OuA:01100110011001100110
OuB:01000100010001000100
OuC:01111000011110000111
OuD:01010000010100000101
在Clk是输入时钟的情况下,OuA输出A,OuB,输出B等。正如您所看到的,OuA和OuC在开启与关闭的比例看起来有点可以接受,但B和D看起来真的很奇怪!
我的代码是:
#include <stdio.h>
#include <stdlib.h>
void DFF(int Clk, int D, int *Q, int *NQ)
{
if(Clk)
{
*Q = D;
*NQ = !*Q;
}
}
void JKF(int Clk, int J, int K, int *Q, int *NQ)
{
if(Clk&J&(!K))
{
*Q = 1;
*NQ = 0;
}
if(Clk&K&(!J))
{
*Q = 0;
*NQ = 1;
}
if(Clk&J&K)
{
*Q = *NQ;
*NQ = !*Q;
}
}
int main()
{
FILE *fptr;
const int Len = 20;
int Clk = 1, ClkA[Len];
int n, OA[Len], OB[Len], OC[Len], OD[Len];
int Q = 0, NQ = 1;
int Q2 = 0, NQ2 = 1;
int Q3 = 0, NQ3 = 1;
int Q4 = 0, NQ4 = 1;
for(n=0; n<Len; n++)
{
Clk^=1;
JKF(Clk, 1, 1, &Q, &NQ);
JKF(Q, 1, 1, &Q2, &NQ2);
JKF(Q2, 1, 1, &Q3, &NQ3);
JKF(Q3, 1, 1, &Q4, &NQ4);
ClkA[n] = Clk;
OA[n] = Q;
OB[n] = Q2;
OC[n] = Q3;
OD[n] = Q4;
}
fptr = fopen("c:/ff.txt", "w");
fprintf(fptr, "Clk: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", ClkA[n]);
fprintf(fptr, "\nOuA: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", OA[n]);
fprintf(fptr, "\nOuB: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", OB[n]);
fprintf(fptr, "\nOuC: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", OC[n]);
fprintf(fptr, "\nOuD: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", OD[n]);
fclose(fptr);
return 0;
}
我为清晰度道歉并且我知道它可能不是特别有效但是有人可以请清楚输出结果吗?
干杯!
答案 0 :(得分:1)
稍微改进的版本......
#include <stdio.h>
#include <stdlib.h>
typedef struct _JKFF
{
int clk;
int q;
int nq;
}JKFF;
void JKFFn(int Clk, int J, int K, _JKFF * jkff)
{
if ((Clk != jkff->clk) && !Clk)
{ //Triggering FF on the falling edge
if(J& (!K))
{
jkff->q = 1;
}
if(K &(!J))
{
jkff->q = 0;
}
if(J & K)
{
jkff->q = !jkff->q;
}
jkff->nq = !jkff->q;
}
jkff->clk = Clk;
}
int main()
{
FILE *fptr;
const int Len = 80;
int Clk = 1, ClkA[Len];
int n, OA[Len], OB[Len], OC[Len], OD[Len];
_JKFF jkff[4];
memset(jkff, 0, sizeof(jkff));
for(n=0; n<Len; n++)
{
Clk^=1;
JKFFn(Clk, 1, 1, &jkff[0]);
JKFFn(jkff[0].q, 1, 1, &jkff[1]);
JKFFn(jkff[1].q, 1, 1, &jkff[2]);
JKFFn(jkff[2].q, 1, 1, &jkff[3]);
ClkA[n] = Clk;
OA[n] = jkff[0].q;
OB[n] = jkff[1].q;
OC[n] = jkff[2].q;
OD[n] = jkff[3].q;
}
fptr = fopen("ff.txt", "w");
fprintf(fptr, "Clk: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", ClkA[n]);
fprintf(fptr, "\nOuA: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", OA[n]);
fprintf(fptr, "\nOuB: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", OB[n]);
fprintf(fptr, "\nOuC: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", OC[n]);
fprintf(fptr, "\nOuD: ");
for(n = 0; n<Len; n++) fprintf(fptr, "%d", OD[n]);
fclose(fptr);
return 0;
}
答案 1 :(得分:0)
根据函数JKF的实现,它是水平触发而不是边缘触发。
Clk:010
OuA:011
OuB:010
在第三个时钟转换时,OuA仍为“1”。 因此JKF(Q,1,1和&amp; Q2,&amp; NQ2);将OuB切换为逻辑0。
必须考虑时钟的转换,而不是JKF函数实现中的当前时钟级别。
作为简单的补救措施,可以按如下方式更改for循环,以便将时钟转换考虑在内。
for(n=0; n<Len; n++)
{
Clk^=1;
JKF(Clk, 1, 1, &Q, &NQ);
if (n > 0)
{
if (OA[n -1] != Q)
{
JKF(Q, 1, 1, &Q2, &NQ2);
}
if (OB[n -1] != Q2)
{
JKF(Q2, 1, 1, &Q3, &NQ3);
}
if (OC[n -1] != Q3)
{
JKF(Q3, 1, 1, &Q4, &NQ4);
}
}
else
{
JKF(Q, 1, 1, &Q2, &NQ2);
JKF(Q2, 1, 1, &Q3, &NQ3);
JKF(Q3, 1, 1, &Q4, &NQ4);
}
ClkA[n] = Clk;
OA[n] = Q;
OB[n] = Q2;
OC[n] = Q3;
OD[n] = Q4;
}