<li id="8g3ty"><tbody id="8g3ty"><th id="8g3ty"></th></tbody></li>
    <label id="8g3ty"><samp id="8g3ty"></samp></label>
  • <span id="8g3ty"></span>

    1. <center id="8g3ty"><optgroup id="8g3ty"></optgroup></center>
    2. <bdo id="8g3ty"><meter id="8g3ty"><bdo id="8g3ty"></bdo></meter></bdo><center id="8g3ty"><optgroup id="8g3ty"></optgroup></center>
      <label id="8g3ty"><samp id="8g3ty"></samp></label>

    3. 電子開發網

      電子開發網電子設計 | 電子開發網Rss 2.0 會員中心 會員注冊
      搜索: 您現在的位置: 電子開發網 >> 電子開發 >> EDA開發應用 >> Keilc >> 正文

      KEIL C 使用總結大全

      作者:佚名    文章來源:本站原創    點擊數:    更新時間:2011-6-6
      我們使用Keil C調試某系統時積累的一些經驗

      1、在Windows2000下面,我們可以把字體設置為Courier,這樣就可以顯示正常。
      2、當使用有片外內存的MCU(如W77E58,它有1K片外內存)的時候,肯定要設置標志位,并且編譯方式要選擇大模式,否則會出錯。
      3、當使用Keil C跟蹤程序運行狀態的時候,要把引起Warning的語句屏蔽,否則有可能跟蹤語句的時候會出錯。
      4、在調用數組的時候,Keil C是首先把數組Load進內存。如果要在C中使用長數組的時候,我們可以使用code關鍵字,這樣就實現了匯編的DB的功能,Keil C是不會把標志code的數組Load入內存的,它會直接讀取Rom。
      5、拉高管腳的執行速度遠遠比檢查管腳電平的要快。當編程涉及到有關通信,時序是很重要的。
      6、在等待管腳電平變化的時候,我們需要設置好超時處理,否則程序就會因為一個沒有預計的錯誤而死鎖。
      7、能用C語言實現的地方,盡量不要用匯編,尤其在算法的實現,用匯編是晦澀難懂。
      8、程序的幾個參數數組所占篇幅很大,其中液晶背景數組最長,有四千個Byte,因而把那些初始化數組都放在另外一個C文件,在主文件使用使用關鍵字extern定義,這樣就不會對主文件的編寫造成干擾。
      9、所有函數之間的相關性越低越有利于以后功能的擴展。
      10、6.20版在編譯帶code關鍵字的數組時,編譯通過但是單片機運行結果是錯誤的,改用6.14版后正常。


      ------------------------------------------------------------------------------------------------------------------------------------------------------

      問:C51 怎樣將1個子程序段定位在1個固定的地址位置?     
      以下2問題均要用C51解決
      1。 怎樣將1個子程序段定位在1個固定的地址位置?
          例如將 INT BCD2HEX(INT XX)定位在1000H
      2。 HOW在EEPROM 中固定的位置存放1字符串?
          如在200H處放“COPYRIGHT 2001-11”

      答: 函數定位與變量定位...

      1、函數定位:
      假如要把C源文件 tools.c 中的函數
      int BIN2HEX(int xx)
      {
        ...
      }
      放在CODE MEMORY的0x1000處,先編譯該工程,然后打開該工程的M51文件,在
      * * *   C O D E   M E M O R Y   * * *
      行下找出要定位的函數的名稱,應該形如:
      CODE    xxxxH     xxxxH     UNIT         ?PR?_BCD2HEX?TOOLS
      然后在:
      Project->Options for Target ...->BL51 Locate:Code
      中填寫如下內容:
      ?PR?_BCD2HEX?TOOLS(0x1000)
      再次Build,在M51中會發現該函數已放在CODE MEMORY的0x1000處了

      2、賦初值的變量定位:
      要將某變量定位在一絕對位置且要賦初值,此時用 _at_ 不能完成,則如下操作:
      在工程中建立一個新的文件,如InitVars.c,在其中對要處理的變量賦初值(假設是code變
      量):
      char code myVer = {"COPYRIGHT 2001-11"};
      然后將該文件加入工程,編譯,打開M51文件,若定義的是code型,則在
      * * *   C O D E   M E M O R Y   * * *
      下可找到:
      CODE    xxxxH     xxxxH     UNIT         ?CO?INITVARS
      然后在:
      Project->Options for Target ...->BL51 Locate:Code
      中填入:
      ?CO?INITVARS(0x200)
      再次編譯即可。

      相應地,如為xdata變量,則InitVars.c中寫:
      char xdata myVer = {"COPYRIGHT 2001-11"};
      然后將該文件加入工程,編譯,打開M51文件,在
      * * *  X D A T A   M E M O R Y  * * *
      下可找到:
      XDATA   xxxxH     xxxxH     UNIT         ?XD?INITVARS
      然后在:
      Project->Options for Target ...->BL51 Locate:Xdata
      中填入:
      ?XD?INITVARS(0x200)
      再次編譯即可。相應地,若定義的是data/idata等變量,則相應處理即可。

      3、若有多個變量或函數要進行絕對地址定位,則應按地址從低到高的順序排列。
       
      ------------------------------------------------------------------------------------------------------------------------------------------------------

      C51的一些誤區和注意事項
      2005-11-24 9:03:43
      1)C忌諱絕對定位。 常看見初學者要求使用_at_,這是一種謬誤,把C當作ASM看待了。在C中變量的定位是編譯器的事情,初學者只要定義變量和變量的作 用域,編譯器就把一個固定地址給這個變量。怎么取得這個變量的地址?要用指針。比如unsigned char data x;后,x的地址就是&x, 你只要查看這個參數,就可以在程序中知道具體的地址了。所以俺一看見要使用絕對定位的人,第一印象就是:這大概是個初學者。
      2)設置SP的問題。 原因和1差不對,編譯器在把所有變量和緩沖區賦予地址后,自動把最后一個字節開始的地方,作為SP的開始位置,所以初學者是不必 要去理會的。這體現C的優越性,很多事情C編譯時候做了。
      3)用C的主程序結構: #i nclude <reg52.h> void main(void) { while(1); } 這是個最小的成功的C程序,包括頭部文件和程序主體。 頭部文件的名詞解釋:引用的外部資源文件,這個文件包括了硬件信息和外部模塊提供的可使用的函數和變量的說明。可以用文本方 式打開reg52.h,仔細研究下,會有一些寫程序的體會。
      4)這樣構成一個C項目 在C中,常用項目來管理。項目一般分為兩大塊:C文件塊和頭部文件塊。 我們常把不同功能寫在不同的C文件中,依靠項目的管理,最后把所有文件連接起來,這樣就可以得到可以燒錄的HEX文件或BIN文件。 這些C文件中,有且只有唯一一個包括main()函數,和3)中一樣的C文件。 用頭部文件把各個不同的C互相連接起來。一個C文件基本上要對應有一個H頭部文件,這個H文件就包含本C文件中可以提供給外面使 用的變量和函數,沒有在H文件中列出的文件,可以算是該C文件的內部函數和變量,外部C不能使用。 例子:a.C: unsigned char i; unsigned char mWork; void Test1(void) { mWork ; } void Test2(void) { i ; } a.h文件中: extern unsigned char i; extern void Test1(void); 這樣主程序M.c中: #i nclude <reg52.h> /*C編譯器內部自帶的H文件,使用<>*/ #i nclude "a.h" /*自定義的H文件,一般用""*/ void main(void) { Test1(); /*使用a.c模塊文件中的函數*/ while(1){ i ; /*使用a.c模塊文件中的變量*/ } }
      5)51家族 核心都是基于8031的,有很多在此核心上進行擴展,有的把程序存儲器放在內部:89c(S)51..,有的增加了RAM:89c(S)52..,有的增加 了一些專用硬件80C552...,有的改變時鐘時序W77E58...。市面上現在常用的主要有ATMEL公司的AT89X系列,PHILIPS的P87(89)x,臺 灣WINBOND的w77(78)x系列,Cygnal的C8051Fx系列。
      6)51單片機結構的C描述 這里不講51的具體結構,只是引導初學者快速理解51單片機的物理結構。寄存器和IO及其它硬件設備的地址名稱,在相應的C頭部文件 中可以找到。51為reg51.h,52為reg52.h,以次類推,比如winbond的78E58就為w78e58.h這些H文件中的描述: srf,定義一個8位的設備。 srf16,定義一個16位的設備。 sbit,定義一個位的設備。 用這些語句定義后,就可以在C中象匯編一樣使用這些硬件設備,這是單片機應用比標準C特殊的地方,其它差別很少。
      7)在51系列中data,idata,xdata,pdata的區別 data:固定指前面0x00-0x7f的128個RAM,可以用acc直接讀寫的,速度最快,生成的代碼也最小。 idata:固定指前面0x00-0xff的256個RAM,其中前128和data的128完全相同,只是因為訪問的方式不同。idata是用類似C中的指針方式 訪問的。匯編中的語句為:mox ACC,@Rx.(不重要的補充:c中idata做指針式的訪問效果很好) xdata:外部擴展RAM,一般指外部0x0000-0xffff空間,用DPTR訪問。 pdata:外部擴展RAM的低256個字節,地址出現在A0-A7的上時讀寫,用movx ACC,@Rx讀寫。這個比較特殊,而且C51好象有對此BUG, 建議少用。但也有他的優點,具體用法屬于中級問題,這里不提。
      8)startup.a51的作用 和匯編一樣,在C中定義的那些變量和數組的初始化就在startup.a51中進行,如果你在定義全局變量時帶有數值,如unsigned char data xxx=100;,那startup.a51中就會有相關的賦值。如果沒有=100,startup.a51就會把他清0。(startup.a51==變量的初始化)。 這些初始化完畢后,還會設置SP指針。對非變量區域,如堆棧區,將不會有賦值或清零動作。 有人喜歡改startup.a51,為了滿足自己一些想當然的愛好,這是不必要的,有可能錯誤的。比如掉電保護的時候想保存一些變量, 但改startup.a51來實現是很笨的方法,實際只要利用非變量區域的特性,定義一個指針變量指向堆棧低部:0xff處就可實現。, 為什么還要去改? 可以這么說:任何時候都可以不需要改startup.a51,如果你明白它的特性。
       
      關于在 KEIL C51 中嵌入匯編以及C51與A51間的相互調用

         如何在 KEIL C51(v6.21) 中調用匯編函數的一個示例 [ycong_kuang]

      有關c51調用匯編的方法已經有很多帖子講到,但是一般只講要點,很少有對整個過程作詳細描述,對于初學者是不夠的,這里筆者
      通過一個簡單例子對這個過程進行描述,希望能對初學者有所幫助。幾年來,在這個論壇里筆者得到很多熱心人指導,因此也希望
      藉此盡一點綿薄之力。

      在這個例子里,闡述了編寫c51程序調用匯編函數的一種方法,這個外部函數的入口參數是一個字符型變量和一個位變量,返回值是
      一個整型變量。例中,先用c51寫出這個函數的主體,然后用SRC控制指令編譯產生asm文件,進一步修改這個asm文件就得到我們所
      要的匯編函數。該方法讓編譯器自動完成各種段的安排,提高了匯編程序的編寫效率。

      step1. 按寫普通c51程序方法,建立工程,在里面導入main.c文件和CFUNC.c文件。

      相關文件如下:
      //main.c文件
      #include < reg51.h >

      #define uchar unsigned char
      #define uint unsigned int

      extern uint AFUNC(uchar v_achr,bit v_bflag);

      void main()
      {
          bit BFLAG;
          uchar mav_chr;
          uint    mvintrslt;

          mav_chr=0xd4; BFLAG=1;
          mvintrslt=AFUNC(mav_chr,BFLAG);
      }

      //CFUNC.c文件

      #define uchar unsigned char
      #define uint unsigned int

      uint AFUNC(uchar v_achr,bit v_bflag)
      {
          uchar tmp_vchr;
          uint  tp_vint;

          tmp_vchr=v_achr;
          tp_vint=(uint)v_bflag;
          return tmp_vchr+(tp_vint<<8);
      }

      step2. 在 Project 窗口中包含匯編代碼的 C 文件上右鍵,選擇“Options for ...”,點擊右邊的“Generate Assembler SRC
              File”和“Assemble SRC File”,使檢查框由灰色變成黑色(有效)狀態;

      step3. 根據選擇的編譯模式,把相應的庫文件(如 Small 模式時,是 Keil\C51\Lib\C51S.Lib)加入工程中,該文件必須作為工
             程的最后文件;

      step4. build這個工程后將會產生一個CFUNC.SRC的文件,將這個文件改名為CFUNC.A51(也可以通過編譯選項直接產生CFUNC.A51文
             件),然后在工程里去掉庫文件(如C51S.Lib)和CFUNC.c,而將CFUNC.A51添加到工程里。

      //CFUNC.SRC文件如下
      .\CFUNC.SRC generated from: CFUNC.c
      NAME CFUNC

      ?PR?_AFUNC?CFUNC     SEGMENT CODE
      ?BI?_AFUNC?CFUNC     SEGMENT BIT OVERLAYABLE
          PUBLIC    ?_AFUNC?BIT
          PUBLIC    _AFUNC

          RSEG  ?BI?_AFUNC?CFUNC
      ?_AFUNC?BIT:
          v_bflag?041:   DBIT   1
      ; #define uchar unsigned char
      ; #define uint unsigned int
      ;
      ; uint AFUNC(uchar v_achr,bit v_bflag)

          RSEG  ?PR?_AFUNC?CFUNC
      _AFUNC:
          USING    0
                  ; SOURCE LINE # 5
      ;---- Variable 'v_achr?040' assigned to Register 'R7' ----
      ; {
                  ; SOURCE LINE # 6
      ;     uchar tmp_vchr;
      ;     uint    tp_vint;
      ;
      ;     tmp_vchr=v_achr;
                  ; SOURCE LINE # 10
      ;---- Variable 'tmp_vchr?042' assigned to Register 'R5' ----
          MOV      R5,AR7
      ;     tp_vint=(uint)v_bflag;
                  ; SOURCE LINE # 11
          MOV      C,v_bflag?041
          CLR      A
          RLC      A
      ;---- Variable 'tp_vint?043' assigned to Register 'R6/R7' ----
      ;     return tmp_vchr+(tp_vint<<8);
                  ; SOURCE LINE # 12
          MOV      R6,A
          MOV      R4,#00H
          CLR      A
          ADD      A,R5
          MOV      R7,A
          MOV      A,R4
          ADDC     A,R6
          MOV      R6,A
      ; }
                  ; SOURCE LINE # 13
      ?C0001:
          RET
      ; END OF _AFUNC

          END

      step5. 檢查main.c的“Generate Assembler SRC File”和“Assemble SRC File”是否有效,若是有效則點擊使檢查框變成無效狀
             態;再次build這個工程,到此你已經得到匯編函數的主體,修改函數里面的匯編代碼就得到你所需的匯編函數了。

      參考文獻:
        1.徐愛鈞,彭秀華。單片機高級語言C51windows環境編程與應用,電子工業出版社
        2.www.c51bbs.com,  C51編程:關于在 KEIL C51 中直接嵌入匯編。。。帖子編號: 83838 發表用戶:Youth
      ------------------------------------------------------------------------------------------------------------------------------------------------------
                                       keil中匯編函數調用c51函數 [ycong_kuang]

      在keil的寫法可參考89852帖子,具體如下:
      與89852帖子相比,第一步在工程里多了一個被匯編調用的c51的函數文件(c51func.c),至于匯編函數還是先用c51編寫出主體
      (a51func.c),這樣匯編程序接口和段都交給編譯器處理,你只管在編譯成匯編代碼后按你的要求改寫匯編代碼就行了。

      例程如下:
      //main.c
      #include < reg51.h >

      #define uchar unsigned char
      #define uint unsigned int

      extern uint AFUNC(uchar v_achr,bit v_bflag);

      void main()
      {
          bit BFLAG;
          uchar mav_chr;
          uint    mvintrslt;

          mav_chr=0xd4; BFLAG=1;
          mvintrslt=AFUNC(mav_chr,BFLAG);
      }

      //a51FUNC.c

      #define uchar unsigned char
      #define uint unsigned int

      extern uint CFUNC(uint);

      uint AFUNC(uchar v_achr,bit v_bflag)    //c51寫的匯編函數,最終要變成匯編代碼
      {
          uchar tmp_vchr;
          uint  tp_vint;

          tmp_vchr=v_achr;
          tp_vint=(uint)v_bflag;

          return CFUNC(tp_vint);             //這里調用一個c51函數
      }

      //c51FUNC.c

      #define uchar unsigned char
      #define uint unsigned int

      uint CFUNC(uint v_int)                //被匯編函數調用c51函數
      {
          return v_int<<2;
      }

      第二步是按89852帖子的step2,3,4把用c51寫的(匯編)函數變成a51文件(今天我試了一下step3可以不要)例程編譯結果如
      下:
      ; .\a51func.SRC generated from: a51func.c
      NAME    A51FUNC

      ?PR?_AFUNC?A51FUNC   SEGMENT CODE
      ?DT?_AFUNC?A51FUNC   SEGMENT DATA OVERLAYABLE
      ?BI?_AFUNC?A51FUNC   SEGMENT BIT OVERLAYABLE
          EXTRN    CODE (_CFUNC)
          PUBLIC    ?_AFUNC?BIT
          PUBLIC    _AFUNC

          RSEG  ?DT?_AFUNC?A51FUNC
      ?_AFUNC?BYTE:
         tmp_vchr?042:   DS   1

          RSEG  ?BI?_AFUNC?A51FUNC
      ?_AFUNC?BIT:
          v_bflag?041:   DBIT   1
      ; //a51FUNC.c
      ;
      ; #define uchar unsigned char
      ; #define uint unsigned int
      ;
      ; extern uint CFUNC(uint);
      ;
      ; uint AFUNC(uchar v_achr,bit v_bflag)

          RSEG  ?PR?_AFUNC?A51FUNC
      _AFUNC:        ;c51所寫的函數產生的匯編代碼從這里開始
          USING    0
                  ; SOURCE LINE # 8
      ;---- Variable 'v_achr?040' assigned to Register 'R7' ----
      ; {
                  ; SOURCE LINE # 9
      ;     uchar tmp_vchr;
      ;     uint  tp_vint;
      ;
      ;     tmp_vchr=v_achr;
                  ; SOURCE LINE # 13
          MOV      tmp_vchr?042,R7
      ;     tp_vint=(uint)v_bflag;
                  ; SOURCE LINE # 14
          MOV      C,v_bflag?041
          CLR      A
          MOV      R6,A
          RLC      A
          MOV      R7,A
      ;---- Variable 'tp_vint?043' assigned to Register 'R6/R7' ----
      ;      這里說明R6,R7內容就是tp_vint
      ;     return CFUNC(tp_vint);
                  ; SOURCE LINE # 16
          LCALL    _CFUNC    ;這里調用了用c51寫的函數
      ; }
                  ; SOURCE LINE # 17
      ?C0001:
          RET
      ; END OF _AFUNC

          END

      這個文件就是你的匯編函數所在文件,把函數里面的匯編代碼修改成你所需的匯編函數就ok了。

      建議參考 徐愛鈞,彭秀華所寫的《單片機高級語言C51windows環境編程與應用》或馬忠梅所寫的
      《單片機的c語言應用程序設計》有關混合語言編程有關章節

      ------------------------------------------------------------------------------------------------------------------------------------------------------
                                      關于在 KEIL C51 中直接嵌入匯編。。。 [Youth]
      有時在C51程序中需要嵌入一些匯編代碼,這時當然可以用通常的作法:
      按照 C51 與匯編的接口寫一個匯編函數,然后在 C51 程序中調用該函數。(此種方法可在論壇里搜索,以前有很多帖子講到,不再
      重復)

      下面介紹直接嵌入匯編代碼的方法:

      1、在 C 文件中要嵌入匯編代碼片以如下方式加入匯編代碼:
      #pragma ASM
       ; Assembler Code Here
      #pragma ENDASM

      2、在 Project 窗口中包含匯編代碼的 C 文件上右鍵,選擇“Options for ...”,點擊右邊的“Generate Assembler SRC File”
      和“Assemble SRC File”,使檢查框由灰色變成黑色(有效)狀態;

      3、根據選擇的編譯模式,把相應的庫文件(如 Small 模式時,是 Keil\C51\Lib\C51S.Lib)加入工程中, 該文件必須作為工程的最
      后文件;

      4、編譯,即可生成目標代碼。

       C51中變量的空間分配幾個方法
      在C51中變量的空間分配幾個方法
      liy-tj 發表于 2006-1-24 12:59:19

      1、 data區空間小,所以只有頻繁用到或對運算速度要求很高的變量才放到data區內,比如for循環中的計數值。

      2、 data區內最好放局部變量。

      因為局部變量的空間是可以覆蓋的(某個函數的局部變量空間在退出該函數是就釋放,由別的函數的局部變量覆蓋),可以提高內存利用率。當然靜態局部變量除外,其內存使用方式與全局變量相同;

      3、 確保你的程序中沒有未調用的函數。

      在Keil C里遇到未調用函數,編譯器就將其認為可能是中斷函數。函數里用的局部變量的空間是不釋放,也就是同全局變量一樣處理。這一點Keil C做得很愚蠢,但也沒辦法。

      4、 程序中遇到的邏輯標志變量可以定義到bdata中,可以大大降低內存占用空間。

      在51系列芯片中有16個字節位尋址區bdata,其中可以定義8*16=128個邏輯變量。定義方法是: bdata bit LedState;但位類型不能用在數組和結構體中。

      5、 其他不頻繁用到和對運算速度要求不高的變量都放到xdata區。

      6、 如果想節省data空間就必須用large模式,將未定義內存位置的變量全放到xdata區。當然最好對所有變量都要指定內存類型。

      7、 當使用到指針時,要指定指針指向的內存類型。

      在C51中未定義指向內存類型的通用指針占用3個字節;而指定指向data區的指針只占1個字節;指定指向xdata區的指針占2個字節。如指針p是指向data區,則應定義為: char data *p;。還可指定指針本身的存放內存類型,如:char data * xdata p;。其含義是指針p指向data區變量,而其本身存放在xdata區。

      Tags:KEIL C使用總結大全,keilc  
      責任編輯:admin
      請文明參與討論,禁止漫罵攻擊,不要惡意評論、違禁詞語。 昵稱:
      1分 2分 3分 4分 5分

      還可以輸入 200 個字
      [ 查看全部 ] 網友評論
      推薦文章
      最新推薦
      熱門文章
      關于我們 - 聯系我們 - 廣告服務 - 友情鏈接 - 網站地圖 - 版權聲明 - 在線幫助 - 文章列表
      返回頂部
      刷新頁面
      下到頁底
      晶體管查詢
      主站蜘蛛池模板: 久久综合日本熟妇| 久久狠狠爱亚洲综合影院| 亚洲综合久久精品无码色欲| 亚洲综合图片小说区热久久| 一本狠狠色丁香婷婷综合久久| 色欲香天天综合网站| 激情五月综合综合久久69| 精品亚洲综合久久中文字幕| 涩涩色中文综合亚洲| 激情综合色五月丁香六月亚洲| 香蕉蕉亚亚洲aav综合| 色综合天天娱乐综合网| 一本一道久久精品综合| 狠狠人妻久久久久久综合蜜桃| 色综合久久综合中文综合网| 亚洲伊人久久综合影院| 色婷婷99综合久久久精品 | 狠狠色婷婷狠狠狠亚洲综合| 久久婷婷五月国产色综合| 一本丁香综合久久久久不卡网站| 2020久久精品亚洲热综合一本| 色噜噜狠狠狠综合曰曰曰| 国产精品亚洲综合一区在线观看| 亚洲婷婷第一狠人综合精品| 伊伊人成亚洲综合人网7777| 伊人亚洲综合青草青草久热| 色综合天天色综合| 亚洲国产综合无码一区二区二三区| 中文字幕人成无码人妻综合社区| 久久综合综合久久狠狠狠97色88| 久久久久综合中文字幕 | 国产精品天干天干在线综合| 女人和拘做受全程看视频日本综合a一区二区视频 | 色综合无码AV网站| 色欲老女人人妻综合网| 69国产成人综合久久精品| 亚洲色欲啪啪久久WWW综合网| 色综合色狠狠天天综合色| 亚洲第一综合天堂另类专| 一本一道久久a久久精品综合| 亚洲综合激情另类专区|