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

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

(1)最常用的PAGE和BANK
EMC的IC是分幾個(gè)page和幾個(gè)bank的,低端的EM78P156等只有一個(gè)bank和一個(gè)page,所以不用切換,新
一點(diǎn)的IC基本都要切換的了,這個(gè)經(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

調(diào)用格式是
BANKnum(num是0~3代表4個(gè)BANK)
PAGEnum(num是0~3代表4個(gè)PAGE)
這樣方便多了,而且不會(huì)出錯(cuò)

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

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

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

FUNC0X10,0X20

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

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 ;
這個(gè)應(yīng)該很容易看的懂吧?中間的 “|”是或運(yùn)算,這個(gè)就是編譯器在編譯之前先做的運(yùn)算了,具體CT
0_MODE1 代表 0X01 CT1_MODE2 代表0x20,然后“與運(yùn)算”之后結(jié)果就是0X21 了,跟上面一樣。但是老
實(shí)說,大家愿意用哪個(gè)辦法去做呢?我會(huì)毫不猶豫的選擇第二種。

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

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

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

1 首先定義一個(gè)宏,以后可以用這個(gè)宏來初始化了
TCCA_SETUP MACRO TCCACNT
clr 0x04 ; 0x04 是用來做臨時(shí)寄存器用的
ior 0x08 ; 0x08是控制TCCA的寄存器
and a,@0xf8 ; 屏蔽掉TCCA相關(guān)的
MOV 0x04,a
MOV a,@TCCACNT ; 讀取傳遞進(jìn)來的參數(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
(因?yàn)檫@個(gè)程序在初始化階段,所以改變0x04寄存器沒有所謂,不過在正常跑的時(shí)候千萬不要亂來,那
個(gè)是會(huì)切換BANK的,跑飛了可不是說著玩,當(dāng)然,這里可以在RAM開辟一個(gè)寄存器來用,那就沒事了。喜
歡的自己改)

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 計(jì)數(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ù),異或之后作為一個(gè)參數(shù)傳遞給宏
TCCA_SETUP ,修改的時(shí)候我們很簡單就能搞定,甚至絕對(duì)不需要查資料,例如,我們想改成外部TCCA
脈沖計(jì)數(shù),只需要簡單的修改

TCCA_SETUP TCCA_DISABLE|TCCA_SRC_EXT|TCCA_EDGE_RISE

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


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

TEMP EQU 0X10

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

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

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

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

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

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

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

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

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

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

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