設置 | 登錄 | 註冊

作者共發了4篇帖子。

【程序】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的情況,直接跳變至指定的數字。

內容轉換:

回覆帖子
內容:
用戶名: 您目前是匿名發表。
驗證碼:
看不清?換一張
©2010-2025 Purasbar Ver3.0 [手機版] [桌面版]
除非另有聲明,本站採用知識共享署名-相同方式共享 3.0 Unported許可協議進行許可。