色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

使用51單片機實現LED呼吸燈

CHANBAEK ? 來源:嵌入式小書蟲 ? 作者:FledgingSu 支離蘇 ? 2023-07-04 11:40 ? 次閱讀

【說在前面的話】

單片機技術是現代工業自動化電子電氣物聯網等的一門必不可少的主流技術。隨著人們生活智能化的提高,單片機技術也幾乎融入了我們生活的各個角落,比如智能電飯煲、智能音箱、等等。

由此,《 重學51單片機 》系列文章意在幫助初學者入門單片機技術。我們會從最簡單的點亮一個燈開始,一步一步實現按鍵、lcd1602、ds18b20、ds1302、雙機通信等模塊,同時,還會講一些硬件通信協議,比如uart、IIC、SPI等。并結合C語言編程技巧,以實際的工程項目來給大家講解編程思路,讓大家靈活運用C語言的指針與結構體,實現編程模塊化。

言歸正傳,接下來我們就開始進入今天的主題,用51單片機控制LED實現呼吸燈的效果。

【呼吸燈原理】

我們先看一下呼吸燈的效果下

呼吸燈就是先漸漸變亮再漸漸變暗,如此循環就像呼吸一樣。可是單片機的管腳要么輸出1(亮)要么輸出0(滅),怎么會有漸變的效果呢?

這就和我們的眼睛 觀看圖像會有滯留時間引起的 。當我們在看東西時,眼睛成像后會滯留0.04s(這個標準是網上找的)。

我們按照0.04s計算,就等于40ms,也就是亮滅都是20ms時,看到的LED就是一直在亮。如下圖:

圖片

那LED 20ms亮20ms滅和一直常亮的效果一樣嗎?

哈哈,肯定是不一樣的。交替20ms亮20ms滅我們看到的效果要比一直常亮的效果暗。我們假設一直常亮的亮度為100%,那么交替20ms亮20ms滅的亮度就是50%,基于此, 我們就可以調節LED的亮度了 。如下圖

圖片

到此,我們就可以調節LED燈的亮度了(就是40ms內設置高電平的持續時間),這個就是大名鼎鼎的PWM調節亮度的原理了,而設置高電平的持續時間就是調節 占空比 (即高電平的時間除以周期數:20/40=50%)。

這里,我們 最重要的還是這個占空比, 比如周期是20ms,交替10ms亮10ms滅,我們看到的亮度還是50%(即占空比為10/20=50%)

接下來我們就看看程序怎么實現吧。

【程序實現】

點亮一個LED

首先,我們先從點亮一個LED燈開始,然后再一步一步實現一個呼吸燈的效果。我們使用的硬件如下:

開發板 零壹單片機培訓開發板
單片機型號 STC89C52
LED接口 P4^4腳

圖片

由原理圖我們知道,LED燈接到了單片機的P4^4腳,單片機輸出1,LED亮,輸出0,LED滅。由此,點亮一個LED的程序就很簡單了,如下

sbit LED1 = P4^4;
void LED_ON(){//LED亮
  LED1 = 1;
}
void LED_OFF(){//LED滅
  LED1 = 0;
}

點亮LED燈的程序還是很簡單,相信大家都會。

調節LED亮度

接下來我們就實現一個可以調節亮度的函數(即調節占空比),如下

//調節LED亮度
void set_led_luminance(unsigned int pwm_duty_cycle)
{
    static unsigned int s_Counter = 0;//計時
    //調節占空比
    if (pwm_duty_cycle >= s_Counter) {
        LED_ON();
    } else {
        LED_OFF();
    }
    //計數器開始計時
    s_Counter++;
  if(s_Counter > 255){
    //40ms時間到,清零重新計時
    s_Counter = 0;
  }    
}
void main(){
  while(1){
    set_led_luminance(128);
  }
}
  • 我們定義了一個靜態變量s_Counter作為 軟件定時器 ,s_Counter加到255后清零(這里相當于是一個周期的時間40ms,當然不是嚴格的40ms,只要周期小于40ms我們就看不到閃爍)
  • 函數的參數就是我們要調節的占空比,比如傳入的是128,占空比為128/255=50%

現在有了設置LED亮度的函數,那怎么讓它漸漸變亮再漸漸變暗,實現呼吸燈的效果呢?

實現呼吸燈

這個也很簡單,我們只要給set_led_luminance函數傳的參數從0慢慢加到255然后再從255慢慢減到0就可以了,如下

