?導(dǎo)讀:《藍(lán)橋杯單片機組》專欄文章是博主2018年參加藍(lán)橋杯的單片機組比賽所做的學(xué)習(xí)筆記,在當(dāng)年的比賽中,博主是獲得了省賽一等獎,國賽二等獎的成績。成績雖談不上最好,但至少問心無愧。如今2021年回頭再看該系列文章,仍然感觸頗多。為了能更好地幫助到單片機初學(xué)者,今年特地抽出時間對當(dāng)年的文章邏輯和結(jié)構(gòu)進(jìn)行重構(gòu),以達(dá)到初學(xué)者快速上手的目的。需要指出的是,由于本人水平有限,如有錯誤還請讀者指出,非常感謝。那么,接下來讓我們一起開始愉快的學(xué)習(xí)吧。
在前面一節(jié)《【藍(lán)橋杯單片機組模塊】1、硬件電路基礎(chǔ)知識 與 蜂鳴器模塊上手》中,我們提到了IO編程,其實與IO編程相對應(yīng)的還有一種編程方式叫MM編程,今天我們就來深入了解下這兩種編程方式吧...
前排提醒:MM編程僅作為拓展視野,比賽還是最好使用IO編程!
一、兩種編程方式簡介
兩種編程方式通過板上跳線 J13 進(jìn)行切換,比賽建議最好還是用 IO 編程。
1.1、IO 編程方式
IO編程方式,即我們之前一直在用的這種IO操作方式...
舉例來說,點亮所有LED的示例代碼如下:
P2 = ((P2&0x1F)|0x80);
P0 = 0x00; //點亮所有LED
P2 = P2 & 0x1F;
1.2、MM 編程方式
MM 編程方式通過 XBYTE 關(guān)鍵字來操作部分外設(shè)資源,這種方式能夠大大簡化外設(shè)程序設(shè)計。
CT107D 單片機綜合訓(xùn)練平臺的 MM 編程方式,是一 種可以像操作外部 RAM 存儲器一樣,操作 LED 指示燈、執(zhí)行結(jié)構(gòu)(蜂鳴器、繼電器 )、數(shù)碼管等外設(shè)資源的編程方式。當(dāng)然要實現(xiàn)這樣的編程方式,是與 CT107D 單片機綜合訓(xùn)練平臺的硬件設(shè)計具有關(guān)聯(lián)性的。
注:51 單片機可以外擴 64K 字節(jié)的 RAM 和 ROM 空間,傳統(tǒng)的 8051 單片機具有 16 位地址總線和 8 位數(shù)據(jù)總線,其中 P0 口作為數(shù)據(jù)和地址低字節(jié)的復(fù)用端口,P2 口作為高 8 位地址線。
對比學(xué)習(xí),IO 編程方式控制LED代碼片段如下:
P2 = ((P2&0x1F)|0x80);
P0 = 0x00; //點亮所有LED
P2 = P2 & 0x1F;
MM 編程方式控制LED代碼片段(僅1行代碼)如下:
XBYTE[0x8000] = 0x00; // XBYTE[0x8000] = 0xff;
Q1:為什么LED外設(shè)對應(yīng)的地址是 0x8000 呢,其他外設(shè)該如何確定呢?
答:由 CT107D單片機綜合訓(xùn)練平臺的硬件電路圖我們可以知道。
當(dāng) P2.7 = 1; P2.6 = 0; P2.5 = 0;
(Y4)(其它地址線不需要關(guān)心),即可將與 LED 指示燈模塊連接的74HC573“打通”,此時可以通過 P0口控制 LED 指示燈的狀態(tài),因此LED 指示燈模塊的地址為 0x8000。
以此類推,我們可以知道執(zhí)行機構(gòu)模塊(蜂鳴器、繼電器)的操作地址為 0xA000 (Y5);數(shù)碼管段碼端的操作地址為 0xE000 (Y7);數(shù)碼管位選端口的操作地址為 0xC000 (Y6)。
寫到這,對應(yīng)的規(guī)律也自然不言而喻了,各個外設(shè)對應(yīng)的操作地址如下圖所示。
Q2:MM編程中的 XBYTE 可以繼續(xù)深入講解一下么?
還是順藤摸瓜的思路,我們不難發(fā)現(xiàn):XBYTE
關(guān)鍵字定義在 absacc.h
文件中,而absacc.h
中的XBYTE
又定義在xdata
的0
地址處,如下圖所示。
注:
xdata
關(guān)鍵字你是不是又有疑惑了,這是個什么玩意呢?別急,后面也會一一介紹到的?。∣(∩_∩)O哈哈~)
這里寫圖片描述
二、兩種編程方式控制LED實驗
2.1、IO 編程方式控制 LED
#include "reg52.h"
#include "intrins.h"
//軟件自動生成的1s延時函數(shù)
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
// 主函數(shù)
void main(void)
{
while(1)
{
/* 注釋 1 :通過此句代碼將 P2.7 = 1 , P2.6 = 0 , P2.5 = 0 ,不改變 P2 口其它引腳
狀態(tài)。由 138 譯碼器的真值表可以知道此時譯碼器輸出端 Y4 處于低電平狀態(tài);因為
為 IO 編程方式,所以 Y4 和 GND 一起經(jīng)過或非門后,輸出高電平,并連接到 573
鎖存器的使能端口,將 573 鎖存器 “ 打通 “ ,此時鎖存器輸出端與單片機 P0 口狀態(tài)一
致。 */
P2 = ((P2&0x1f)|0x80);
/* 注釋 2 :因為 573 鎖存器已經(jīng) “ 打通 “ ,現(xiàn)在通過 P0 口輸出 0xff , 573 鎖存器的輸
出端也將輸出 0xff ,從而將所有 LED 熄滅。 */
P0 = 0xff;
/* 注釋 3 :通過此句代碼將 P2.7 = 0 , P2.6 = 0 , P2.5 = 0 ,不改變 P2 口其它引腳
狀態(tài)。由 138 譯碼器的真值表可以知道此時譯碼器輸出端 Y4 處于高電平狀態(tài);因為
為 IO 編程方式,所以 Y4 和 GND 一起經(jīng)過或非 門后,輸出低電平,并連接到 573
鎖存器的使能端口,將 573 鎖存器 “ 鎖存 “ ,此時鎖存器將輸入鎖存,輸出端口數(shù)據(jù)不
再受到 P0 口影響。 */
P2 &= 0x1f;
/* 1s延時 */
Delay1000ms();
/* 與注釋 1 相同 */
P2 = ((P2&0x1f)|0x80);
/* 注釋 2 :因為 573 鎖存器已經(jīng) “ 打通 “ ,現(xiàn)在通過 P0 口輸出 0x00 , 573 鎖存器的輸
出端也將輸出 0x00 ,從而將所有 LED 點亮。 */
P0 = 0x00;
/* 與注釋 3 相同 */
P2 &= 0x1f;
/* 1s延時 */
Delay1000ms();
}
}
2.2、MM 編程方式控制 LED
#include "reg52.h"
#include "absacc.h"
//軟件自動生成的1s延時函數(shù)
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
// 主函數(shù)
void main(void)
{
while(1)
{
XBYTE[0x8000] = 0x00; //LED 指示燈全部點亮
Delay1000ms();//延時1s
XBYTE[0x8000] = 0xff; //LED 指示燈全部熄滅
Delay1000ms();//延時1s
}
}
小結(jié):本篇文章以上一篇的遺留問題 “ IO 編程是什么?”為引子,詳細(xì)介紹了基于 CT107D 單片機綜合訓(xùn)練平臺的兩種編程方式:IO 編程和MM編程的原理及LED控制實例。從中我們看到雖然 MM 編程代碼較為短小精悍,但是不如 IO 編程代碼直觀方便。在后面的其他模塊學(xué)習(xí)及比賽中還是推薦大家使用 IO 編程方式,MM 編程僅僅作為一個擴展視野的東西即可。
希望大家多多支持我的原創(chuàng)文章。如有錯誤,請大家及時指正,非常感謝。