當前位置:首頁 > 單片機 > 單片機
[導讀] (1)最常用的PAGE和BANKEMC的IC是分幾個page和幾個bank的,低端的EM78P156等只有一個bank和一個page,所以不用切換,新一點的IC基本都要切換的了,這個經(jīng)常用的冬冬,做成宏就最合適,代碼如下:/****

(1)最常用的PAGE和BANK
EMC的IC是分幾個page和幾個bank的,低端的EM78P156等只有一個bank和一個page,所以不用切換,新
一點的IC基本都要切換的了,這個經(jīng)常用的冬冬,做成宏就最合適,代碼如下:

/*****************************************************






*BANKSELECTION*
*****************************************************/
BANKmacronum
ifnum==0
bcR4,6
bcR4,7
elseifnum==1
bsR4,6
bcR4,7
elseifnum==2
bcR4,6
bsR4,7
elseifnum==3
bsR4,6
bsR4,7
else
message"warring!"
endif
endm

/*****************************************************
*PAGESELECTION*
*****************************************************/
PAGEmacronum
ifnum==0

bcpsw,5
bcpsw,6
elseifnum==1
bspsw,5
bcpsw,6
elseifnum==2
bcpsw,5
bspsw,6
elseifnum==3
bspsw,5
bspsw,6
else
message"warring!"
endif
endm

調用格式是
BANKnum(num是0~3代表4個BANK)
PAGEnum(num是0~3代表4個PAGE)
這樣方便多了,而且不會出錯

(2)帶參數(shù)的宏
作為例子,我們假定定義一個宏“FUNC”,帶兩個參數(shù),功能是單純的將傳進來的數(shù)據(jù)傳到PORT5和
PORT6而已,演示用法。
首先看定義:

FUNCMACROARG1,ARG2
MOV A,@ARG1
MOV PORT5,A
MOV A,ARG2
MOV PORT6,A
ENDM

注意到,為什么ARG1前面有個@的符號的呢?這個代表的是宏接收的第一個參數(shù)是一個立即數(shù),而AR
G2沒有那個符號,代表宏接收的第二個參數(shù)是一個寄存器的地址。
好了,看在主程序怎么用:

FUNC0X10,0X20

這樣就OK了,編輯器編譯的時候,會自動進行宏替換,將0X10這個立即數(shù)作為第一個參數(shù)傳遞進去,而
將0X20寄存器的內容,作為第二個參數(shù)傳遞進去,進行宏替換之后的結果,等效于:
MOV A,@0x10
MOV PORT5,A
MOV A,0x20
MOV PORT6,A
(3)說一點C語言的一種良好風格
C語言上面有一種比較好的編程風格,給個C51的例子:
我們想設置TIMER0在模式1,TIMER1在模式2
一般教程的思維和代碼就是:
翻資料看看TMOD的位的定義,然后慢慢算,模式1和模式2該給什么值,最后寫指令:
TMOD = 0x21;
完工…..
其實我們還可以有另外一種辦法,那就是這樣寫:

TMOD = CT0_MODE1 | CT1_MODE2 ;

其中里面用到一些宏,具體定義是:
#define CT0_MODE0 0x00 // Timer0/Counter0 Mode
#define CT0_MODE1 0x01
#define CT0_MODE2 0x02
#define CT0_MODE3 0x03

#define CT1_MODE0 0x00 // Timer1/Counter1 Mode
#define CT1_MODE1 0x10
#define CT1_MODE2 0x20
#define CT1_MODE3 0x30

TMOD = CT0_MODE1 | CT1_MODE2 ;
這個應該很容易看的懂吧?中間的 “|”是或運算,這個就是編譯器在編譯之前先做的運算了,具體CT
0_MODE1 代表 0X01 CT1_MODE2 代表0x20,然后“與運算”之后結果就是0X21 了,跟上面一樣。但是老
實說,大家愿意用哪個辦法去做呢?我會毫不猶豫的選擇第二種。

(4)用我們的EMC的匯編編譯器模仿這種風格
我們的EMC匯編編譯器同樣支持這種編譯時候的運算,讓編譯器幫我們先處理一些基本的運算,面對C編
譯器這個小功能真實見慣不怪,但是匯編編譯器也能,小小的有點意外。