void breath_led(void){
  static int duty_cycle = 0;  
  static char flag = 1;
  //設置亮度
  set_led_luminance(duty_cycle);
  if(flag == 1){//占空比增加
    duty_cycle++;
    if(duty_cycle > 255){//大于255開始減少
      duty_cycle = 255;
      flag = 0;
    }
  }else{//占空比減少
    duty_cycle--;
    if(duty_cycle < 0){//小于0開始增加
      duty_cycle = 0;
      flag = 1;
    }
  }
}
void main(){
  while(1){
    breath_led();
  }
}
  • 定義一個靜態變量duty_cycle來保存占空比,當flag為1時,占空比慢慢增加到255,然后把flag設置成0 ,duty_cycle再從255慢慢減為0,如此循環就可以了。

哈哈,到這里你是不是覺得呼吸燈已經實現了, 然而,并不是 。不相信的同學可以自己試試上面的代碼哦。

那到底是哪里有問題呢?

這就是我們直接調用設置亮度的函數set_led_luminance()是有問題的,因為此函數執行一個周期需要40ms,也就是在這40ms期間是不可以改變占空比的,否則可就調不了亮度了。再來看看breath_led函數,每次調用完set_led_luminance()函數設置占空比后就立即改變了duty_cycle的值,并沒有延時40ms。

此時,我們還需要再加一個軟件定時器,定時超過40ms后修改duty_cycle的值,修改后的程序如下

void breath_led(void){
  static unsigned int s_breathCounter = 0;
  static int duty_cycle = 0;  
  static char flag = 1;  
  //設置亮度
  set_led_luminance(duty_cycle);
  //計時器增加
  s_breathCounter++;
  //超過40ms
  if(s_breathCounter > 511){
    //計時器設置為0,重新計時
    s_Counter = 0;
    if(flag == 1){//占空比增加
      duty_cycle++;
      if(duty_cycle > 255){//大于255開始減少
        duty_cycle = 255;
        flag = 0;
      }
    }else{//占空比減少
      duty_cycle--;
      if(duty_cycle < 0){//小于0開始增加
        duty_cycle = 0;
        flag = 1;
      }
    }
  }
}
  • 注意: 我們定時器的時間要大于40ms(也就是s_breathCounter的值要大于255)就可以, 但最好是周期的倍數 ,比如我們的周期為255(即0 ~ 255共256個數),我們設置成它的兩倍即256*2-1=511(即0~511共512個數)。

到這里,我們的呼吸燈就制作好了,是不是很簡單(* ̄︶ ̄)

接下來就是今天的彩蛋環節

雖然實現了呼吸燈的效果,但是代碼還是不夠簡潔和優雅,用了一堆if和else,我們想辦法再簡化一下。

首先化簡set_led_luminance()函數中的這一部分,如下圖所示

圖片

化簡之前,先講一個C語言的小知識,就是 按位與運算

1 & 0 = 01 & 1 = 10 & 0 = 00 & 1 = 0

由此,我們知道:不論是1還是0,和0做與運算都為0,

不論是1還是0,和1做與運算還是它本身

為了方便計算,我們采用16進制數(即前面加0x),比如0xff對應的十進制就是255;那么

一個小于等于0xff的數和0xff做與運算,結果還是它本身 ,如下

0x03 & 0xff = 0x03;
0xff & 0xff = 0xff;

那一個大于0xff的數和0xff做與運算呢?

0x100 & 0xff = 0x00;
0x1ff & 0xff = 0xff;
  • 結果就是這個數除以(0xff+1)的余數(即結果還是在0~0xff之間)

有了這個與運算,上面的代碼就可以化簡為

s_Counter++;
s_Counter = s_Counter & 0xff;
  • 這樣s_Counter的取值范圍就一直在0x00~0xff了

同樣的,上面breath_led函數中的軟件定時器也可以化簡一下,如下

