日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]從業(yè)將近十年!手把手教你單片機(jī)程序框架 第19講:開場白:上一節(jié)講了把74HC595驅(qū)動程序翻譯成類似單片機(jī)IO口直接驅(qū)動的方式。這節(jié)在上一節(jié)的驅(qū)動程序基礎(chǔ)上,開始講跑馬燈程序。我的跑馬燈程序看似簡單而且重復(fù),其實

從業(yè)將近十年!手把手教你單片機(jī)程序框架 第19講:

開場白:

上一節(jié)講了把74HC595驅(qū)動程序翻譯成類似單片機(jī)IO口直接驅(qū)動的方式。這節(jié)在上一節(jié)的驅(qū)動程序基礎(chǔ)上,開始講跑馬燈程序。我的跑馬燈程序看似簡單而且重復(fù),其實蘊含著鴻哥的大智慧。它是基于鴻哥的switch狀態(tài)機(jī)思想,領(lǐng)略到了它的簡單和精髓,以后任何所謂復(fù)雜的工程項目,都不再復(fù)雜。要教會大家一個知識點:通過本跑馬燈程序,加深理解鴻哥所有實戰(zhàn)項目中switch狀態(tài)機(jī)的思想精髓。

具體內(nèi)容,請看源代碼講解。

 

(1)硬件平臺:基于朱兆祺51單片機(jī)學(xué)習(xí)板。

 

(2)實現(xiàn)功能:第1個至第8個LED燈,先依次逐個亮,再依次逐個滅。第9至第16個LED燈一直滅。

 

(3)源代碼講解如下:

#include "REG52.H"

 

#define const_time_level_01_08  200  //第1個至第8個LED跑馬燈的速度延時時間

 

void initial_myself();    

void initial_peripheral();

void delay_short(unsigned int uiDelayShort); 

void delay_long(unsigned int uiDelaylong);

void led_flicker_01_08(); // 第1個至第8個LED的跑馬燈程序,逐個亮,逐個滅.

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

void led_update();  //LED更新函數(shù)

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

 

 

sbit hc595_sh_dr=P2^3;    

sbit hc595_st_dr=P2^4;  

sbit hc595_ds_dr=P2^5;  

 

unsigned char ucLed_dr1=0;   //代表16個燈的亮滅狀態(tài),0代表滅,1代表亮

unsigned char ucLed_dr2=0;

unsigned char ucLed_dr3=0;

unsigned char ucLed_dr4=0;

unsigned char ucLed_dr5=0;

unsigned char ucLed_dr6=0;

unsigned char ucLed_dr7=0;

unsigned char ucLed_dr8=0;

unsigned char ucLed_dr9=0;

unsigned char ucLed_dr10=0;

unsigned char ucLed_dr11=0;

unsigned char ucLed_dr12=0;

unsigned char ucLed_dr13=0;

unsigned char ucLed_dr14=0;

unsigned char ucLed_dr15=0;

unsigned char ucLed_dr16=0;

 

unsigned char ucLed_update=0;  //刷新變量。每次更改LED燈的狀態(tài)都要更新一次。

 

unsigned char ucLedStep_01_08=0; //第1個至第8個LED跑馬燈的步驟變量

unsigned int  uiTimeCnt_01_08=0; //第1個至第8個LED跑馬燈的統(tǒng)計定時中斷次數(shù)的延時計數(shù)器

 

unsigned char ucLedStatus16_09=0;   //代表底層74HC595輸出狀態(tài)的中間變量

unsigned char ucLedStatus08_01=0;   //代表底層74HC595輸出狀態(tài)的中間變量

 

void main() 

  {

   initial_myself();  

   delay_long(100);   

   initial_peripheral(); 

   while(1)   

   {

      led_flicker_01_08(); // 第1個至第8個LED的跑馬燈程序,逐個亮,逐個滅.

          led_update();  //LED更新函數(shù)

   }

 

}

 

 

void led_update()  //LED更新函數(shù)

