 |
#include <at89x52.h>
#define _BV(n) (1 << (n))
sbit PL = P3^0; // 置数端 sbit MR = P3^1; // 清零端 sbit TCU = P3^2; // 进位端 sbit TCD = P3^3; // 借位端 sbit CPD = P3^4; // 倒计时端 sbit CPU = P3^5; // 计时端
unsigned char code seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
void delay(unsigned int n) { unsigned char i; while (n--) for (i = 0; i < 115; i++); }
void LS193_Clear(void) { MR = 1; MR = 0; }
unsigned char LS193_Read(void) { return (P1 & 0x0f); // 输出端接P1低4位 }
void LS193_Write(unsigned char dat) { P1 = ((dat & 0x0f) << 4) | 0x0f; // 置数输入端接P1高4位 PL = 0; PL = 1; }
// 进位、借位信号出现的时间很短 // 这样的判断方法不可靠 /* // 判断是否进位 bit LS193_Carry(void) { TCU = 1; return (TCU == 0); }
// 判断是否借位 bit LS193_Borrow(void) { TCD = 1; return (TCD == 0); } */
// 向上计数 void LS193_Up(void) { CPU = 0; CPU = 1; }
// 向下计数 void LS193_Down(void) { CPD = 0; CPD = 1; }
void seg_scan(void) { unsigned char i; unsigned char n = LS193_Read(); for (i = 7; i >= 6; i--) // 扫描第7、6个数码管,从低位到高位 { P2 = 0xff; P0 = seg8[n % 10]; P2 = ~_BV(i); delay(5); n /= 10; } }
int main(void) { unsigned char i, j; P1 = 0x0f; LS193_Clear(); // 上电先清零 IT0 = 1; // 下降沿触发 EX0 = 1; IT1 = 1; EX1 = 1; EA = 1; // 把外中断的触发方式改为低电平触发(ITx=0)也没有问题 // 因为进位、借位信号持续的时间极短(相应的时钟为低电平时才会出现) while (1) { for (j = 0; j < 32; j++) { for (i = 0; i < 40; i++) seg_scan(); LS193_Up(); } for (j = 0; j < 32; j++) { for (i = 0; i < 40; i++) seg_scan(); LS193_Down(); } } }
void et0(void) interrupt 0 { LS193_Write(2); // 进位时预置数2 }
void et1(void) interrupt 2 { LS193_Write(10); // 借位时预置数10 }
|
 |
/* 延长进、借位信号持续时间的方法 */ /* 副作用: 每次进/退位会产生一短一长两次脉冲, 且切换计数方向时计数值不变 */ #include <at89x52.h>
#define _BV(n) (1 << (n))
// 清零端(14)恒接低电平, 通电时计数值为随机数 sbit TCU = P1^0; // 进位端(12) sbit TCD = P1^1; // 借位端(13) sbit CPD = P1^2; // 倒计时端(4) sbit CPU = P1^3; // 计时端(5)
unsigned char code seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
void delay(unsigned int n) { unsigned char i; while (n--) for (i = 0; i < 115; i++); }
unsigned char LS193_Read(void) { P3 |= 0x0f; return (P3 & 0x0f); // 输出端接P3低4位 }
// 判断是否进位 bit LS193_Carry(void) { TCU = 1; return (TCU == 0); }
// 判断是否借位 bit LS193_Borrow(void) { TCD = 1; return (TCD == 0); }
// 向上计数 void LS193_Up(void) { CPD = 1; // 使向下计数无效, 副作用: 会产生一次向下计数,使得最终本次数字没有变 CPU = 0; CPU = 1; // 产生上升沿 CPU = 0; // =0时进位信号才能长期保持 }
// 向下计数 void LS193_Down(void) { CPU = 1; // 使向上计数无效, 副作用:会产生一次向上计数 CPD = 0; CPD = 1; // 产生上升沿 CPD = 0; // =0时借位信号才能长期保持 }
void seg_scan(void) { unsigned char i; unsigned char n = LS193_Read(); for (i = 7; i >= 6; i--) // 扫描第7、6个数码管,从低位到高位 { P2 = 0xff; P0 = seg8[n % 10]; P2 = ~_BV(i); delay(5); n /= 10; } // 若有进位则显示小写c if (LS193_Carry()) { P2 = 0xff; P0 = 0xa7; P2 = ~_BV(0); } delay(5); // 若有借位则显示小写b if (LS193_Borrow()) { P2 = 0xff; P0 = 0x83; P2 = ~_BV(1); } delay(5); }
int main(void) { unsigned char i, j; while (1) { // 正计时 // 等于15时进位灯亮 for (j = 0; j < 32; j++) { for (i = 0; i < 40; i++) seg_scan(); LS193_Up(); } // 倒计时 // 等于0时借位灯亮 for (j = 0; j < 32; j++) { for (i = 0; i < 40; i++) seg_scan(); LS193_Down(); } } }
|
 |
/* 脉冲产生个数测试 */ #include <at89x52.h>
#define _BV(n) (1 << (n))
// 清零端(14)恒接低电平, 通电时计数值为随机数 sbit TCU = P3^2; // 进位端(12), 外部中断0 sbit TCD = P3^3; // 借位端(13), 外部中断1 sbit CPD = P1^2; // 倒计时端(4) sbit CPU = P1^3; // 计时端(5)
unsigned char code seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; unsigned char num = 0; // 下降沿个数
void delay(unsigned int n) { unsigned char i; while (n--) for (i = 0; i < 115; i++); }
unsigned char LS193_Read(void) { P1 |= 0xf0; return (P1 >> 4) & 0x0f; // 输出端接P1高4位 }
// 向上计数 void LS193_Up(void) { CPD = 1; // 使向下计数无效, 副作用: 会产生一次向下计数,使得最终本次数字没有变 CPU = 0; CPU = 1; // 产生上升沿 CPU = 0; // =0时进位信号才能长期保持 }
// 向下计数 void LS193_Down(void) { CPU = 1; // 使向上计数无效, 副作用:会产生一次向上计数 CPD = 0; CPD = 1; // 产生上升沿 CPD = 0; // =0时借位信号才能长期保持 }
void seg_scan(void) { char i; unsigned char n = LS193_Read(); for (i = 7; i >= 6; i--) // 扫描第7、6个数码管,从低位到高位 { P2 = 0xff; P0 = seg8[n % 10]; P2 = ~_BV(i); delay(5); n /= 10; } n = num; for (i = 2; i >= 0; i--) // 扫描第2~0个数码管,从低位到高位 { P2 = 0xff; P0 = seg8[n % 10]; P2 = ~_BV(i); delay(5); n /= 10; } }
int main(void) { unsigned char i, j; IT0 = 1; EX0 = 1; IT1 = 1; EX1 = 1; EA = 1; while (1) { // 正计时 for (j = 0; j < 32; j++) { for (i = 0; i < 80; i++) seg_scan(); LS193_Up(); } // 倒计时 for (j = 0; j < 32; j++) { for (i = 0; i < 80; i++) seg_scan(); LS193_Down(); } } }
void et0(void) interrupt IE0_VECTOR { num++; }
void et1(void) interrupt IE1_VECTOR { num += 10; }
// 正计时时,从14到15, num+1,说明产生了一个下降沿 // 倒计时时,从01到00,再到15,都要加10,num一共加了20, 说明产生了两个下降沿
|
 |
在第一个程序中,当计数值为14且为向上计数的时候,时钟CPU先置0后置1,也就是先下降沿后上升沿,最后计数值变成15。CPU=0时计数值为14,所以无进位信号。
当从15跳变到0时,因为进位信号只会出现在CPU=0时,且此时计数值为15,所以产生进位信号。因为CPU=0持续的时间极短,大约只有一个时钟周期,所以进位信号有效的时间也极短。如果不使用中断的话基本上检测不出来。
这大大提高了系统的可靠性,使得在置数的时候可以保证不出现计数值=0的情况,直接跳变至指定的数字。
|