//計時器增加
s_breathCounter++;
if (!(s_breathCounter & (0x1ff))) {
    duty_cycle++;
    duty_cycle &= 0x1ff;
}
if(duty_cycle > (0xff)){
  set_led_luminance(duty_cycle - (0xff));
}else{
  set_led_luminance( (0xff) - duty_cycle );
}
  • 第3行,0x1ff就是十進制的511,當s_breathCounter的值為(0x1ff+1)即512時條件成立,因為512&0x1ff=0,前面還有個感嘆號就是取非運算(準確的說就是s_breathCounter的值為512的倍數時條件成立,這樣都省去了s_breathCounter清零的操作了,不知道給大家解釋清楚了沒,大家要多想想),條件成立則占空比開始增加或減少

  • 那占空比的范圍不是0~ 255嗎,第5行怎么也變成0x1ff(511)了,別急,你再往下看第8行,我們又減去了0xff,所以占空比的范圍還是0~255

  • 第7~ 10行代碼的意思為:當duty_cycle > (0xff)時,即256~511,減去0xff,就相當于從1增加到255,亮度漸漸變亮

    當duty_cycle <= (0xff)時,即duty_cycle 從0增加到255,而設置的亮度為255 - duty_cycle ,相當于從255降到0,亮度 漸漸變暗 ,這樣就實現了呼吸燈的效果。

哈哈,你以為我們的簡化就結束了嗎?

no,no,no

其實第7到10行還可以更簡單一些。此時就需要用到取絕對值的函數了。

什么,用絕對值干嘛?

你看第10行0xff- duty_cycle就相當于duty_cycle - 0xff然后再取絕對值,好了,化簡后的代碼如下

set_led_luminance(ABS(duty_cycle - (0xff)));

取絕對值的宏函數如下

#define ABS(N) ((N) < 0 ? -(N) : (N))

最后我把整個化簡后的代碼也貼到下面

#define ABS(N)    ((N) < 0 ? -(N) : (N))
static void set_led_luminance(unsigned int pwm_duty_cycle)
{
    static unsigned int s_Counter = 0;
    if (pwm_duty_cycle >= s_Counter) {
        LED1 = 1;
    } else {
        LED1 = 0;
    }
    s_Counter++;
    s_Counter = s_Counter & 0xff;     
}
void breath_led(void){
  static unsigned int s_breathCounter = 0;
  static int duty_cycle = 0;  
  s_breathCounter++;
  if (!(s_breathCounter & (0x1ff))) {
    duty_cycle++;
    duty_cycle &= 0x1ff;
  }
  set_led_luminance(ABS(duty_cycle - (0xff)));
}
void main(){
  while(1){    
    breath_led();    
  }
}

怎么樣,是不是很簡潔(* ̄︶ ̄)

好了,到這里今天的呼吸燈就講完了,想和我一起重學51單片機的同學記得 點贊+關注, 這會加速我對文章更新的速度哦

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • led
    led
    +關注

    關注

    242

    文章

    23253

    瀏覽量

    660598
  • 單片機
    +關注

    關注

    6035

    文章

    44554

    瀏覽量

    634693
  • 51單片機
    +關注

    關注

    274

    文章

    5702

    瀏覽量

    123498
  • C語言
    +關注

    關注

    180

    文章

    7604

    瀏覽量

    136704
  • 呼吸燈
    +關注

    關注

    10

    文章

    110

    瀏覽量

    42723