EMC的芯片的功能寄存器分配,真有點亂七八糟,唉,看著吐血,用定一種型號的IC那還好,如果用了幾
種IC的話,那個叫郁悶,一個例子就是EM78P447 和EM78P156,本來前者是升級版,但是為啥有些控制差
別會那么大呢,每次都要瘋狂的查DATASHEET,為了緩慢腦細胞的死亡速度,俺決定用宏……

例如: 我們需要開啟EM78P260的TCCA計數(shù)器來用,初始化時候的工作,我們用帶參數(shù)的宏來實現(xiàn)。分幾
步走

1 首先定義一個宏,以后可以用這個宏來初始化了
TCCA_SETUP MACRO TCCACNT
clr 0x04 ; 0x04 是用來做臨時寄存器用的
ior 0x08 ; 0x08是控制TCCA的寄存器
and a,@0xf8 ; 屏蔽掉TCCA相關的
MOV 0x04,a
MOV a,@TCCACNT ; 讀取傳遞進來的參數(shù)
or a,0x04
iow 0x08
MOV a,@TCCACNT ; 如果允許TCCA的話,開TCCA的中斷
and a,@0x04 ; 否則直接跳出
jbc 0x03,2
jmp $+4
ior 0x0f
or a,@0x08
iow 0x0f
ENDM
(因為這個程序在初始化階段,所以改變0x04寄存器沒有所謂,不過在正常跑的時候千萬不要亂來,那
個是會切換BANK的,跑飛了可不是說著玩,當然,這里可以在RAM開辟一個寄存器來用,那就沒事了。喜
歡的自己改)

2 第二部就是定義一些宏的具體數(shù)值了(跟C類似)
TCCA_ENABLE == 0X04
TCCA_DISABLE == 0X00
TCCA_SRC_INT == 0X00
TCCA_SRC_EXT == 0X02
TCCA_EDGE_RISE == 0X00
TCCA_EDGE_FALL == 0X01

3 第三步就是華麗的開始用了,在主程序里面,
/*
TCCA_SETUP setup MACRO
argument : TCCA_ENABLE / TCCA_DISABLE 是否允許
TCCA_SRC_INT / TCCA_SRC_EXT 計數(shù)源選擇
TCCA_EDGE_RISE / TCCA_EDGE_FALL 出發(fā)弦選擇
*/
TCCA_SETUP TCCA_DISABLE|TCCA_SRC_INT|TCCA_EDGE_RISE
看到了吧?
(TCCA_DISABLE|TCCA_SRC_INT|TCCA_EDGE_RISE)一堆有意義的參數(shù),異或之后作為一個參數(shù)傳遞給宏
TCCA_SETUP ,修改的時候我們很簡單就能搞定,甚至絕對不需要查資料,例如,我們想改成外部TCCA
脈沖計數(shù),只需要簡單的修改

TCCA_SETUP TCCA_DISABLE|TCCA_SRC_EXT|TCCA_EDGE_RISE

完工了,想禁止TCCA的話,改成 TCCA_DISABLE 就OK了


(5)寄存器自動分配
終于到了尾聲,到了最BT的地方了,也是最有成就感的東西,怎么讓寄存器自動分配空間,匯編跟C一個
很大的區(qū)別就是,C的變量是自動分配,看著都眼紅,那是多少好的東西啊,被匯編虐待了好些日子,突
然發(fā)現(xiàn),原來咱們EMC的匯編編譯器也有這個功能,大喜!可能已經(jīng)有前輩懂得怎么用了,那就算在下班
門弄斧好,拍拍磚~~~
平時寫程序的習慣就是,定義一個有意義,容易記的名字去代替抽象的寄存器名,例如定義一個臨時變
量用的寄存器

TEMP EQU 0X10

這樣,我們定義了TEMP,以后都用 TEMP 來代替 0X10 寄存器,這是最最常規(guī)的辦法。但是,問題是,
我們必須每次寫程序之前都重新定義一次TEMP EQU 0X10 ,當然,也不是說很煩,但是我們都有一些
常用功能的子程序,子程序里面用到寄存器的話,也需要定義,然后做項目的時候,這里copy一個子程
序,那里copy一個子程序,好了,一大堆沖突的寄存器定義,必須慢慢仔細的檢查,如果不走運,有兩
個名字定義到同一個寄存器上面,好,慘了,很隱蔽的邏輯錯誤就來了,那是惡夢。

