流水燈,學單片機時,編程第一課的內容,多少小伙伴的單片機之路都是從流水燈開始的。那有沒有想過,我們能用幾種方式來寫流水燈,各有什么優缺點呢?今天小代就來聊聊流水燈的寫法。
硬件介紹:小代采用自己畫的STC15開發板,8位LED接P0口,陽極驅動,共陰連接方式,就這么多。
(實際測試時用的數碼管模擬,昨天剛接了線,懶得再次重新接線,直接用數碼管來代替LED,原理都一樣,能驗證就好)
1.初學者入門法
直接上代碼看后再說
#include"STC15.h"#defineu8unsignedchar#defineu16unsignedintvoid delay_ms(u16x);//ms延時函數void main(){u8led=0x01;u8i=0;P0M1=0x00;//STC15單片機把IO設為推挽輸出P0M0=0xff;P2M1=0x00;P2M0=0xff;P2=0xff;//數碼管位選驅動,硬件介紹上已經說明原因while(1){//①初學者常見delay延時方式流水燈led=0x01;for(i=0;i<8;i++){????????????P0=led;????????????delay_ms(1000);????????????led=led<<1;????????}?????}??????//while(1)?結束}//main結束 //************************************//功能:ms延時函數?//參數:x--延時的時間長短,x=1000約為1s 24M晶振//作者:小代//微信關注:單片機技術宅//************************************void delay_ms(u16?x){????u16?i,j,k;????for(k=0;k
一看代碼37行,太多了,仔細一看,注釋和空行占據了一大半,這樣一想就開心多了。這個代碼沒有更多需要解釋的,采用最常見的,初學者最喜歡的方式,delay延時方式實現,下面聊優缺點。
優點:簡單粗暴好理解,能看懂文字(字母)的都知道
缺點:代碼執行效率太低,太低,太低
程序流程圖如下圖所示,CPU更多的時間是花在“等待1s”上,效率太低,單純的這樣演示流水燈,那這個程序沒有任何問題,當在這個程序中再加入其它的程序,必然會出問題,第一流水燈會被執行慢了,第二,新加入的功能反應會很慢,特別是一些實時性有要求的代碼。加到這里就會有問題了。為了解決這些問題,我們引出了第二種方式的流水燈。
2.記錄主程序執行次數方式
還是先上代碼再聊
#include "STC15.h"
#define u8 unsigned char
#define u16 unsigned int
//************************************
//功能:主函數入口 main
//參數:無
//作者:小代
//微信關注:單片機技術宅
//************************************
voidmain(){
u8 led=0x01;
u16main_cnt=0;
P0M1=0x00; //STC15單片機把IO設為推挽輸出
P0M0=0xff;
P2M1=0x00;
P2M0=0xff;
P2=0xff; //數碼管位選驅動,硬件介紹上已經說明原因
while(1){
//②主程序循環次數實現延時方式流水燈
main_cnt++; //主程序每運行一次,main_cnt將會被加1
//通過if語句實現內部代碼塊的運行速率降低
//只有主程序循環60000此后,if語句內的代碼塊才被執行一次
//如若需要更低的執行速率,可以采用兩層變量嵌套計數
P0=led;
if(main_cnt>60000){
main_cnt=0; //次數記錄清零,為下一次記錄準備
if(led==0x80){
led=0x01;
}
else{
led=led<<1;
}
}
} //while(1) 結束
}
//main結束
還是40+行代碼,還是注釋+空行占據了一半左右。以上代碼最大的特點就是沒有之前執行效率很低的delay函數,也算是升級了吧。沒了delay延時,那如何實現等待的呢?小代慢慢聊。
在while(1)循環里的第21行,只要主程序每運行一次,21行就會對變量main_cnt加1,這個變量定義為16位無符號類型,最大可以到65535,在此,小代記錄60000此后就去點亮下一個流水燈的LED,顯示效果比方法1的略快,以上注釋也說了,如果單一變量記錄次數沒法滿足需要的等待時間,可以采用兩個變量嵌套記錄的方式。
通過這種方式點亮LED燈,真正的點燈程序段只有在主程序運行60000后才會被運行到一次。仔細看主程序里面,其實就只有一條語句,那就是對main_cnt做加1處理,完了每次都去判斷一下main_cnt有沒有到60000了,到了后才去處理LED點燈。下面聊聊優缺點。
優點:程序簡單,效率高
缺點:點燈的速度會隨著主程序內循環語句的增多而降低。
也就是說如果主程序里增加了其他的運行語句,那這里控制點燈的記錄次數值就不再是60000,需要減小,或者說60000得到的效果就會讓流水燈變慢。程序流程圖如下圖
到這里,程序執行效率問題我們已經解決了,在這程序基礎上加入其它代碼后,各個功能還是能運行起來,但是還是有問題,流水燈的速度會改變,為解決這個問題,小代引出了第三種方法。
3.定時器實現
說到定時器,首先還得知道中斷的原理,但是,中斷和定時器,學單片機連這兩個知識點都沒學會,那怎好意思說你學過單片機。也就是說中斷和定時器就像單片機驅動IO口一樣的普通,一樣的簡單,不要想的多復雜。還是先上代碼再聊。
#include "STC15.h"
#define u8 unsigned char
#define u16 unsigned int
voiddelay_ms(u16 x); //ms延時函數
voidTimer0Init(void); //2毫秒@24.000MHz
u16 timer0_cnt=0;
bit timer0_1s_flag=0;
//************************************
//功能:主函數入口 main
//參數:無
//作者:小代
//微信關注:單片機技術宅
//************************************
voidmain(){
u8 led=0x01;
u16main_cnt=0;
P0M1=0x00; //STC15單片機把IO設為推挽輸出
P0M0=0xff;
P2M1=0x00;
P2M0=0xff;
P2=0xff; //數碼管位選驅動
Timer0Init(); //定時器初始化
while(1){
//③通過定時器中斷控制流水燈效果
//主程序里只做LED的驅動
//如果任務少,判斷標志位置位都可以放到定時器中斷里
//這里統一放到了主循環里
P0=led;
if(timer0_1s_flag==1){
timer0_1s_flag=0; //清除標志位
if(led==0x80){ //是否移動了8次
led=0x01;
}
else{
led=led<<1;
}
}
}//while(1) 結束
}
//main結束
//************************************
//功能:定時器初始化函數
//參數:無
//作者:小代
//微信關注:單片機技術宅
//************************************
voidTimer0Init(void) //2毫秒@24.000MHz
{
AUXR|=0x80; //定時器時鐘1T模式
TMOD&=0xF0; //設置定時器模式
TL0=0x80; //設置定時初值
TH0=0x44; //設置定時初值
TF0=0; //清除TF0標志
TR0=1; //定時器0開始計時
ET0=1; //開中斷
EA=1;
}
//************************************
//功能:Timer0中斷函數 2ms中斷一次
//參數:無
//作者:小代
//微信關注:單片機技術宅
//************************************
voidtimer0_int (void) interrupt 1 {
TF0=0;
timer0_cnt++;
if(timer0_cnt==500){
timer0_1s_flag=1;
timer0_cnt=0;
}
}
看到這,一看代碼量暴增,一下子就是原來的兩倍,其實更多的也還是注釋,代碼量是有所增加,因為用到了定時器和中斷,需要對定時器進行初始化,完了還需要一個中斷函數。在這個程序,定時T0每2ms中斷一次,進入中斷后,中斷處理函數直接對timer0_cnt變量加1記錄,當記錄500次后,說明1s時間到,此時置位1s時間標志位timer0_1s_flag=1。在主程序,只做點燈和判斷1s時間到來沒有,當1s時間到來后,主程序就去處理LED的移位操作。
優點:效率極高,實時性好,時間穩定
缺點:非要說,那就是用到了定時器和中斷,初學者會覺得難
通過這種方式實現流水燈,還可以在主程序中加入其它的代碼,并不會影響到流水燈的運行。其實這只是一個最簡單的模型,在復雜項目中同樣可以用這模型,比如,1s點亮一個LED燈,1ms刷新一次數碼管,10ms讀取一次按鍵,500ms讀取一次ADC的值等等。這樣很多的功能都可以采用這樣的模型來實現,并且各個功能之間是互不干擾的。
到此,今天的內容聊完了,其實第三種方式就是“狀態機”或者“分時處理”等等一些比較高級的名稱就是這么一回事。下次再聽到這些高大上的名稱時,一定要知道,這并不是什么高深的東西。更重要的是在以后的復雜項目中要會用這樣的方式去處理各個功能之間的切換。
責任編輯:lq
-
單片機
+關注
關注
6032文章
44514瀏覽量
632981 -
流水燈
+關注
關注
21文章
432瀏覽量
59636 -
代碼
+關注
關注
30文章
4747瀏覽量
68349
原文標題:你有幾種方法寫流水燈
文章出處:【微信號:chuxue_MCU,微信公眾號:單片機技術宅】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論