收藏 人收藏

    評論

    相關推薦

    51單片機呼吸程序設計

    51單片機呼吸程序設計是基于單片機的原理與接口設計,采用單片機I/O口,加以C語言編程
    發表于 07-14 07:54

    基于51單片機呼吸怎樣設計

    課程設計報告書題目:基于51單片機呼吸設計信息工程學院課程設計任務書學 號1學生姓名專業(班級)設計題目基于51
    發表于 07-15 08:01

    怎么樣去設計基于單片機與PWM的呼吸

    51單片機(呼吸)C語言版基于單片機與PWM的呼吸
    發表于 07-15 06:02

    如何利用51單片機實現呼吸的設計?

    如何利用51單片機實現呼吸的設計?
    發表于 10-19 06:24

    基于51單片機實現呼吸設計

    實現效果如圖:注:該51單片機led引腳為P2^ 0 - P2^7,實際代碼按照引腳圖實現。代
    發表于 11-18 06:48

    51單片機呼吸實現源程序

    51單片機呼吸實現,源程序,hex文件都有,用到的led
    發表于 12-10 16:35 ?169次下載

    使用51單片機設計LED點陣呼吸效果程序免費下載

    本文檔的主要內容詳細介紹的是使用51單片機設計LED點陣呼吸效果程序免費下載。
    發表于 07-04 17:41 ?20次下載
    使用<b class='flag-5'>51</b><b class='flag-5'>單片機</b>設計<b class='flag-5'>LED</b>點陣<b class='flag-5'>呼吸</b><b class='flag-5'>燈</b>效果程序免費下載

    使用51單片機實現呼吸工程文件免費下載

    本文檔的主要內容詳細介紹的是使用51單片機實現呼吸工程文件免費下載。
    發表于 09-03 08:00 ?13次下載
    使用<b class='flag-5'>51</b><b class='flag-5'>單片機</b><b class='flag-5'>實現</b>的<b class='flag-5'>呼吸</b><b class='flag-5'>燈</b>工程文件免費下載

    使用單片機實現呼吸的設計程序免費下載

    本文檔的主要內容詳細介紹的是使用單片機實現呼吸的設計程序免費下載。
    發表于 03-24 08:00 ?2次下載
    使用<b class='flag-5'>單片機</b><b class='flag-5'>實現</b><b class='flag-5'>呼吸</b><b class='flag-5'>燈</b>的設計程序免費下載

    基于單片機與PWM實現呼吸的設計

    本設計是基于單片機的原理與接口設計,采用單片機I/O口,加以C語言編程實現LED漸亮再漸暗類似人的呼吸一樣的效果。
    發表于 05-19 08:00 ?22次下載
    基于<b class='flag-5'>單片機</b>與PWM<b class='flag-5'>實現</b><b class='flag-5'>呼吸</b><b class='flag-5'>燈</b>的設計

    使用單片機實現呼吸的程序免費下載

    本文檔的主要內容詳細介紹的是使用單片機實現呼吸的程序免費下載。
    發表于 06-05 17:35 ?45次下載
    使用<b class='flag-5'>單片機</b><b class='flag-5'>實現</b><b class='flag-5'>呼吸</b><b class='flag-5'>燈</b>的程序免費下載

    51單片機基于定時器的精準呼吸

    51單片機基于定時器的精準呼吸設計目的:實現LED
    發表于 11-21 09:51 ?50次下載
    <b class='flag-5'>51</b><b class='flag-5'>單片機</b>基于定時器的精準<b class='flag-5'>呼吸</b><b class='flag-5'>燈</b>

    51單片機心形實現旋轉呼吸流水編程

    51單片機心形實現旋轉呼吸流水編程
    發表于 11-23 16:20 ?23次下載
    <b class='flag-5'>51</b><b class='flag-5'>單片機</b>心形<b class='flag-5'>燈</b><b class='flag-5'>實現</b>旋轉<b class='flag-5'>呼吸</b><b class='flag-5'>燈</b>流水編程

    基于51單片機呼吸程序編寫

    利用51單片機編寫的呼吸小程序,實驗程序內容截圖分享~
    發表于 11-23 16:36 ?33次下載
    基于<b class='flag-5'>51</b><b class='flag-5'>單片機</b>的<b class='flag-5'>呼吸</b><b class='flag-5'>燈</b>程序編寫

    51單片機呼吸頻率怎么調節

    51單片機呼吸頻率的調節方法可以通過改變PWM(脈沖寬度調制)的工作周期和占空比來實現。在下面的文章中,我將詳細介紹如何使用
    的頭像 發表于 12-19 10:39 ?2582次閱讀
    主站蜘蛛池模板: 日本黄 色大片全| 色尼玛亚洲综合| 日日操天天操夜夜操| 亚洲AV无码乱码A片无码蜜桃| 一本色道久久综合亚洲精品蜜桃冫| 99国产在线精品观看二区| 国产精品久久久久AV麻豆| 久久热最新网站获取3| 三级网站视频| 51成人精品午夜福利AV免费七| 国产成人综合在线视频| 看美女大腿中间的部分| 我要搞av| a视频免费在线观看| 狠狠色狠狠色综合日日91app| 欧美乱码伦视频免费66网| 亚洲欧美中文字幕先锋| 成年人在线视频免费观看| 久久久久久电影| 歪歪漫画羞羞漫画国产| 99精品免费久久久久久久久日本| 国产午夜在线视频| 人妻洗澡被强公日日澡| 最近的2019中文字幕国语完整版| 国产超碰人人爱被IOS解锁| 可以看的黄页的网站| 亚洲 欧美 清纯 校园 另类 | 91国在线视频| 国产亚洲视频在线观看| 人妻夜夜爽99麻豆AV| 最近中文字幕MV免费高清在线| 国产午夜精AV在线麻豆| 日韩精品人成在线播放| 1000部做羞羞事禁片免费视频网站| 国产午夜精品一区理论片飘花| 日本精品久久久久中文字幕2| 2021自产拍在线观看视频| 黄色a级免费网站| 亚洲 欧美 国产 综合不卡| 成人在线观看免费视频| 嫩草影院久久精品|