但是用宏可以做到自動分配
用到的是變量宏,WICE手冊里面也有說,用法是
TEST VAR 1
MOV A,@TEST
TEST VAR TEST+1
MOV A,@TEST

對比兩次的A值,我們發(fā)現(xiàn),第一個A值為1,第二個A值為2 ??!這個就是變量宏的基本原理,編譯器當
它是一個變量,可以改變的,不過這個改變,只發(fā)生在編譯的時候,生成代碼之后就沒有用的了。
好了,下面說說我們的核心,具體怎么分配。
首先定義個分配變量的宏,代碼如下

ADDR_ASSIGN MACRO REGISTER
REGISTER EQU ADDRESS
ADDRESS VAR ADDRESS+1
ENDM

用了一個參數(shù),傳遞進來的變量的名字。例如我們在主程序里面寫了
ADDRESS VAR 0X10 (首先定義開始分配的地址,我們是由 0X10 開始)
ADDR_ASSIGN Temp0
Temp0 作為參數(shù)傳遞進來,實際上就是執(zhí)行了
Temp EQU 0X10
ADDRESS = ADDRESS+1 (現(xiàn)在的ADDRESS已經(jīng)是 0X11了!因為它是一個變量宏!)
下次如果我們繼續(xù)定義
ADDR_ASSIGN Temp1
現(xiàn)在 Temp1 已經(jīng)自動被定義為 0X11 了,然后ADDRESS滾到0X12為下個寄存器定義用。
這樣就方便了,例如我們定義一堆寄存器
ADDR_ASSIGN Temp0
ADDR_ASSIGN Temp1
ADDR_ASSIGN Temp2
ADDR_ASSIGN TeMP3

天啊,這實在是太好用了?。?!我們完全不用關心具體分配到哪個寄存器上面,反正就是分配了,反正
就是可以用了,哈~~TEST一下就知道。
牽涉的問題1
越界問題,當分配到 0X3F 的時候一個頁面結束了,但是ADDRESS還是繼續(xù)加上去,怕不怕?不怕,編譯
器已經(jīng)報錯了,不能編譯,這樣就不怕越界,可以放心的定義了
牽涉的問題2
多也bank的怎么分配?其實可以在定義宏的時候加多一個參數(shù),通過條件宏來跳轉定義就OK了,不過我
怕麻煩,用了一下的辦法:
/*---------------------------BANK 0 入口地址-------------------------------------*/
ADDRESS VAR 0X10 ; 可分配 0x10 ~ 0x3f
/*--------------------------- BANK 0 ----------------------------------------*/
這里就是我們需要定義的寄存器的
/*---------------------------BANK0 調試信息輸出----------------------------------*/
MESSAGE "Bank0最大分配RAM:"
ADDR_DISP ADDRESS-1
/*-------------------------------------------------------------------------------*/

/*---------------------------BANK 1 入口地址-------------------------------------*/
ADDRESS VAR 0X20 ; 可分配 0x20 ~ 0x3f
/*--------------------------- BANK 1 ----------------------------------------*/
這里我門需要定義的bank 1 的寄存器
/*---------------------------BANK1 調試信息輸出----------------------------------*/
MESSAGE "Bank 1 最大分配RAM:"
ADDR_DISP ADDRESS-1
/*-------------------------------------------------------------------------------*/

怎么樣?和諧了吧? 將變量嚴格分開,你需要放在 bank0 的就填到 bank0 的區(qū)域,需要分到bank1 的
就填到bank1那里,因為在bank1開頭,重新定義了 ADDRESS 為 0X20 ,那樣就可以繼續(xù)從 0X20開始分
配,如果有多個page的,按照同樣的辦法。
在每個bank結束的時候,我還放了兩個宏,他們是
MESSAGE "Bank0最大分配RAM:"
ADDR_DISP ADDRESS-1
第一個,簡單的顯示文字而已,第二個 ADDR_DISP 是用來顯示一共最大分配到哪個寄存器,這個宏的原
型是:
ADDR_DISP macro reg
IF reg==0x10
MESSAGE "0x10"
ELSEIF reg==0x11
MESSAGE "0x11"
ELSEIF reg==0x12
MESSAGE "0x12"
ELSEIF reg==0x13
……
……
(下面的自己寫了….)
ENDM

很簡單,將ADDRESS最后的地址傳進去,現(xiàn)實一下而已,因為ADDRESS執(zhí)行多了一條自加指令的,所以我
們減回,那就OK了。

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

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