目前共有4篇帖子。 內容轉換:不轉換▼
 
點擊 回復
394 3
【程序】51单片机操作外部计数器74LS193
一派護法 十九級
1樓 發表于:2017-2-21 18:08
#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
}
一派護法 十九級
2樓 發表于:2017-2-21 18:09
/* 延长进、借位信号持续时间的方法 */
/* 副作用: 每次进/退位会产生一短一长两次脉冲, 且切换计数方向时计数值不变 */
#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();
        }
    }
}
一派護法 十九級
3樓 發表于:2017-2-21 20:09
/* 脉冲产生个数测试 */
#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, 说明产生了两个下降沿
一派護法 十九級
4樓 發表于:2017-2-22 09:05
在第一个程序中,当计数值为14且为向上计数的时候,时钟CPU先置0后置1,也就是先下降沿后上升沿,最后计数值变成15。CPU=0时计数值为14,所以无进位信号。
当从15跳变到0时,因为进位信号只会出现在CPU=0时,且此时计数值为15,所以产生进位信号。因为CPU=0持续的时间极短,大约只有一个时钟周期,所以进位信号有效的时间也极短。如果不使用中断的话基本上检测不出来。
这大大提高了系统的可靠性,使得在置数的时候可以保证不出现计数值=0的情况,直接跳变至指定的数字。

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
(快捷鍵:Ctrl+Enter)
 

本帖信息

點擊數:394 回複數:3
評論數: ?
作者: 巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2017-2-22 09:05
 
©2010-2024 Arslanbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。