1. 程式人生 > >KEIL C51之絕對地址定位

KEIL C51之絕對地址定位

微控制器空間分配看*.M51檔案,ARM,DSP空間分配看*.map檔案

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、若有多個變數或函式要進行絕對地址定位,則應按地址從低到高的順序

使用KeilC51軟體,可以很方便地將程式碼或者資料絕對定位到某個地址。
1、程式碼定位:
方法1:使用偽指令CSEG。比如要將MyFunc1定位到程式碼區C:0x1000,則新建一個A51檔案,新增以下內容:
 PUBLIC  MYFUNC1
 CSEG AT 1000H
MYFUNC1:
 ;其它程式碼
 RET
 在其它原始檔中,就可以呼叫MyFunc()函數了。需要注意的是,編譯器不檢測傳遞引數的數目,僅檢測函式是否有返回值。
方法2:使用BL51 Locate選項。比如在main.c中定義了一個MyFunc2函式,並且要將該函式定位到程式碼區C:0x2000,則從選單中選擇Project->Options for Target 'Target1',在彈出的對話方塊中選擇BL51 Locate頁,在下面的code欄中寫上?PR?MYFUNC2?MAIN(0x2000)即可。
如果想定位多個函式,也可以使用*萬用字元。
2、變數定位:
只有全域性變數可以絕對定位,區域性變數無法實現絕對定位。
方法1:使用_at_關鍵字。宣告一個全域性變數unsigned char data MyBuf1[8] _at_ 0x20;
方法2:使用BL51 Locate選項。比如將main.c中定義的所有data型的全域性變數定位到資料區D:0x28開始的空間,則從選單中
選擇Project->Options for Target 'Target1',在彈出的對話方塊中選擇BL51 Locate頁,在下面的data欄中寫上?DT?MAIN(0x28)即可。
如果是idata,則使用?ID?MAIN(0x28),如果是xdata,則使用?XD?MAIN(0x28),如果是pdata,則使用?PD?MAIN(0x28)
3、堆疊定位:
在STARTUP.A51檔案中定義了堆疊區?STACK,其起始地址同樣可以在BL51 Locate頁中設定,在Stack欄寫上?STACK(0x80)

還可以通過彙編實現
// my.a51

public my_flash_var

cseg at 0F100H

my_flash_var:
    db 55h

end

然後C宣告

// flash.c
extern unsigned char code my_flash_var;


BL51 locate 選項卡中

code range 和 xdata range如果不填寫,編譯預設將程式中相應程式碼和變數從空間前面取起

網上看到有人提到在keil中使用_at_進行絕對地址定位問題,我簡單介紹一下它的用法。

 使用_at_關鍵字對儲存器進行絕對地址定位程式如下

#i nclude<reg51.h>

char xdata LED_Data[50] _at_ 0x8000;

main()

{

   LED_Data[0] = 0x23;

}

在keil中執行以上程式可以在儲存器視窗中輸入 x:0x8000 可以看到0x8000地址中的值為0x23.

值得指出的幾點是

1.在給變數LED_Data[50]定位絕對地址空間時,不能對其賦初值。

2.char xdata LED_Data[50] _at_ 0x8000;這條語句不能主函式中。有些網友提到在按著keil說明中用_at_進行絕對地址定位時,編譯會出現錯誤274,就是將這條語句放在主函式中的原因。

3.keil中地址是自動分配的,所以除非特殊情況否則不提倡使用絕對地址定位。初學者因帖別注意。不要把c當作彙編使用。

對需要/RST復位後要保持變數不變,防止意外改變(比如升級到新程式,變數地址可能被編譯器優化到其他地方),比較有用!!!!

相關推薦

KEIL C51絕對地址定位

微控制器空間分配看*.M51檔案,ARM,DSP空間分配看*.map檔案 1、函式定位: 假如要把C原始檔 tools.c 中的函式 int BIN2HEX(int xx) {     ... } 放在CODE MEMORY的0x1000處,先編譯該工程,然後開啟該工程的

SourceInsight絕對地址和相對地址

    在SourceInsight中,新建的工程基本都是基於絕對地址的,因此如果要把程式碼移到另一臺電腦上時,便需要刪除先前的檔案並重新新增。另一個解決這個問題的方法便是將程式碼的檔案路徑設為相對地址,修改為相對路徑的步驟如下: 首先是按照正常操作建立絕對地址的Sourc

IAR STM32 函式和變數的絕對地址定位

 昨天我突然冒出個想法,能否利用函式和變數的絕對定位,實現程式的模組化更新。  也就是說,如果我要改變某個函式,只需要更新flash裡面一個區域性,也許只需要更新幾百個位元組,而無須重新下載整個上百K的程式。  經過查詢資料和反覆實驗,終於實現了,現總結如下:  1) 把函

CSS絕對定位

用戶 note alt src 基礎 讓我 blue 分享 出現 w3school定義: 絕對定位的元素的位置相對於最近的已定位祖先元素,如果元素沒有已定位的祖先元素,那麽它的位置相對於最初的包含塊。 對於定位的主要問題是要記住每種定位的意義。所以,現在讓我們復習一下學

