新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 第17節:兩片聯級74HC595驅動16個LED燈的基本驅動程序

        第17節:兩片聯級74HC595驅動16個LED燈的基本驅動程序

        作者: 時間:2016-11-22 來源:網絡 收藏
        開場白:

        上一節講了如何把矩陣鍵盤翻譯成獨立按鍵的處理方式。這節講74HC595驅動程序。要教會大家兩個知識點:

        本文引用地址:http://www.104case.com/article/201611/319791.htm

        第一點:朱兆祺的學習板是用74HC595控制LED,因此可以直接把595的OE引腳接地。如果在工控中,用來控制繼電器,那么此芯片的片選腳OE不要為了省一個IO口而直接接地,否則會引起上電瞬間繼電器莫名其妙地動作。為了解決這個問題,OE腳應該用一個IO口單獨驅動,并且千萬要記住,此IO必須接一個15K左右的上拉電阻,然后在程序剛上電運行時,先把OE置高,并且盡快把所有的74HC595輸出口置低,然后再把OE置低.當然還有另外一種解決辦法,就是用一個10uF的電解電容跟一個100K的下拉電阻,組成跟51單片機外圍復位電路原理一樣的電路,連接到OE口,這樣確保上電瞬間OE口有一小段時間是處于高電平狀態,在此期間,盡快通過軟件把74hc595的所有輸出口置低。

        第二點:兩個聯級74HC595的工作過程:每個74HC595內部都有一個8位的寄存器,兩個聯級起來就有兩個寄存器。ST引腳就相當于一個刷新信號引腳,當ST引腳產生一個上升沿信號時,就會把寄存器的數值輸出到74HC595的輸出引腳并且鎖存起來,DS是數據引腳,SH是把新數據送入寄存器的時鐘信號。也就是說,SH引腳負責把數據送入到寄存器里,ST引腳負責把寄存器的數據更新輸出到74HC595的輸出引腳上并且鎖存起來。

        具體內容,請看源代碼講解。

        (1)硬件平臺:基于朱兆祺51單片機學習板。

        (2)實現功能:兩片聯級的74HC595驅動的16個LED燈交叉閃爍。比如,先是第1,3,5,7,9,11,13,15八個燈亮,其它的燈都滅。然后再反過來,原來亮的就滅,原來滅的就亮。交替閃爍。

        (3)源代碼講解如下:

        #include "REG52.H"

        #define const_time_level 200

        void initial_myself();

        void initial_peripheral();

        void delay_short(unsigned int uiDelayShort);

        void delay_long(unsigned int uiDelaylong);

        void led_flicker();

        void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);

        void T0_time(); //定時中斷函數

        /* 注釋一:

        * 朱兆祺的學習板是用74HC595控制LED,因此可以直接把595的OE引腳接地。如果在工控中,用來控制繼電器,

        * 那么此芯片的片選腳OE不要為了省一個IO口而直接接地,否則會引起上電瞬間繼電器莫名其妙地動作。

        * 為了解決這個問題,OE腳應該用一個IO口單獨驅動,并且千萬要記住,此IO必須接一個15K左右的

        * 上拉電阻,然后在程序剛上電運行時,先把OE置高,并且盡快把所有的74HC595輸出口置低,然后再把OE置低.

        * 當然還有另外一種解決辦法,就是用一個10uF的電解電容跟一個100K的下拉電阻,組成跟51單片機外圍復位電路原理

        * 一樣的電路,連接到OE口,這樣確保上電瞬間OE口有一小段時間是處于高電平狀態,在此 期間,

        * 盡快通過軟件把74hc595的所有輸出口置低。

        */

        sbit hc595_sh_dr=P2^3;

        sbit hc595_st_dr=P2^4;

        sbit hc595_ds_dr=P2^5;

        unsigned char ucLedStep=0; //步驟變量

        unsigned int uiTimeCnt=0; //統計定時中斷次數的延時計數器

        void main()

        {

        initial_myself();

        delay_long(100);

        initial_peripheral();

        while(1)

        {

        led_flicker();

        }

        }

        /* 注釋二:

        * 兩個聯級74HC595的工作過程:

        * 每個74HC595內部都有一個8位的寄存器,兩個聯級起來就有兩個寄存器。ST引腳就相當于一個刷新

        * 信號引腳,當ST引腳產生一個上升沿信號時,就會把寄存器的數值輸出到74HC595的輸出引腳并且鎖存起來,

        * DS是數據引腳,SH是把新數據送入寄存器的時鐘信號。也就是說,SH引腳負責把數據送入到寄存器里,ST引腳

        * 負責把寄存器的數據更新輸出到74HC595的輸出引腳上并且鎖存起來。

        */

        void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)

        {

        unsigned char i;

        unsigned char ucTempData;

        hc595_sh_dr=0;

        hc595_st_dr=0;

        ucTempData=ucLedStatusTemp16_09; //先送高8位

        for(i=0;i<8;i++)

        {

        if(ucTempData>=0x80)hc595_ds_dr=1;

        else hc595_ds_dr=0;

        hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器

        delay_short(15);

        hc595_sh_dr=1;

        delay_short(15);

        ucTempData=ucTempData<<1;

        }

        ucTempData=ucLedStatusTemp08_01; //再先送低8位

        for(i=0;i<8;i++)

        {

        if(ucTempData>=0x80)hc595_ds_dr=1;

        else hc595_ds_dr=0;

        hc595_sh_dr=0; //SH引腳的上升沿把數據送入寄存器

        delay_short(15);

        hc595_sh_dr=1;

        delay_short(15);

        ucTempData=ucTempData<<1;

        }

        hc595_st_dr=0; //ST引腳把兩個寄存器的數據更新輸出到74HC595的輸出引腳上并且鎖存起來

        delay_short(15);

        hc595_st_dr=1;

        delay_short(15);

        hc595_sh_dr=0; //拉低,抗干擾就增強

        hc595_st_dr=0;

        hc595_ds_dr=0;

        }

        void led_flicker() ////第三區 LED閃爍應用程序

        {

        switch(ucLedStep)

        {

        case 0:

        if(uiTimeCnt>=const_time_level) //時間到

        {

        uiTimeCnt=0; //時間計數器清零

        hc595_drive(0x55,0x55);

        ucLedStep=1; //切換到下一個步驟

        }

        break;

        case 1:

        if(uiTimeCnt>=const_time_level) //時間到

        {

        uiTimeCnt=0; //時間計數器清零

        hc595_drive(0xaa,0xaa);

        ucLedStep=0; //返回到上一個步驟

        }

        break;

        }

        }

        void T0_time() interrupt 1

        {

        TF0=0; //清除中斷標志

        TR0=0; //關中斷

        if(uiTimeCnt<0xffff) //設定這個條件,防止uiTimeCnt超范圍。

        {

        uiTimeCnt++; //累加定時中斷的次數,

        }

        TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f

        TL0=0x2f;

        TR0=1; //開中斷

        }

        void delay_short(unsigned int uiDelayShort)

        {

        unsigned int i;

        for(i=0;i

        {

        ; //一個分號相當于執行一條空語句

        }

        }

        void delay_long(unsigned int uiDelayLong)

        {

        unsigned int i;

        unsigned int j;

        for(i=0;i

        {

        for(j=0;j<500;j++) //內嵌循環的空指令數量

        {

        ; //一個分號相當于執行一條空語句

        }

        }

        }

        void initial_myself() //第一區 初始化單片機

        {

        TMOD=0x01; //設置定時器0為工作方式1

        TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f

        TL0=0x2f;

        }

        void initial_peripheral() //第二區 初始化外圍

        {

        EA=1; //開總中斷

        ET0=1; //允許定時中斷

        TR0=1; //啟動定時中斷

        }

        總結陳詞:

        這節講了74HC595的驅動程序,它是一次控制16個LED同時亮滅的,在實際中應用不太方便,如果我們想要像單片機IO口直接控制LED那樣方便,我們該怎么編寫程序呢?欲知詳情,請聽下回分解-----把74HC595驅動程序翻譯成類似單片機IO口直接驅動的方式。



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 宜兰市| 从江县| 满城县| 塘沽区| 石阡县| 洛川县| 卫辉市| 同心县| 石嘴山市| 黎城县| 黑水县| 贡觉县| 普定县| 搜索| 澄城县| 运城市| 海伦市| 连南| 汉中市| 巨野县| 广平县| 砚山县| 吉安市| 柳林县| 绥宁县| 淳安县| 新晃| 桐乡市| 白玉县| 南投市| 宿州市| 商南县| 镶黄旗| 汨罗市| 乐山市| 肃南| 游戏| 新巴尔虎右旗| 清涧县| 肥乡县| 青河县|