• <rp id="wfxtb"><acronym id="wfxtb"></acronym></rp><em id="wfxtb"></em><dd id="wfxtb"><big id="wfxtb"><video id="wfxtb"></video></big></dd>
  • <rp id="wfxtb"></rp>

    <mark id="wfxtb"><center id="wfxtb"></center></mark>

      <rp id="wfxtb"><span id="wfxtb"><u id="wfxtb"></u></span></rp>

      <rp id="wfxtb"><object id="wfxtb"></object></rp>

      注意:訪問本站需要Cookie和JavaScript支持!請設置您的瀏覽器! 打開購物車 查看留言付款方式聯系我們
      初中電子 單片機教材一 單片機教材二
      搜索上次看見的商品或文章:
      商品名、介紹 文章名、內容
      首頁 電子入門 學單片機 免費資源 下載中心 商品列表 象棋在線 在線繪圖 加盟五一 加入收藏 設為首頁
      本站推薦:
      EMC資料轉貼大全
      文章長度[48949] 加入時間[2008/3/19] 更新時間[2025/5/3 19:11:28] 級別[0] [評論] [收藏]

      EMC資料轉貼大全

      來源:21ic 作者:McuPlayer 欄目:單片機 EMC資料轉貼大全
      本帖的所有跟貼資料完全來自轉貼(本論壇或其它壇子)
      有版權爭議的內容,請跟貼說明,我會妥善處理的。

      * - 本貼最后修改時間:2006-6-28 9:01:45 修改者:McuPlayer

      1樓: >>參與討論 作者: McuPlayer 于 2006-6-28 9:00:00 發布:
      【轉貼】編程寶典:ADD A,@0xFF的妙用
      EMC的單片機全部是OTP的,開發時只能使用仿真器,但很多情況下,仿真器并不能仿真實際的運行環境,如工作電壓為3.3V左右、測試系統的功耗、測試系統的穩定性、測試ADC、DAC、看門狗使用等,如果使用仿真器會根實際情況有很大差別,只有燒片子才能測試到實際結果,這樣一次試驗下來,如果運氣不好,可能需要浪費10~20個芯片,造成很大的浪費。
        要有效使用ADD A,@0xFF這條指令,需要對單片機系統編程進行一些分析,從仿真結果(包含硬件仿真器)根實際芯片運行的差異方面分析程序,可以把程序分為兩個相對獨立的系統:算法級程序和硬件級程序。
        算法級程序:指與硬件無關的程序,如加減乘除算法,控制算法等,總之不涉及硬件單元的操作,這些程序由于其硬件無關性,使用仿真器和芯片結果肯定相同。
        硬件級程序:與硬件相關的程序,如WDT、計數器、端口、中斷、休眠、喚醒等等,特別是WDT、中斷、休眠、喚醒等需要在芯片上才能測試出實際的結果,比如測試休眠狀態的功耗,用仿真器無論如何是試驗不出來的。
        閑話少說,書歸正傳。
        有效使用ADD A,@0xFF可以將一個芯片當作數片使用,甚至可以到數十片,原理如下:
        EMC單片機寫燒寫的過程實際就是將為1的熔絲位熔斷成為0,即可以從1寫為0,但不能從0到1,ADD A,@0xFF的機器碼剛好是0x1FFF,全為1。例程如下:
        第一次編程代碼如下:
          ORG    0X000
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
      MAIN1:
          ...
          ...
          JMP    MAIN1
        如果MAIN1程序運行結果不能達到預期目標,需要修改程序,假定為MAIN2。修改后代碼如下:

          ORG    0X000
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          JMP    MAIN2
      MAIN1:
          ...
          ...
          JMP    MAIN1    
          
      MAIN2:
          ...
          ...
          JMP    MAIN2


      * - 本貼最后修改時間:2006-6-28 9:02:00 修改者:McuPlayer

      2樓: >>參與討論 作者: McuPlayer 于 2006-6-28 9:03:00 發布:
      【轉貼】EMC單片機的IIC程序包
        本程序已經穩定使用很長一段時間了,如果非要追根求源,應該追溹到1998年,由于本系統是基于IIC EEPROM的,故對2401的讀寫采用了阻塞的方式,讀不到數據或寫不入數據就不退出。
        本程序是基于447的,也在163上運行過,不過IO的初始化操作需要作些修改,其他可以完全不用修改。
        程序開頭的幾行ADD A,@0xFF是非常有用的,在以后的文章中會有描述。
        程序如下:

      ;SYSTEM CLOCK 4MHz
      ;IO port define
          SDA    == 4
          SCL    == 3

          MSDA    == 0
          MSCL    == 1
          MCS    == 2
          MRST    == 5
          
      ;Register define
          TREG    == 0X10
          TCNT    == 0X11
          GCNT    == 0X12

          IICADDR    == 0X1E
          IICBUF    == 0X28
          IICDAT0    == 0X28
          IICDAT1    == 0X29
          IICDAT2    == 0X2A
          IICDAT3    == 0X2B
          IICDAT4    == 0X2C
          IICDAT5    == 0X2D
          IICDAT6    == 0X2E
          IICDAT7    == 0X2F
          
          INCLUDE "EM78P447S.H"
          
          ORG    0X000
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF
          ADD    A,@0XFF

      START:
          DISI
          ;SET P6 P7 PULL UP EN
          CONTR
          MOV    TREG,A
          BC    TREG,7
          MOV    A,TREG
          CONTW
          ;SET SCL SDA OUTPUT HIGH
          MOV    A,@0XFF
          MOV    TREG,A
          BC    TREG,SCL    ;SCL OUTPUT
          BC    TREG,SDA    ;SDA OUTPUT
          MOV    A,TREG
          IOW    IOC6
          BS    R6,SCL        ;SCL HIGH
          BS    R6,SDA        ;SDA HIGH

      ;********************************************************************
      ;讀入的測試程序,讀取2401的0x00~0x07地址內容
      READ_2401:
          MOV    A,@0X00
          MOV    IICADDR,A
          CALL    IIC_R8BYT
          RET

      ;********************************************************************
      ;寫入的測試程序,向2401的0x00~0x07地址寫入0x00
      WRITE_2401:
          MOV    A,@0X00
          MOV    IICADDR,A
          CLR    IICDAT
          CLR    IICDAT
          CLR    IICDAT
          CLR    IICDAT
          CLR    IICDAT
          CLR    IICDAT
          CLR    IICDAT
          CLR    IICDAT
          CALL    IIC_W8BYT
          RET

      ;********************************************************************
      ;與Microchip的2401接口程序
      ;********************************************************************
      ;IIC_W8BYT,向2401的指定地址寫入8個字節數據
      ;地址由IICADDR指定,數據存在IICDAT0~IICDAT7
      IIC_W8BYT:
          CALL    IIC_START
          MOV    A,@0XA0
          CALL    IIC_WBYT
          CALL    IIC_CACK
          JBC    R3,GP        ;IF GP=1 OPTION AGAIN
          JMP    IIC_W8BYT
          MOV    A,IICADDR
          CALL    IIC_WBYT
          CALL    IIC_CACK
          JBC    R3,GP        ;IF GP=1 OPTION AGAIN
          JMP    IIC_W8BYT
          ;WRITE 8 BYTES TO 24C01
          MOV    A,@IICBUF
          MOV    R4,A
          MOV    A,@8
          MOV    GCNT,A
      IIC_W8BYT1:
          MOV    A,R0
          INC    R4
          CALL    IIC_WBYT
          CALL    IIC_CACK
          JBC    R3,GP        ;IF GP=1 OPTION AGAIN
          JMP    IIC_W8BYT
          DJZ    GCNT
          JMP    IIC_W8BYT1
          CALL    IIC_STOP
          RET

      ;********************************************************************
      ;IIC_W1BYT,向2401的指定地址寫入1個字節數據
      ;地址由IICADDR指定,數據存在IICDAT0
      IIC_W1BYT:
          CALL    IIC_START
          MOV    A,@0XA0
          CALL    IIC_WBYT
          CALL    IIC_CACK
          JBC    R3,GP        ;IF GP=1 OPTION AGAIN
          JMP    IIC_W1BYT
          MOV    A,IICADDR
          CALL    IIC_WBYT
          CALL    IIC_CACK
          JBC    R3,GP        ;IF GP=1 OPTION AGAIN
          JMP    IIC_W1BYT
          ;WRITE 1 BYTES TO 24C01
          MOV    A,@IICBUF
          MOV    A,IICDAT0
          CALL    IIC_WBYT
          CALL    IIC_CACK
          JBC    R3,GP         3樓: >>參與討論 作者: McuPlayer 于 2006-6-28 9:04:00 發布:
      【轉貼】bs,bc指令慢慢解

      各位大俠是否有碰到過這樣得情況:就是沒個IO口電位莫名其妙的變化,從而出現你不希望的結果?別急,這很有可能就是bs、bc指令在作怪,欲知為何,且聽俺慢慢解來。
      要回答這個問題,首先要對IO PORT的結構要有所了解。具體io 口電路結構圖請參照相關資料。在EMC單片機中,不能單獨更改一個位的數據。當試圖更改沒個IO 口(或RAM)中的一個位時,其8個位的數據都將被取入ALU中,然后執行AND/OR指令之后再寫回io port(RAM)。
      舉個例子,將PORT 6 bit 0 置1,指令為bs 0X06,0。指令的執行過程是這樣,首先將整個PORT 6的數據取到ALU,然后用二進制數據“00000001”跟取回的數據執行“或”操作,最后將結果寫入port 6;相反的,如果要將它清零,那么會用11111110與之相與再寫回去。
      那么為什么可能產生錯誤呢?有兩種情況,用port6 bit7舉例,一種情況是port6.7設置為input,另一種則為output,現用第一種情況分析一下錯誤是怎么產生的。bit 7設置為input,此時bit7鎖存器上的值為0或1;當在port6 bit0-6上執行bs或bc指令改變bit0-6上的值時,如上所述的,bit7io port(不是latch)上的值也會被讀入ALU,之后再寫入bit7之data latch,盡管你并沒有如此意圖。如此,bit7上之data latch上的值就有可能不經意的被改變了。當bit7由input轉變為output時,意想不到的錯誤就可能發生了。另一種情況就不羅嗦了。
      可以發現,這種影響只會影響io port的其他位,對本身不會影響;對于非io port的RAM,也不會有這種影響出現;除了bs,bc指令外,如下指令也可能出現上述情況:XOR/AND/OR R,A;DEC R;RRC R;RLC R;SWAP R;MOV R,R;COM R;DJZ R;SWAP R;JZ R;JBC R,B;JBS R,B;等等,這里如果R不是io port而是RAN,則錯誤不會發生。



      4樓: >>參與討論 作者: McuPlayer 于 2006-7-7 22:31:00 發布:
      EM78系列單晶片-提升軟體效率的小程式
      EM78系列單晶片-提升軟體效率的小程式  
      ■ 譚振文
      EM78系列單晶片-提昇軟體效率的小程式譚振文分享
      筆者閒暇時總喜歡一個人窩在房裡拿烙鐵 ,焊電路板,在網路上游走,看到喜歡的DIY也一定仔細端詳,即使按圖施工也可以得到不少的樂趣,相信酷愛此道的人應該也不少 ,除了喜歡看看別人的作品,也可以互相比較一下看誰用的零件少,誰提供的功能強,誰的速度最快,所以經常很容易就蒐集到一些不錯的電路,日子久了就像堆積木一樣,可以一個方塊一個方塊的拿來用,吾人戲稱為積木設計法。將許多有用的電路組合在一起,又是一個新的東西。這種方式的確又快又經濟,符合現代人速食的觀念。不僅是硬體可以像堆積木一樣的收集起來,軟體當然也可以適用於積木法則,於是在不少有心人的努力之下,筆者也收集了EM78系列單晶片一些很好的程式庫,所以說麻雀雖小,五臟俱全。也因為這些程式庫極具參考價值,筆者不忍獨享,故決定將紊亂的筆記重新整理後
      公開出來,與熱愛此系列單晶片的朋友們一同分享。
      EM78XXX單晶片自從問世以來已經陸續推出十餘種不同等級的單晶片,小到8Pin的78P152,大到100Pin OTP的78P860,其組合語言指令都是一樣的,僅有57個,所以反覆練習幾次就能熟悉指令的用法。組合語言用在I/O控制非常容易,也有很高的效率,所以坊間的書籍大部份以討論控制為主顯,顯少專門探討軟體技巧的篇幅,其實老手都知道,關於晶片之控制往往用到時再去翻一翻DATA BOOK,注意一下TIMING,然後準備一部示波器,三兩下就可以搞定。反倒是演算法用的好不好會大大影響產品的穩定度,所以有經驗的程式設計師通常都有自己的一套葵花祕笈,所以要提昇自己的功力最好的方式除了多練習之外,看看別人的程式也會使你進步很快。
      BCD轉換成Binary
      由於EM78XXX是8位元的微控器,因此為了節省記憶體,我們的範例僅以一個BYTE存放兩位BCD數為例,數字的範圍在0~99之間,轉換後的結果放在ACC,如果您需要更多的位數,相信您在看完之後應該不難自行修改才是。
      程式一
      這個範例程式共花費13個指令CYCLE,需要兩個變數空間,執行後會影響到原BCD的內容。
      MOV A,BCD
      MOV TMP,A
      MOV A,@0x0F
      AND TMP,A
      SWAP BCD
      AND BCD,A
      BC PSW,0
      RLC BCD ; *2
      MOV A,BCD
      ADD TMP,A
      RLC BCD
      RLCA BCD ; *8
      ADD A,TMP
      說明
      在程式一中所採用的方式應該算是最多人知道的方式,也是一種最直覺的方法,先將BCD個位數保存起來,因為十位數必須要乘以10,所以利用移位的技巧乘以10再加上個位數,所得的答案放入ACC。
      程式二
      在程式一的缺點,就是在執行程式以後,原本BCD的內容已經在移位的過程中被破壞掉了,為了改善這項缺失,我們換一種方式看看。下面這個程式,我們企圖改善前面的缺失,共花費11個指令CYCLE,仍需要兩個變數空間,但是執行後不會破壞原來BCD的內容。
      SWAPA BCD
      MOV TMP,A
      MOV A,@0x0F
      AND BCD,A
      AND TMP,A
      BC PSW,0
      RLCA TMP
      SWAP TMP
      RRC TMP
      ADD A,TMP
      ADD A,BCD
      程式三
      對於程式二的結果我們仍然不滿意,似乎稍嫌複雜,雖然速度有所改善,但在記憶體的分配上仍有餘地,所以我們再改善成程式三的型態。轉換過程只花費10個指令CYCLE,而且只需要一個變數空間,執行之後也不會改變原來BCD的內容。
      MOV A,@0x0f
      AND A,BCD
      JBC BCD,4
      ADD A,@10
      JBC BCD,5
      ADD A,@20
      JBC BCD,6
      ADD A,@40
      JBC BCD,7
      ADD A,@80
      說明
      看過以上三個範例,您是否覺得程式三最簡潔而且容易瞭解?寫程式的確是一項極具挑戰性的工作,而且還可以找到很多靈感及樂趣,想不到吧!
      Binary轉換成BCD碼
      下面的範例程式會將存放在ACC內的二進位數轉換成兩位BCD碼(Compacted BCD Code),可轉換最大的BCD碼是99。
      CLR BCD
      DIGIT_HI:
      ADD A,@256-10
      JBS PSW,FC
      JMP DIGIT_LO
      INC BCD
      JMP DIGIT_HI
      DIGIT_LO:
      ADD A,@10
      SWAP BCD
      OR BCD,A
      減法的陷阱
      EM78系列組合語言的減法指令是SUB,使用這個指令時您得特別注意,因為ACC永遠都是減數,不可為被減數。SUB指令的語法有以下三種:
      SUB A,R (R-A→A)
      SUB R,A (R-A→R)
      SUB A,K (K-A→A)
      也就是說如果我們想計算A-2的值,如果寫成:
      SUB A,@2
      其實是執行2-A,解決方法如下:
      ADD A,@256-2 或
      ADD A,@254
      交換兩組暫存器的內容
      如果你覺得要交換兩組記憶體的內容一定要借用第三組變數,那麼您可以參考以下的方式,只是用了一些數學技巧就變得又快又簡單。
      MOV A,REG1
      SUB A,REG2
      ADD REG1,A
      SUB REG2,A
      原理說明
      A=REG1
      A=REG2-REG1
      REG1=REG1+A
      =REG1+(REG2-REG1)
      =REG2
      REG2=REG2-(REG2-REG1)
      =REG1
      若X>Y就交換...
      延續上一個例子,此法用應用在Bubble Sort特別管用。
      MOV A,X
      SUB A,Y
      JBC PSW,FC
      JMP NO_CHANGE
      ADD X,A
      SUB Y,A
      2補數
      2補數加法經常代替減法,傳統上的做法是先取1補數,然後加1。
      COM REG
      INC REG
      或是可以利用另一種方式求得,所不同的是第二種方式會影響PSW暫存器。
      ADD A,REG
      SUB A,REG
      如果您所要求的數已經放在ACC裡面,那只要一行就能解決了。
      SUB A,@0
      旋轉位元組運算
      在8051指令中位元左旋有RLC與RL兩種指令區分,RLC在ACC左旋時會連帶將CY一併旋轉,而RL只會將ACC的MSB旋入LSB。EM78XXX指令只有RLC,那麼要如何才能做到不帶CY旋轉呢?答案是旋轉兩次:
      RLCA REG1
      RLC REG1
      如圖1所示,第一次位元旋轉並沒有真正改變REG1的內容,目的是將REG1的MSB先放入FC,第二次位元旋轉才將剛剛放在FC內的MSB旋入LSB。同理,兩個BYTES不經FC的位元旋轉也是相同的原理。
      RLCA HI_BYTE
      RLC LO_BYTE
      RLC HI_BYTE
      範圍判斷
      寫程式免不了會碰到IF..THEN..的場合,有些人覺得EM78XXX的條件判斷式太過繁瑣,所以筆者也將它們整理歸納一下。條件判斷式可分為開放區間條件式與封閉區間條件式來討論,以圖2來表示。
      開放條件式是以N點為出發點,當待測值大於N或是小於等於N時的條件判斷,以C的語法描述如下:
      if(number>n)
      ... /* number大於N */
      else
      ... /* number小於等於N */
      EM78XXX組合語言寫法如下:
      MOV A,@N+1
      SUB A,Number
      JBC PSW,FC
      JMP LABEL_1 ; 大於N
      JMP LABEL_2 ; 小於等於N
      封閉式條件判斷是指待測值N是否在X與Y的範圍之內,若以C的語法描述:
      if((number>=x) && (number<=y))
      .... /* in range */
      else
      .... /* False */
      如何以EM78組合語言做到呢?一般做法是以減法後的PSW做條件判斷,程式如下:
      MOV A,@2
      SUB A,number
      JBS PSW,FC
      JMP FALSE
      MOV A,@y+1
      SUB A,SI
      JBC PSW,FC
      JMP FALSE
      IN_RANGE:
      ; ....
      FALSE:
      ; ....
      這個IF條件式要花費8個指令Cycle,還不算太複雜。但是還有個更簡潔的方法,以下用加法後的PSW(R3)做條件判斷,一共只要5行就清潔溜溜了。
      MOV A,Number
      ADD A,@255-y
      ADD A,@y-x+1
      JBC PSW,FC
      JMP IN_RANGE
      FALSE:
      ; ....
      IN_RANGE:
      ; ....
      說明
      關鍵就在前三行,x表示條件式的下限值,y表示條件式的上限值,可以看得出仍是利用CY旗標製造的特效,不但精簡而且有點小聰明,許多老手都愛用,這也是他們口袋裡的秘密武器之一。如果您覺得不錯,不妨也收入錦囊中,爾後就可以依樣畫葫蘆了。
      ACC與暫存器內容交換
      這理我們要介紹一種快速的邏輯演算法,只需要3個指令CYCLE,就可以將ACC的內容與暫存器的內容交換,不拖泥帶水,Very cute!
      XOR Number,A
      XOR A,Number
      XOR Number,A
      請讀者自行在紙上推算一次,就知道答案了。
      交換多組暫存器內容
      利用上面介紹的方法,可以推廣到多組暫存器交換的例子上,下面的程式將5組DATA內容移位,第一筆暫存器的資料傳到第二筆暫存器內,第二暫存器的資料再傳送到第三筆暫存器內,依此類推,最後一筆資料則傳給第一個暫存器,形成一種位元組資料旋轉。
      MOV A,@5
      MOV COUNT,A
      MOV A,@DATA1
      MOV RSR,A
      MOV A,DATA5
      NEXT:
      XOR INDIR,A
      XOR A,INDIR
      XOR INDIR,A
      INC RSR
      DJZ COUNT
      JMP NEXT
      計算MOD 2N
      假如你剛好需要計算ACC MOD X,且X剛好是2的N次方,使用ACC AND (X-1)是最快的方法了。例如要判斷YEAR是否為閏年,有個簡單的方法,可以排除一些非閏年的條件,只要不能被4整除者就不是閏年。所以可以用YEAR AND 3解決。
      MOV A,@4-1
      AND A,YEAR
      JBS PSW,FZ
      JMP NOLEAP
      清除一段連續的記憶體
      對於連續一段記憶體做讀寫最好的方式就是使用間接定址法,但是要注意在一些如M78447/811/860等高階MCU,記憶體20H~ 3FH又可以分成4組BANK,如果之前沒有切換到正確的BANK會造成讀寫錯誤。下面的範例程式會將BANK1內的32個BYTES全部清為0。
      INDIR == 0x00
      RSR == 0x04
      COUNT == 0x10
      REG == 0x20
      BANK1 == 0x40
      BANK2 == 0x80
      BANK3 == 0xC0
      MOV A,@32
      MOV COUNT,A
      MOV A,@REG|BANK1
      MOV RSR,A
      NEXT:
      CLR INDIR
      INC RSR
      DJZ COUNT
      JMP NEXT
      計算一個BYTE中有多少個"1"
      這個小程式可以檢查出在某個BYTE中共有幾個1,在某些演算法的過程可能會用得到,計算的結果放在ACC。
      RRCA DATA
      AND A,@0x55
      SUB DATA,A
      MOV A,DATA
      AND A,@0x33
      ADD DATA,A
      RRC DATA
      ADD DATA,A
      RRC DATA
      SWAPA DATA
      ADD A,DATA
      AND A,@0x0F
      節省NOP指令的方法
      您還在為程式擠不下傷腦筋嗎?NOP指令有時候在延遲指令時間很有用,假如你有連續兩個NOP指令可以用JMP到下一個指令的方式代替, 5樓: >>參與討論 作者: sonic530 于 2006-7-10 17:01:00 發布:
      非常感謝
      非常感謝樓主的分享!

      6樓: >>參與討論 作者: weizhiwei 于 2006-8-8 23:39:00 發布:
      感謝
      樓主辛苦了!

      7樓: >>參與討論 作者: McuPlayer 于 2006-8-12 16:01:00 發布:
      EM78P447 I/O喚醒程序示例
        由于EM78P447在I/O喚醒方式上特殊性(SLEEP2,低電平喚醒),大家覺得不是很好用,其實只要在喚醒之前注意以下幾點,用起來某些地方比EM78P156更方便(可以單獨開/關某一個腳喚醒功能)∶
      1.    IOCB清零或置p6口喚醒腳相對應的IOCB位清零.
      2.    喚醒腳p60~p6.7、p7.4、p7.5內部電阻上拉、輸入口.
      3.    p6àp6.
      4.    10HàIOCE(SPLC位置1、關看門狗、喚酲功能允許).
             ORG   0x0
             JMP   MAIN
             ORG   0x8
             JMP   P6INT
      MAIN:  and   a,@0x3F       ; **** port 6 pull high
             contw
             mov   a,@0x00       ; enable port6 wake up
             iow   0x0B          ;
             MOV   A,@0x0       ; **** Disable WDT ****
             IOW   0xE           
             MOV   A,@0Xff       ;
      IOW   0x6      
             MOV   0x6,0x6   ;
      SLEEP: MOV   A,@0x10
             IOW   0xE          
      JMP   $            ;WAITING THE WAKE SIGN-“0” LEVEL
      MOV   A,@0x0      ; **** Disable WDT ****
      IOW   0xE     
      JMP   SLEEP
      ;
             org 0xfff
      jmp main


      8樓: >>參與討論 作者: McuPlayer 于 2006-8-19 1:06:00 發布:
      EMC實用子程序
      一 二進制數轉換為ASCⅡ碼
      將一個字節的二進制數轉換為兩位16進制數的ASCⅡ碼
      main: mov a,@0x9f ;二進制數為0x9f
      mov 0x30,a ;二進制數存入0x30
      mov a,@0x02
      mov 0x10,a ;0x10中存放轉換次數
      mov a,@0x31
      mov 0x04,a ;0x04中為轉換后數據存放地址
      mov a,0x30
      B1: and a,@0x0f ;取a低4位
      mov 0x00,a
      sub a,@0x09 ;低4位大于9跳往B2
      jbs 0x03,0
      jmp B2
      mov a,0x00 ;低4位不大于9則加0x30
      add a,@0x30
      mov 0x00,a ;將ASCⅡ碼存入0X04所指單元
      jmp B3
      B2: mov a,0x00 ;大于9則加0X37
      add a,@0x37
      mov 0x00,a
      B3: swapa 0x30 ;將0X30高4位換入A低4位
      inc 0x04 ;存儲地址加1
      djz 0x10 ;循環次數減1,為0則返回
      jmp B1 ;不為0繼續轉換

      self: jmp self
      eop


      二 多字節二進制加法
      0X20,0X21中的二進制無符號數與0X22,0X23中的二進制無符號數相加,結果放在0X24,0X25,0X26中,低地址中放低字節數據。
      Main: mov a,@0x78 ;賦值
      mov 0x20,a
      mov a,@0xc6
      mov 0x21,a
      mov a,@0x86
      mov 0x22,a
      mov a,@0x9e
      mov 0x23,a
      mov a,@0x0 ;0x26單元清0
      mov 0x26,a
      mov a,0x21
      add a,0x23
      mov 0x25,a ;高字節相加,結果送0x25
      jbc 0x03,0
      inc 0x26 ; 有進位則0x26加1
      mov a,0x20
      add a,0x22
      mov 0x24,a ;低字節相加,結果送0x24
      jbs 0x03,0
      jmp self ;無進位跳self
      inc 0x25 ;有進位0x25加1
      jbc 0x03,0
      inc 0x26 ; 有進位0x26加1
      self: jmp self
      eop

      三 多字節二進制減法
      0x20,0x21中的二進制無符號數減0x22,0x23中的二進制無符號數, 低地址中放低字節數據。假設被減數大于減數。
      注意:(1)sub指令減出結果為正時,c標志置1。
      (2)sub指令減出結果為0時,c標志也置1。
      即,sub指令執行后,c標志清0表示結果為負。
      main: mov a,@0x67 ;賦值
      mov 0x20,a
      mov a,@0xff
      mov 0x21,a
      mov a,@0xe8
      mov 0x22,a
      mov a,@0x44
      mov 0x23,a ; 高字節相減
      sub a,0x21
      mov 0x25,a ;結果存0x25
      mov a,0x22 ;低字節相減
      sub a,0x20
      mov 0x24,a
      jbs 0x03,0
      dec 0x25 ;有借位則0x25減1
      self: jmp self
      eop

      四 二進制乘法運算
      EM78單片機沒有乘法指令,所以乘法運算需要轉化為加法運算。0X20單元數據乘以0X21單元數據,結果放在0X22,0X23中。
      main: mov a,@0x0 ;0x22,0x23單元清0
      mov 0x22,a
      mov 0x23,a
      mov a,@0x3f ;賦值
      mov 0x20,a
      mov a,@0x22
      mov 0x21,a
      mul1: mov a,0x20 ;0x20與0x22內容相加
      add 0x22,a
      jbc 0x03,0
      inc 0x23 ;有進位0x23加1
      djz 0x21 ;0x21中次數減到0則結束
      jmp mul1 ;沒減到0則繼續
      self: jmp self
      eop

      五 二進制除法運算
      多字節二進制除法
      被除數為3個字節,在0x20、0x21、0x22單元中,0x22.7為最高位,0x20.0為最低位。
      除數為2個字節,在0x30、0x31中。
      算法:EM78單片機沒有除法指令,而且本例中除法為多字節除法,可采用如下算法。
      將被除數擴充一個字節0X23,0X23清0。被除數左移1位,0X23、0X22中數據減去0X31、0X30中數據,夠減則減且0X20.0置1,減出結果存入0X23、0X22;不夠減則0X23、0X22保持不變,0X20.0清0。然后被除數再左移1位,重復上述過程。共循環16次,最后0X23、0X22中得相減余數,0X21、0X20中得商。注意,若被除數左移后C標志為1,則不比較0X23、0X22與0X31、0X30數據大小關系而直接相減。
      main: mov a,@0x55 ;被除數賦值
      mov 0x20,a
      mov 0x21,a
      mov 0x22,a
      mov a,@0x0 ;被除數擴充1字節并清0
      mov 0x23,a
      mov a,@0x12 ;除數賦值
      mov 0x30,a
      mov 0x31,a

      mov a,@0x10 ;循環次數為16
      mov 0x32,a
      again: call rt_sub ;調移位除法子程
      djz 0x32 ;16次循環完成則結束
      jmp again ;未完成則繼續

      self: jmp self

      rt_sub:
      bc 0x03,0 ;c標志清0
      rlc 0x20 ;被除數左移1位
      rlc 0x21
      rlc 0x22
      rlc 0x23
      jbc 0x03,0
      jmp rt3 ;c標志為1則直接相減
      mov a,0x23 ;c標志為0則先比較大小
      mov 0x25,a
      mov a,0x22
      mov 0x24,a
      mov a,0x31 ;先比較高位
      sub 0x25,a
      jbc 0x03,2
      jmp rt1 ;高位相等跳rt1比較低位
      jmp rt2 ;高位不等跳rt2
      rt1: mov a,0x30 ;比較低位
      sub 0x24,a
      jbc 0x03,2
      jmp rt3 ;低位也相等則跳rt3,相減,上1
      rt2: jbs 0x03,0
      ret ;減數大則返回,減數小則相減,上1
      rt3: bs 0x20,0 ;上1
      call sub_2b ;調2字節減法子程
      ret

      sub_2b:
      mov a,0x31 ;高字節相減
      sub 0x23,a
      mov a,0x30 ;低字節相減
      sub 0x22,a
      jbc 0x03,2
      ret ;低字節相等,無借位,返回
      jbc 0x03,0
      ret ;無借位,返回
      dec 0x23 ;低字節相減有借位,高字節結果減1
      ret
      eop

      六 BCD數轉換為二進制數
      兩字節壓縮BCD碼轉換為兩字節二進制數。算法如下:
      BCD碼abcd=1000a+100b+10c+d=10{10[10a+b]+c}+d,將各位BCD碼分離出之后,即可根據此式轉換為二進制數。涉及到乘法運算和多字節加法運算。
      0X20,0X21中為BCD碼,0X21高4位為最高位。轉換結果放在0X30,0X31中。
      main: mov a,@0x79
      mov 0x20,a
      mov a,@0x54
      mov 0x21,a ;賦值
      mov a,0x20
      and a,@0x0f
      mov 0x22,a
      swapa 0x20
      and a,@0x0f
      mov 0x23,a
      mov a,0x21
      and a,@0x0f
      mov 0x24,a
      swapa 0x21
      and a,@0x0f
      mov 0x25,a ;BCD碼展開后存于0X22,0X23,0X24,0X25
      mov a,0x25, ;0X25為最高位
      mov 0x30,a
      mov a,@0x0 ;多字節加法高位為0
      mov 0x31,a
      mov a,0x24
      mov 0x32,a
      call a_b ;調子程
      mov a,0x23
      mov 0x32,a
      call a_b
      mov a,0x22
      mov 0x32,a
      call a_b
      self: jmp self

      a_b:
      mov a,@0x0 ;0X34,0X35存儲中間結果
      mov 0x34,a
      mov 0x35,a
      mov a,@0x0a ;實現乘10
      mov 0x33,a
      a1: mov a,0x35 ;兩字節二進制加法,在本例中高字節肯定無進位
      add a,0x31
      mov 0x35,a
      mov a,0x34
      add a,0x30
      mov 0x34,a
      jbc 0x03,0
      inc 0x35
      djz 0x33
      jmp a1
      mov a,0x32
      add 0x34,a
      jbc 0x03,0
      inc 0x35
      mov a,0x34
      mov 0x30,a
      mov a,0x35
      mov 0x31,a
      ret
      eop

      七 二進制數轉換為BCD碼
      本例為單字節二進制數(0X20)轉換為非壓縮BCD碼,存在0X25,0X24,0X23中,0X25為百位,0X23為個位。
      main: mov a,@0xa4 ;賦值
      mov 0x20,a
      mov 0x21,a
      mov 0x22,a
      mov a,@0x0 ;0x23,0x24,0x25單元清0
      mov 0x23,a
      mov 0x24,a
      mov 0x25,a
      mov a,@0x64 ;對100的個數計數
      mov 0x26,a
      mov a,@0x25 ;百位存在0x25中
      mov 0x04,a
      call a0 ;調計數子程
      mov a,@0x0a ;對10的個數計數
      mov 0x26,a
      dec 0x04 ;個位存在0x24中
      call a0
      mov a,0x22 ;除去百位,十位,余下的即個位,存入0x23
      mov 0x23,a
      self: jmp self

      a0: ;計數子程
      mov a,0x26
      sub 0x22,a
      jbs 0x03,2
      jmp a1
      inc 0x00 ;無余數則對應位加1
      mov a,@0x0 ;0x21與0x22在返回時應保持相同
      mov 0x21,a
      ret
      a1: jbs 0x03,0 ;小于則跳a2
      jmp a2
      inc 0x00 ;大于則計數值加1
      mov a,0x22
      mov 0x21,a ;將0x22保存到0x21中
      jmp a0 ;跳回a0繼續計數
      a2: mov a,0x21 ;0x21中保存的減之前的數據,此時恢復到0x22
      mov 0x22,a
      ret
      eop


      9樓: >>參與討論 作者: McuPlayer 于 2006-8-19 1:08:00 發布:
      EM78P156e+1621顯示匯編例子
      ;HT1621 ,3.58,OUT 20001  /6/22

      INDI    EQU     0X0
      RTCC    EQU     0X1
      PC      EQU     0X2
      STATUS  EQU     0X3
      FSR     EQU     0X4
      PORT5   EQU     0X5
      PORT6   EQU     0X6
      STACK_A EQU     0X10
      STACK_S EQU     0X11
      XS1     EQU     0X12
      XS2     EQU     0X13
      XS3     EQU     0X15
      XS4     EQU     0X16
      XS5     EQU     0X17
      XS6     EQU     0X18
      XS7     EQU     0X19
      XS8     EQU     0X1A
      JP1     EQU     0X1B
      JP2     EQU     0X1C
      JP3     EQU     0X1D
      JP4     EQU     0X1E
      XS9     EQU     0X20
      XS10    EQU     0X21
              ORG     0
              JMP     MAIN
              ORG     8
              MOV     STACK_A,A
              SWAP    STACK_A
              SWAPA   STATUS
              MOV     STACK_S,A
              CLR     0XF
              SWAPA   STACK_S
              MOV     STATUS,A
              SWAPA   STACK_A
              RETI
      BIAO:
              ADD     0X2,A
              RETL    @0B11101110     ;0
              RETL    @0B01001000     ;1
              RETL    @0B10111010     ;2
              RETL    @0B11011010     ;3
              RETL    @0B01011100     ;4
              RETL    @0B11010110     ;5
              RETL    @0B11110110     ;6
              RETL    @0B01001010     ;7
              RETL    @0B11111110     ;8
              RETL    @0B01011110     ;9
              RETL    @0B00000000     ;A
      XSZW:
              MOV     A,JP1
              CALL    BIAO
              MOV     XS3,A
              MOV     A,JP2
              CALL    BIAO
              MOV     XS4,A
              MOV     A,JP3
              CALL    BIAO
              MOV     XS5,A
              MOV     A,JP4
              CALL    BIAO
              MOV     XS6,A
              MOV     A,@7
              MOV     XS1,A
      AWS:
              RLC     XS10
              RLC     XS9
              RLC     XS8
              RLC     XS7
              JBS     XS6,1
              JMP     ASD1
              BS      XS10,4
              JMP     ASG1
      ASD1:
              BC      XS10,4
      ASG1:
              RRC     XS6
              RLC     XS10
              RLC     XS9
              RLC     XS8
              RLC     XS7
              JBS     XS5,1
              JMP     ASD2
              BS      XS10,4
              JMP     ASG2
      ASD2:
              BC      XS10,4
      ASG2:
              RRC     XS5
              RLC     XS10
              RLC     XS9
              RLC     XS8
              RLC     XS7
              JBS     XS4,1
              JMP     ASD3
              BS      XS10,4
              JMP     ASG3
      ASD3:
             10樓: >>參與討論 作者: McuPlayer 于 2006-8-19 1:11:00 發布:
      1621的匯編驅動程序
      1621的匯編驅動程序

          我用HT1621顯示時間、溫度、制冷/制熱,時間顯示用“:”閃爍,我是否需要在MCU中(臺灣義隆EM78P156)專門設對應的RAM區?能否提供參考程序。

          最好要設,LCD的反應時間是毫秒級的,開個RAM緩沖,由顯示子程序往HT1621送數據,主程序和其它程序改變要顯示的內容。
      最好在RAM區中設置一個顯緩區,定時刷新,然后調用一個通訊模塊將數據寫到HT1621中去.
      另:關于時間的秒閃,如果你用了TCC中斷的話,可用計數器中的某一位充當秒閃標志。


      ;****************************
      ;HT1621操作輯
      P_HT    EQU    0X05        ;LCD驅動口
          DATA    EQU    1
          WR    EQU    3
          CS    EQU    4
      ;****************************
      ;=======================
      ;寫字節
      ;入口:    LCD_D:    寫往DATA的數值
      ;    LCD_N:    位數(循環數)
      ;=======================
      WBLCD:
          MOV    A,@8
      WBLCD1:
          MOV    LCD_N,A
      ;=======
      WNLCD:
          RLC    LCD_D        ;LCD_D左循環,LCD_D(7)->C
          JBC    R3,C        ;C=0跳
          JMP    WNLCD1
          BC    P_HT,DATA    ;DATA=0
          JMP    WNLCD2
      WNLCD1:
          BS    P_HT,DATA    ;DATA=1
      WNLCD2:
          NOP
          NOP
          BC    P_HT,WR        ;WR=0
          NOP            ;延時1.67uS以上
          BS    P_HT,WR        ;WR=1
          NOP            ;延時1.67uS以上
          DJZ    LCD_N
          JMP    WNLCD
          RET
      ;=======
      WBLCDADD:            ;寫操作碼101+首地址碼000000(共9位)
          MOV    A,@0B10100000
      W9LCD:
          MOV    LCD_D,A
          BC    R3,C
          MOV    A,@9
          JMP    WBLCD1
      ;=======
      WBLCDCOM:            ;命令碼100(共3位)
          MOV    A,@0B10000000
          MOV    LCD_D,A
          MOV    A,@3
          JMP    WBLCD1
      ;****************************
      ;LCD顯示初始化
      ;功能:    LCD驅動器HT1621顯示初始化
      ;****************************
      RESTLCD:
          BC    P_HT,CS        ;CS=0,開片選
          NOP
          CALL    WBLCDCOM    ;命令操作
          MOV    A,@0B00000001
          CALL    W9LCD        ;開震蕩源SYSEN
          MOV    A,@0B00101001
          CALL    W9LCD        ;BIAS 1/3
          MOV    A,@0B00000011
          CALL    W9LCD        ;開顯示LCDON
          NOP
          BS    P_HT,CS        ;CS=1,關片選
          RET
      ;****************************
      ;送LCD顯示
      ;功能:    U1顯緩區(0X20-0X28)->LCD驅動器HT1621內RAM
      ;****************************
      MOVLCD:
          WDTC            ;喂狗
          BC    P_HT,CS        ;CS=0,開片選
          MOV    A,@DISBUF1    ;載入顯緩區首地址
          MOV    R4,A
          CALL    WBLCDADD    ;寫操作碼101+首地址碼000000->LCD
      MOVLCD1:
          MOV    A,R0        ;取欲顯示字符代碼
          CALL    TABLCD        ;查表求筆畫碼
          MOV    LCD_D,A
      ;=======填加小數點
          RLC    DISBUF9        ;取小數點->C
          JBC    R3,C        ;
          BS    LCD_D,0        ;填加小數點
      ;=======
          CALL    WBLCD        ;筆畫碼->LCD
          MOV    A,R4
          AND    A,@0B00111111
          XOR    A,@DISBUF7    
          JBS    R3,Z        ;顯緩區地址=最后一個顯示單元跳
          JMP    MOVLCD2
      ;=======小數點
          MOV    A,DISBUF8
          MOV    LCD_D,A
          CALL    WBLCD        ;筆畫碼->LCD
      ;=======
          BS    P_HT,CS        ;CS=1,關片選
          RET
      MOVLCD2:
          INC    R4        ;顯緩區地址+1
          JMP    MOVLCD1

      11樓: >>參與討論 作者: fjf8101 于 2006-8-22 23:07:00 發布:
      學了
      看了,又學了不少,樓主真會鉆啊,照這種精神,學不精才是件奇怪的事情

      12樓: >>參與討論 作者: groge00111 于 2006-8-23 16:28:00 發布:
      樓主是好漢
      樓主真英雄,無私誨人.
      可惜我看書三年了,至今沒做出一個子程式,
      以后請多指教我呀,
      groge00111

      13樓: >>參與討論 作者: McuPlayer 于 2006-8-29 11:37:00 發布:
      不知道這個帖子copy到我的blog合適不
      這可是100%轉帖,還在由于

      14樓: >>參與討論 作者: al2913 于 2006-9-12 19:16:00 發布:
      em78p156 向PT2258送數程序

      ;;===========================================================
      ;程序單位:
      ;程序名稱:
      ;使用芯片:
      ;使用晶振:4MHz
      ;日期:2005年9月14日  //     2005年11月21日
      ;程序編寫者:ANLONG CHEN    
      ;   AL0896@163.com  QQ:529196989    
      ;===========================================================

      對音量PT2258芯片控制,成功生產幾萬臺,放心使用。對樓主支持。!

      ;==========================================================
      ;功能說明:向PT2258送數程序           
      ;使用:AA1,AA2
      ;入口: DD1=要送出的數據           
      ;出口:             
      ;  PT2258_ADD=0X88     ;PT2314地址
      ;==========================================================
      PT2258_ADDCOMM:
          DISI           ;關中斷
          ;CALL STA_I2C  ;啟始
          BC    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BS    PORT5,PT2258_DAT    ;PT2314數據
          NOP
          BS    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BC    PORT5,PT2258_DAT    ;PT2314數據
          NOP
          BC    PORT5,PT2258_CLK    ;PT2314數據

      ;-----------------------------------  
          MOV  A,@PT2258_ADD  ;PT2314地址
          MOV  AA2,A     ;
          ;CALL WBIT_I2CP1 ;送8位數據
          MOV  A,@0X08      ;每字節共需循環8次
          MOV  AA1,A        ;
      ASWBIT_I2CP2:
          JBC   AA2,7    ;
          JMP   ASI2CP_DH  ;
          BC    PORT5,PT2258_DAT    ;PT2258據
          JMP   ASI2C_OUTDAT  ;
        ASI2CP_DH:   
          BS    PORT5,PT2258_DAT    ;PT2258數據
        ASI2C_OUTDAT:
          NOP
          NOP
          ;NOP
          BS    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BC    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BC    PORT5,PT2258_DAT    ;PT2314數據
          RLC   AA2          ;數據寄存器右移一位
          DJZ   AA1          ;共8位,每一次減1,是到0則跳過下一步轉出口
          JMP   ASWBIT_I2CP2   ;8位發完?
          BC    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BS    PORT5,PT2258_CLK    ;PT2314數據
        ASIN_DAT_L:
          JBC   PORT5,PT2258_DAT    ;PT2314數據
          JMP   ASIN_DAT_L    ;等待I2C輸出確認信號,即出L電平
          BC    PORT5,PT2258_CLK    ;PT2314數據
          
      ;----------------    
          MOV  A,DD1     ;PT2314地址
          MOV  AA2,A     ;
          ;CALL WBIT_I2CP1 ;送8位數據
          MOV  A,@0X08      ;每字節共需循環8次
          MOV  AA1,A        ;
      BSWBIT_I2CP2:
          JBC   AA2,7    ;
          JMP   BSI2CP_DH  ;
          BC    PORT5,PT2258_DAT    ;PT2258據
          JMP   BSI2C_OUTDAT  ;
        BSI2CP_DH:   
          BS    PORT5,PT2258_DAT    ;PT2258數據
        BSI2C_OUTDAT:
          NOP
          NOP
          ;NOP
          BS    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BC    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BC    PORT5,PT2258_DAT    ;PT2314數據
          RLC   AA2          ;數據寄存器右移一位
          DJZ   AA1          ;共8位,每一次減1,是到0則跳過下一步轉出口
          JMP   BSWBIT_I2CP2   ;8位發完?
          BC    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BS    PORT5,PT2258_CLK    ;PT2314數據
        BSIN_DAT_L:
          JBC   PORT5,PT2258_DAT    ;PT2314數據
          JMP   BSIN_DAT_L    ;等待I2C輸出確認信號,即出L電平
          BC    PORT5,PT2258_CLK    ;PT2314數據
        
          
          ;CALL SOTP_I2C ;停止
          ;BC    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BC    PORT5,PT2258_DAT    ;PT2314數據
          NOP
          BS    PORT5,PT2258_CLK    ;PT2314數據
          NOP
          BS    PORT5,PT2258_DAT    ;PT2314數據
          NOP
          NOP
          ;NOP
          ;NOP
          ENI               ;開中斷
          RET
      1、 本站不保證以上觀點正確,就算是本站原創作品,本站也不保證內容正確。
      2、如果您擁有本文版權,并且不想在本站轉載,請書面通知本站立即刪除并且向您公開道歉! 以上可能是本站收集或者轉載的文章,本站可能沒有文章中的元件或產品,如果您需要類似的商品請 點這里查看商品列表!
      本站協議。 版權信息。 關于我們。 本站地圖。 營業執照。 發票說明。 付款方式。 聯系方式
      深圳市寶安區西鄉五壹電子商行——粵ICP備16073394號-1;地址:深圳西鄉河西四坊183號;郵編:518102
      E-mail:51dz$163.com($改為@);Tel:(0755)27947428
      工作時間:9:30-12:00和13:30-17:30和18:30-20:30,無人接聽時可以再打手機13537585389
      91嫩草黄片动漫版