久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 26274|回復: 3
打印 上一主題 下一主題
收起左側

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

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

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


/* 包含的頭文件 */
#include <reg52.h>


/* 尋址變量定義 */
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 */
        }
}
經過驗證!成功了!
如有錯誤的地方,希望大家批評指正!
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏8 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發
ID:82588 發表于 2015-6-14 10:42 | 只看該作者
學習的是一種思維的方法,感覺挺好,收藏待練習
回復

使用道具 舉報

板凳
ID:83294 發表于 2015-6-20 17:40 | 只看該作者
剛剛驗證了一下,確實可以實現,樓主厲害
回復

使用道具 舉報

地板
ID:581062 發表于 2019-7-9 16:45 | 只看該作者
樓主我也遇到麻煩為啥用PWM。調光的呼吸燈的程序變成流水燈程序的一個函數調用的形式。結果只有流水沒有呼吸。
求救大佬:'(
#include"reg52.h"
#include<intrins.h>
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<PWM_Low;b++);}
                                t=0;
                                delay(Clock-PWM_Low);
                                        {int b;
for (b=0;b<Clock-PWM_Low;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);}  }
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 欧美精品成人一区二区三区四区 | 国产精品高潮呻吟久久av野狼 | 日韩a在线 | 中文字幕 在线观看 | 狠狠爱综合网 | 91xxx在线观看 | 中文字幕精品一区久久久久 | 丁香久久 | 欧美日韩一区二区三区四区五区 | av手机在线免费观看 | 五月天国产 | 午夜精品一区二区三区在线视频 | 久久久久国产一级毛片高清网站 | av免费入口 | 日韩成人在线免费观看 | 久久出精品 | 亚洲成人精品久久久 | 黄色在线免费观看 | 国产专区在线 | 国产三级电影网站 | 日韩综合在线 | 色www精品视频在线观看 | 亚洲天堂精品一区 | 日本小电影在线 | 激情一区二区三区 | 午夜电影日韩 | 亚洲视频一区 | 久久久免费电影 | 久久91精品久久久久久9鸭 | 日韩欧美一级片 | 9久久婷婷国产综合精品性色 | 欧美全黄 | 日韩精品免费视频 | 91毛片在线观看 | 欧美精品一区二区三区在线 | 久草资源在线 | 精品视频一区二区三区在线观看 | 一区二区三区欧美 | 精品一区二区三区四区五区 | 国产精品完整版 | 在线中文字幕视频 |