【轉載】CSS絕對定位及相對定位

通過 原本 second span sof 動手 lan 根據 為什麽 我們先來看看CSS3 Api中對position屬性的相關定義: static:無特殊定位,對象遵循正常文檔流。top,right,bottom,left等屬性不會被應用。 relative:對象遵

HTML絕對定位Absolute

HTML之絕對定位 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8">

Keil C51對C語言的關鍵詞擴充套件八: far

far的出現,是Keil 編譯器為了支援新出現的8051家族增強型MCU,這些增強型MCU可能擁有大於64KB的儲存器。使用far可訪問擴充套件的RAM,使用const far可訪問擴充套件的ROM。 NXP 51MX架構51微控制器提供通過通用指標訪問多達8MB的code

51微控制器中將變數、陣列、函式設定在固定位置,定位絕對地址

一、不帶初值的變數或陣列 直接使用_at_ 關鍵字加上地址就行。 如:  unsigned char idata myvar _at_ 0x40;  unsigned char code myvar[10] _at_ 0x40; _at_ 關鍵字

Keil C51對C語言的關鍵詞擴充套件十三: sfr

sfr用來定義特殊功能暫存器。用法如下: sfr name = address; name 為暫存器名字 address 為暫存器的地址 示例: sfr P0 = 0x80; /* P0口,地址為0x80 */ sfr P1 = 0x90;/* P1口,地址為0x90

Keil C51對C語言的關鍵詞擴充套件二: alien

alien關鍵詞主要是為了C51編譯器與PL/M-51編譯器相容。 在C51編譯器中呼叫PL/M-51函式,須使用alien宣告該函式,如下: extern alien char plm_func (int, char); char c_func (void) {

Keil C51對C語言的關鍵詞擴充套件五: code

code 指定儲存位置位於程式儲存器。程式儲存器只讀,因此code型別的變數,是無法再次賦值的。 unsigned char code ary[ ] = :"Read only"; /* 陣列ary位於程式儲存器 */ ary[0]='a'; /* 錯誤,不可修改*/

Keil C51對C語言的關鍵詞擴充套件十: pdata

外部ram通過一個地址指標暫存器來間接訪問,讀寫效率要低於內部ram。 外部ram容量最大可位64KB。 Keil C51提供兩種外部資料儲存方式,pdata和xdata。 1)xdata儲存型別,指示變數可儲存在外部ram 64KB地址範圍內任意位置。large記憶體模型

CSS設計美麗絕對定位(absolute)的使用(小作品)

關於HTML與CSS的小作品之一: 前端已經學習過絕對定位的概念了: 絕對定位:脫離文件流,以 離自己最近定位的祖先元素(position) 為參照物,如果沒有定位的祖先元素,則追溯到以body為參照物,通過四個偏移屬性進行偏移,不會影響文件中的元素,其margin不會與

Keil C51對C語言的關鍵詞擴充套件十一: xdata

xdata宣告的變數位於外部ram 64KB地址範圍內某一位置。 程式示例: unsigned int xdata m=0; /* 宣告一個全域性變數,可位於外部ram 64KB地址範圍內任意位置,由

elf檔案中程式碼段有絕對地址但重定位表中無.text.rel

#include int main() { printf("hello\n"); return 0; }

Keil C51對C語言的關鍵詞擴充套件六: compact

函式的引數和區域性變數儲存在記憶體模型指定的預設區域內。 我們可以通過small,compact 或large 指定一個函式使用何種記憶體模型。 #pragma small /* 預設記憶體模型為small*/ extern int calc (char

OpenStack(ice house)雲主機獲取不到DHCP地址故障分析定位與處理辦法

公司生產機房最近淘汰下來一批裝置,不算太舊,普遍CPU兩顆兩核,少數四顆四核,但其中已經有若干臺主機安裝不了CentOS7的系統了。因為主機型號太舊,CentOS7已經不提供磁碟驅動的支援了。所以只好將就著裝成了CentOS6.7。為了更好得發揮餘熱,著手部署了一套Open

散列技術地址法(基於無序鏈表)

stc 分享 item size obj 單鏈表 結果 clu arc 源碼例如以下: #include <stdlib.h> #include <stdio.h> #define hash(v,M) (v % M) typedef c

iOS開發地圖與定位

control 移動 idt line tor mkmapview 什麽 .cn 構建   不管是QQ還是微信的移動client都少不了定位功能,之前在微信demo中沒有加入定位功能,今天就寫個定位的小demo來了解一下定位和地圖的東西。地圖和定位看上去是挺高大

Appium python自動化測試系列元素的定位(六)

keditor logs ren 匹配 4.4 contex 應用 需要 運用 ?6.1 常用定位方法講解 對象定位是自動化測試中很關鍵的一步,也可以說是最關鍵的一步,畢竟你對象都沒定位那麽你想操作也不行。所以本章節的知識我希望大家多動手去操作,不要僅僅只是書本上的知識,畢