{

 

   if(ucLed_update==1)

   {

       ucLed_update=0;   //及時清零,讓它產(chǎn)生只更新一次的效果,避免一直更新。

 

       if(ucLed_dr1==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x01;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xfe;

           }

 

       if(ucLed_dr2==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x02;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xfd;

           }

 

       if(ucLed_dr3==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x04;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xfb;

           }

 

       if(ucLed_dr4==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x08;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xf7;

           }

 

 

       if(ucLed_dr5==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x10;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xef;

           }

 

 

       if(ucLed_dr6==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x20;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xdf;

           }

 

 

       if(ucLed_dr7==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x40;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0xbf;

           }

 

 

       if(ucLed_dr8==1)

           {

              ucLedStatus08_01=ucLedStatus08_01|0x80;

           }

           else

           {

              ucLedStatus08_01=ucLedStatus08_01&0x7f;

           }

 

       if(ucLed_dr9==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x01;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xfe;

           }

 

       if(ucLed_dr10==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x02;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xfd;

           }

 

       if(ucLed_dr11==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x04;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xfb;

           }

 

       if(ucLed_dr12==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x08;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xf7;

           }

 

 

       if(ucLed_dr13==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x10;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xef;

           }

 

 

       if(ucLed_dr14==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x20;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xdf;

           }

 

 

       if(ucLed_dr15==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x40;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0xbf;

           }

 

 

       if(ucLed_dr16==1)

           {

              ucLedStatus16_09=ucLedStatus16_09|0x80;

           }

           else

           {

              ucLedStatus16_09=ucLedStatus16_09&0x7f;

           }

 

       hc595_drive(ucLedStatus16_09,ucLedStatus08_01);  //74HC595底層驅(qū)動函數(shù)

 

   }

}

 

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引腳的上升沿把數(shù)據(jù)送入寄存器

         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引腳的上升沿把數(shù)據(jù)送入寄存器

         delay_short(15); 

         hc595_sh_dr=1;

         delay_short(15); 

 

         ucTempData=ucTempData<<1;

   }

 

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

   delay_short(15); 

   hc595_st_dr=1;

   delay_short(15); 

 

   hc595_sh_dr=0;    //拉低,抗干擾就增強(qiáng)

   hc595_st_dr=0;

   hc595_ds_dr=0;

 

}

 

/* 注釋一:

* 以下程序,看似簡單而且重復(fù),其實蘊含著鴻哥的大智慧。

* 它是基于鴻哥的switch狀態(tài)機(jī)思想,領(lǐng)略到了它的簡單和精髓,

* 以后任何所謂復(fù)雜的工程項目,都不再復(fù)雜。

*/

void led_flicker_01_08() //第1個至第8個LED的跑馬燈程序,逐個亮,逐個滅.

{

  switch(ucLedStep_01_08)

  {

     case 0:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr1=1;  //第1個亮

 

               ucLed_update=1;  //更新顯示

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

           }

           break;

     case 1:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr2=1;  //第2個亮

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=2; //切換到下一個步驟

           }

           break;

     case 2:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr3=1;  //第3個亮

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=3; //切換到下一個步驟

           }

           break;

     case 3:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr4=1;  //第4個亮

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=4; //切換到下一個步驟

           }

           break;

     case 4:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr5=1;  //第5個亮

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=5; //切換到下一個步驟

           }

           break;

     case 5:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr6=1;  //第6個亮

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=6; //切換到下一個步驟

           }

           break;

     case 6:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr7=1;  //第7個亮

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=7; //切換到下一個步驟

           }

           break;

     case 7:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr8=1;  //第8個亮

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=8; //切換到下一個步驟

           }

           break;

     case 8:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr8=0;  //第8個滅

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=9; //切換到下一個步驟

           }

           break;

     case 9:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr7=0;  //第7個滅

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=10; //切換到下一個步驟

           }

           break;

     case 10:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr6=0;  //第6個滅

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=11; //切換到下一個步驟

           }

           break;

     case 11:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr5=0;  //第5個滅

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=12; //切換到下一個步驟

           }

           break;

     case 12:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr4=0;  //第4個滅

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=13; //切換到下一個步驟

           }

           break;

     case 13:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr3=0;  //第3個滅

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=14; //切換到下一個步驟

           }

           break;

     case 14:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr2=0;  //第2個滅

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=15; //切換到下一個步驟

           }

           break;

     case 15:

           if(uiTimeCnt_01_08>=const_time_level_01_08) //時間到

           {

               uiTimeCnt_01_08=0; //時間計數(shù)器清零

 

               ucLed_dr1=0;  //第1個滅

 

               ucLed_update=1;  //更新顯示

               ucLedStep_01_08=0; //返回到最開始處,重新開始新的一次循環(huán)。

           }

           break;

 

   }

 

}

 

 

void T0_time() interrupt 1

{

  TF0=0;  //清除中斷標(biāo)志

  TR0=0; //關(guān)中斷

 

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

  {

      uiTimeCnt_01_08++;  //累加定時中斷的次數(shù),

  }

 

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

  TL0=0x2f;

  TR0=1;  //開中斷

}

 

void delay_short(unsigned int uiDelayShort) 

{

   unsigned int i;  

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

   {

     ;   //一個分號相當(dāng)于執(zhí)行一條空語句

   }

}

 

void delay_long(unsigned int uiDelayLong)

{

   unsigned int i;

   unsigned int j;

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

   {

      for(j=0;j<500;j++)  //內(nèi)嵌循環(huán)的空指令數(shù)量

          {

             ; //一個分號相當(dāng)于執(zhí)行一條空語句

          }

   }

}

 

 

void initial_myself()  //第一區(qū) 初始化單片機(jī)

{

 

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

 

 

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

  TL0=0x2f;

 

 

}

 

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

{

  EA=1;     //開總中斷

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

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

 

}

總結(jié)陳詞:

這節(jié)講了在第1個至第8個LED燈中,先依次逐個亮再依次逐個滅的跑馬燈程序。下一節(jié)我們略作修改,繼續(xù)做跑馬燈的程序,要求在第9個至第16個LED燈中,依次逐個亮燈并且每次只能亮一個燈(其它的都滅),依次循環(huán),我們該如何編寫程序?欲知詳情,請聽下回分解-----依次逐個亮燈并且每次只能亮一個燈的跑馬燈程序。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

8位單片機(jī)在嵌入式設(shè)計領(lǐng)域已經(jīng)成為半個多世紀(jì)以來的主流選擇。盡管嵌入式系統(tǒng)市場日益復(fù)雜,8位單片機(jī)依然不斷發(fā)展,積極應(yīng)對新的挑戰(zhàn)和系統(tǒng)需求。如今,Microchip推出的8位PIC?和AVR?單片機(jī)系列,配備了先進(jìn)的獨立...

關(guān)鍵字: 單片機(jī) 嵌入式 CPU

中國 上海,2025年8月28日——全球領(lǐng)先的智能傳感和發(fā)射器解決方案供應(yīng)商艾邁斯歐司朗(SIX:AMS)今日宣布,其全新UV-C LED在輻射滅菌領(lǐng)域取得重大技術(shù)突破,并獲得評估認(rèn)可。

關(guān)鍵字: LED 發(fā)射器 光電半導(dǎo)體

在嵌入式系統(tǒng)開發(fā)中,程序燒錄是連接軟件設(shè)計與硬件實現(xiàn)的關(guān)鍵環(huán)節(jié)。當(dāng)前主流的單片機(jī)燒錄技術(shù)已形成ICP(在電路編程)、ISP(在系統(tǒng)編程)、IAP(在應(yīng)用編程)三大技術(shù)體系,分別對應(yīng)開發(fā)調(diào)試、量產(chǎn)燒錄、遠(yuǎn)程升級等不同場景。...

關(guān)鍵字: 單片機(jī) ISP ICP IAP 嵌入式系統(tǒng)開發(fā)

在嵌入式系統(tǒng)開發(fā)中,看門狗(Watchdog Timer, WDT)是保障系統(tǒng)可靠性的核心組件,其初始化時機(jī)的選擇直接影響系統(tǒng)抗干擾能力和穩(wěn)定性。本文從硬件架構(gòu)、軟件流程、安全規(guī)范三個維度,系統(tǒng)分析看門狗初始化的最佳實踐...

關(guān)鍵字: 單片機(jī) 看門狗 嵌入式系統(tǒng)

在LED照明技術(shù)向高能效、低電磁干擾(EMI)方向演進(jìn)的過程中,電流模式控制與動態(tài)負(fù)載調(diào)整算法的協(xié)同優(yōu)化成為突破技術(shù)瓶頸的核心路徑。本文將從控制架構(gòu)創(chuàng)新、動態(tài)負(fù)載補(bǔ)償機(jī)制及EMI抑制策略三個維度,揭示新一代LED驅(qū)動器的...

關(guān)鍵字: LED 動態(tài)負(fù)載調(diào)整算法 EMI

在全球倡導(dǎo)節(jié)能減排的大背景下,家電產(chǎn)品的能耗問題日益受到關(guān)注。電視機(jī)作為家庭中使用頻率較高的電器之一,其能耗的降低對于節(jié)約能源和減少碳排放具有重要意義。LED 驅(qū)動技術(shù)作為影響電視機(jī)能耗的關(guān)鍵因素,正不斷發(fā)展和創(chuàng)新,為實...

關(guān)鍵字: 驅(qū)動技術(shù) 能耗 LED

本文中,小編將對單片機(jī)予以介紹,如果你想對它的詳細(xì)情況有所認(rèn)識,或者想要增進(jìn)對它的了解程度,不妨請看以下內(nèi)容哦。

關(guān)鍵字: 單片機(jī) 開發(fā)板 Keil

LED是一種能發(fā)光的半導(dǎo)體電子元件,這種電子元件早期只能發(fā)出低光度的紅光,隨著技術(shù)的不斷進(jìn)步,現(xiàn)在已發(fā)展到能發(fā)出可見光、紅外線及紫外線的程度,光度也有了很大的提高。

關(guān)鍵字: LED

PCB設(shè)計在EMI抑制中起著關(guān)鍵作用。合理的布局布線能夠有效減少信號的電磁輻射和相互干擾。首先,應(yīng)將功率電路和控制電路進(jìn)行物理隔離,避免功率電路中的大電流、高電壓信號對控制電路造成干擾。功率器件和電感等高頻器件應(yīng)盡量靠近...

關(guān)鍵字: LED 開關(guān)電源

隨著單片機(jī)系統(tǒng)越來越廣泛地應(yīng)用于消費類電子、醫(yī)療、工業(yè)自動化、智能化儀器儀表、航空航天等各領(lǐng)域,單片機(jī)系統(tǒng)面臨著電磁干擾(EMI)日益嚴(yán)重的威脅。電磁兼容性(EMC)包含系統(tǒng)的發(fā)射和敏感度兩方面的問題。

關(guān)鍵字: 單片機(jī) 電磁兼容
關(guān)閉