<p id="5vvtt"><ruby id="5vvtt"><mark id="5vvtt"></mark></ruby></p><p id="5vvtt"></p>

    <p id="5vvtt"></p>
    <ruby id="5vvtt"><b id="5vvtt"></b></ruby>

          <ruby id="5vvtt"></ruby>

          <ruby id="5vvtt"><mark id="5vvtt"></mark></ruby>
            3
            收藏
            微博
            微信
            復制鏈接

            單片機流水燈與呼吸燈結合-滴水燈程序及詳細教程

            提問于
            2024-01-09 08:58

            TWAS手把手教你做呼吸燈-基于51單片機學習板
            內容比較簡單,發這個貼主要是針對新手!
            什么是呼吸燈?
                顧名思義,燈光在微電腦控制之下完成由亮到暗的逐漸變化,感覺像是在呼吸。用專業的話來說是通過控制PWM的占空比來完成對LED亮度的控制
            什么是PWM和占空比?
                脈沖寬度調制(Pulse Width Modulation,簡稱PWM),是利用微處理器的數字輸出來對模擬電路進行控制的一種技術。
                占空比:高電平在一個周期之內所占的時間比率。
            呼吸燈原理
                當一顆LED在高速閃爍,閃爍的頻率已經超過了人眼的感知的范圍,那么我們看到這顆LED就是一直亮的,也就是視覺暫留現象(余暉效應)。如果

            我們控制一次閃爍中亮和滅的時間(修改占空比),就可以控制亮度。
                代碼實現:
            /*******************************************************
            *  程序名稱:main.c
            *  程序功能:實現呼吸燈的主程序文件
            *  程序作者:TWAS
            *  創建時間:2015-1-22
            *  修改時間:
            *  程序版本:V0.1
            *******************************************************/


            /* 包含的頭文件 */
            #include


            /* 尋址變量定義 */
            sbit LED_Drive = P3^5;         /* 定義驅動LED的IO口,LED為共陽 */




            /******************************************************
            * 函數名稱:main
            * 函數功能:主函數
            * 入口參數:NULL
            * 出口參數:NULL
            *******************************************************/
            int main()
            {
                unsigned char i;
                /* 初始化 */
                    LED_Drive = 1;


                    /* 主循環 */
                    while(1)
                    {
                        for(i = 0; i < 200; i++)
                            {


                                /* 外邊的for循環共循環200次,前面10次點亮LED,后面180次熄滅LED
                                     * 通過修改if后面的值,就可以改變占空比
                                     */
                                    if(i < 10)
                                    {
                                            LED_Drive = 0;
                                    }
                                    else
                                    {
                                            LED_Drive = 1;
                                    }
                         }   
                    }


                    return 0;
            }


            /******************************************
            *                      程序結束
            *****************************************/

            可以明顯看出我們所控制的LED比電源燈暗許多,既然我們會控制亮度,想實現呼吸燈也就變的簡單了
                代碼實現:(為了節約空間和界面簡潔,只貼出主要實現的部分)
            int main()
            {
               
                unsigned char         i;
                    unsigned char ucNum = 0;                 /* 新增兩個變量,ucNum控制占空比*/
                    bit            bAdd = 1;                 /* bAdd選擇是增大占空比還是減小占空比 */
                /* 初始化 */
                    LED_Drive = 1;


                    /* 主循環 */
                    while(1)
                    {
                        
                        for(i = 0; i < 200; i++)
                            {


                                /* 外邊的for循環共循環200次,前面10次點亮LED,后面180次熄滅LED
                                     * 通過修改if后面的值,就可以改變占空比
                                     */
                                    if(i < ucNum)
                                    {
                                            LED_Drive = 0;
                                    }
                                    else
                                    {
                                            LED_Drive = 1;
                                    }
                         }
                             /* 選擇是增大占空比還是減小占空比 */
                             if (1 == bAdd)
                             {
                                 ucNum++;
                             }
                             else
                             {
                                 ucNum--;
                             }
                             
                             /* 當Num等于200也就是最大值時,bAdd置0,Num開始減小 */
                             if (200 == ucNum)
                             {
                                 bAdd = 0;
                             }
                             /* 當Num等于200也就是最大值時,bAdd置1,Num開始增大 */
                             else if (0 == ucNum)
                             {
                                 bAdd = 1;
                             }
                                
                    }


                    return 0;
            }
                 由于圖片看不到效果,這個地方就不貼圖了,根據測試,我們的所需要的功能實現了!
            但是這時候有的人就有疑問了,這是很普通的LED,那如果是特殊一點的呢?比如我所用的
            學習板上面,16顆LED是用595驅動的,那呼吸燈又該如何實現呢?
                其實很簡單,我們把驅動LED的函數封裝一下,直接替換,其它不變就行了!
                代碼實現:(為了節約空間和界面簡潔,只貼出主要實現的部分)
            for(i = 0; i < 200; i++)
            {


                /* 外邊的for循環共循環200次,前面10次點亮LED,后面180次熄滅LED
                     * 通過修改if后面的值,就可以改變占空比
                     */
                    if(i < ucNum)
                    {
                            DriveLED(0x0003);   /* LED驅動,點亮D1和D2 */
                    }
                    else
                    {
                            DriveLED(0x0002);   /* LED驅動,熄滅D1點亮D2 */
                    }
            }
                 當我把程序改成這樣的時候,出了一點問題,不能呼吸,變成閃爍了!等等,先把LED驅動部分發一下:

            /******************************************************
            * 函數名稱:SendData
            * 函數功能:74HC595數據的發送
            * 入口參數:unsigned int uiDataOne, unsigned int uiDataTwo
            * 出口參數:void
            *******************************************************/
            void SendData(unsigned char ucDataOne, unsigned char ucDataTwo)
            {
                     
                unsigned int i = 0;
                    
                      /* 將片選信號置為低電平 */
                      HC595RCK = 0;
                    
                      /* 輸入第一個數據:uiDataOne */
                      for (i = 0; i < 8; i++)
                      {
                    /* 給出脈沖信號,首先將CLK置為0 */
                                      HC595CLK = 0;
                                      if (0 != (ucDataOne & 0x80))
                                            {
                        HC595DATA = 1;   
                    }
                                            else
                                            {
                        HC595DATA = 0;
                    }
                                            /* 給出脈沖信號,首先將CLK置為1 */
                                            HC595CLK = 1;
                                            /* 準備第二個數據 */
                                            ucDataOne = ucDataOne << 1;
                }
                           
                      /* 輸入第二個數據:uiDataTwo */
                      for (i = 0; i < 8; i++)
                      {
                    /* 給出脈沖信號,首先將CLK置為0 */
                                      HC595CLK = 0;
                                      if (0 != (ucDataTwo & 0x80))
                                            {
                        HC595DATA = 1;   
                    }
                                            else
                                            {
                        HC595DATA = 0;
                    }
                                            /* 給出脈沖信號,首先將CLK置為1 */
                                            HC595CLK = 1;
                                            /* 準備第二個數據 */
                                            ucDataTwo = ucDataTwo << 1;
                }
                           
                            /* 將片選信號置為高電平 */
                      HC595RCK = 1;
            }


            /********************************************************
            *  函數名稱:DriveLED
            *  函數功能:595驅動程序是分兩個數據發的,
            *            本函數把它合并成一個數據
            *  入口參數:uiData:16顆LED需要顯示的數據
            *  出口參數:NULL
            *******************************************************/
            void DriveLED(unsigned int uiData)
            {
                SendData(uiData >> 8,uiData);
            }

                 繼續剛剛的問題,呼吸燈變成閃爍了,怎么回事呢?在程序邏輯上是沒有問題的,
            我們只是更改了LED的驅動部分,看來就是LED驅動的問題了!先來Debug看一下,執行
            DriveLED這個函數,時間是接近400微妙,循環200次,就是差不多80毫秒,那么LED的
            閃爍頻率為12.5HZ(都是大概的值,沒有精確計算),還不足以形成視覺暫留現象。
            那怎么辦呢,減少循環次數為50,頻率增大到50HZ左右,像這樣:
            for(i = 0; i < 50; i++)
            {



                     /* 通過修改ucNum的值,就可以改變占空比 */
                    if(i < ucNum)
                    {
                            DriveLED(0x0003);   /* LED驅動,點亮D1和D2 */
                    }
                    else
                    {
                            DriveLED(0x0002);   /* LED驅動,熄滅D1點亮D2 */
                    }
            }
            經過驗證!成功了!
            如有錯誤的地方,希望大家批評指正!

            收藏 267 0 3
            粉絲
            0
            關注
            0
            主題
            5
            學習的是一種思維的方法,感覺挺好,收藏待練習
            0

            回答于 · 2024-01-10 15:34

            粉絲
            0
            關注
            0
            主題
            6
            剛剛驗證了一下,確實可以實現,樓主厲害
            0

            回答于 · 2024-01-10 21:03

            粉絲
            0
            關注
            0
            主題
            4
            樓主我也遇到麻煩為啥用PWM。調光的呼吸燈的程序變成流水燈程序的一個函數調用的形式。結果只有流水沒有呼吸。
            求救大佬:'(
            #include"reg52.h"
            #include
            typedef unsigned int u16;
            typedef unsigned char u8;


            sbit led1=P2;
            int PWM_Low,Clock=500;
            #define led P2
            void delay(u16 a)
            {while(a--);
            }


                       void main1(int t)
                       {       
                                      
                                         for(PWM_Low=Clock;PWM_Low>0;PWM_Low--)
                                              {t=1;
                                            delay(PWM_Low);
                                            {int b;
            for (b=0;b                                 t=0;
                                            delay(Clock-PWM_Low);
                                                    {int b;
            for (b=0;b        
                                            }        }
                                             
            void main()
            {u8 i,t,t1,t2;
            t1=0xfe;
            t2=0x7f;
            for(i=0;i<4;i++)
            {t=t1&t2;
            led=t;
            main1(t);
            delay(50000);

            t1=_crol_(t1,1);
            t2=_cror_(t2,1);}  }
            0

            回答于 · 2024-01-11 17:15

            亚洲精品免费看>>在线免费观看视频>>亚洲精品免费看