ddw:;程序開始 clrp1.0;led1亮 acalldelay;調用延時子程序 setbp1.0;led1滅 clrp1.1;換燈,同上 acalldelay setbp1.1 clrp1.2 acalldelay setbp1.2 clrp1.3 acalldelay setbp1.3 clrp1.4 acalldelay setbp1.4 clrp1.5 acalldelay setbp1.5 clrp1.6 acalldelay setbp1.6 clrp1.7 acalldelay setbp1.7 ljmpddw;返回到開始循環 delay:;延時子程序 movr1,#50 ad10: movr2,#100 ad11: movr3,#100 djnzr3,$ djnzr2,ad11 djnzr1,ad10 ret;延時子程序結束,返回到調用處的下一句 end 請將上面的程序保存為1led.asm,進行編譯,並燒寫到at89s51中,之後將89s51安裝到套件的實驗部份插座上實驗,這回顯示的就是“流水燈”的效果了!?回過頭,讓我們看看延時子程序是怎樣工作的:單片機內部有不少寄存器,這些寄存器在單片機通電時,你可以給他寫入數據(是單片機按你程序要求寫的數據,而不是編程器寫的),當第二次給他寫入新數據時,前次的數據就被新數據覆蓋;當然也可以從寄存器中讀取數據。當單片機沒有電源供給時,寄存器內部的數據也隨即消失;這些寄存器人們叫他ram,而用編程器將我們編寫的程序燒寫到單片機中的存儲器叫rom;現在,我們應該清楚:ram是讓程序去使用的,rom是我們編寫的程序存放的地方!前面說過,單片機內部有不少ram,本實驗用的at89c51有多少寄存器?我們現在不必關心,現在只須知道單片機內部有名叫r0~r7的這8個寄存器。這8個寄存器每個都由8個單獨的位寄存器組成,最大存放數據為二進制的11111111,十六進制=ff,十進制=255。在使用時注意不要大於其有效范圍。上面延時程序中,先用到movr1,#50,mov是移動的意思,該句是將50這個十進制數放到r1中;50是立即數,按匯編語言要求前面要加“#”號,匯編語言還規定,十六進制數後面要加“?h”,十六進制數的高位是字母時在字母前面還要加“0”,例如:#0f8h;二進制數後面加“b”,例如:#11110000b。十進制不加,例如:#100。延時程序的第二、三句為:movr2,#100;movr3,#100;這兩句意思同前。第四句中djnzr3,$的意思是將r3裡面的數減1後如果r3不等於0則跳到後面指定的程序位置,這裡的“$”既要跳轉的程序位置,“$”代表當前語句處,也就是說,r3不等於0,程序返回再次執行本句。如果r3減1後等於0,程序結束本句,繼續執行下面的語句。延時程序的最後一句是ret,意思是退出本子程序,返回到調用本子程序處的下一句。根據上面的解釋,一進入延時子程序首先為r1,r2,r3寄存器裝入我們需要的數據,然後先對r3進行減數,每次減1,r3減完後減r2,減r2時就費事啦,因為r2每減1後不為0需要跳轉到ad11標號處執行下面的語句,此時r3再次裝入數據100,並且還要再次對r3進行減數......,r2減完後減r1,減r1的過程你研究研究看看。每執行djnz?rn,rel(rn指r0~r7,rel指轉移地址)指令一次,需要2個機器周期,單片機需耗時2us(指本實驗),若忽略裝數等語句,延時子程序從開始到結束,單片機共耗時100*100*50*2ns,既1000000us=1秒!若加上裝數等語句的耗時,延時時間大於1秒。到此,我們做的流水燈已成功,原理大致也明白啦,若你自認為這一課你完全明白了,那請你將“流水燈”的流向改變一下,也可以改為兩邊向內流,內部向外流......,我想你一定能用前面學到的方法實現這些功能。可能有些高手說,前面的編程方法是最最笨的!,不錯!但玩單片機初期不必講究語言的簡練,只要能完成預先要求就好,這是初學者要知道的。那麼還有更好的編程思路嗎?有!請繼續學習下節課
做流水燈實驗詳解三
在上節課中讓led流水是去逐個控制p1端口的每個位來實現的,那麼我們在程序一開始就給p1口送一個數,這個數本身就讓p1.0先低,其他位為高,然後讓這個數據向高位移動不就實現“流水”效果啦?的確如此!可惜,8051沒有讓p1數據移動的指令,但有對累加器acc中數據左移或右移的指令,acc是8051單片機內部算術邏輯單元中的一個“寄存器”(這裡叫他寄存器是不正確的,但你可以先這樣理解,acc在指令中常寫為a),他在數據傳輸和數據處理過程中作用十分重要,acc為8位。他可與片內所有單字節寄存器交換數據,實際上p1和其他端口在單片機中也是一個寄存器。這樣我們可以將需移動的數據先放到acc中,讓其移動,然後將acc移動後的數據再轉送到p1口,這樣同樣可以實現“流水”效果。
程序如下:ddw:;開始 movacc,#0feh;acc中先裝入led1熄滅的數據(即二進制的11111110) movp1,acc;將acc的數據送p1口 movr0,#7;因上句送到?p1口的數據就熄滅了一位,所以將數據再移動7次就完成一個8位流水過程 loop:;數據移動循環 rla;將acc中的數據左移一位 movp1,a;把acc移動過的數據送p1口顯示 acalldelay;調用延時 djnzr0,loop;沒有移動夠7次繼續移動 ljmpddw;移動完7次後跳到開始重來,以達到循環流動效果 delay:;延時子程序,就是上節課中的延時子程序 movr1,#50 adl0: movr2,#100 adl1: movr3,#100 djnzr3,$ djnzr2,ad11 djnzr1,ad10 ret;延時子程序結束,返回到調用處的下一句 end;本匯編程序到此結束
接下來,將上述程序編譯,並燒寫到前面我們的實驗芯片中,流水效果與第二節課的一樣。其實8051單片機有111條指令,這111條指令好比以前我們使用數字傳呼機時的“短語代碼”一樣,可以用幾個“短語代碼”去表示一句完整、通順的語句段落。有的指令常用,有的指令不常用,只要遵守語法規則,你可以用這些指令“組合”成你想象到的任何程序。當然,有時一條指令可以替代很多條指令,這樣會使程序簡捷,費碼減少,在編寫較大程序時可以讓程序存儲器放得下你需要的代碼。這也是單片機高手所追求的。當然,在程序存儲器空間不成問題時,你不這樣做但也可以達到預期的功能,這也不算錯。單片機內部還有很多“部件”我們只是用到什麼說什麼,很不系統。但是我也不想系統的介紹這些,因系統介紹單片機結構和指令的書很多,何況寫的遠比我好,因此,希望你在看本講座的過程中,還要結合正規的教材學習其更多的指令和“部件”。
這是我在別的地方找過來的,希望對你有所幫助。
我用的是wave6000編譯的。
上一页 [1] [2]
|
|