c51編譯器需做什麼處理
『壹』 Keil c51編譯器。D:\KEIL C51 工程C(32): error C141: syntax error near 'void',如何解決
timer1(void) interrupt 3 using 1
{
static unsigned char t;
TH1=0x4C;
TL1=0x00;
TF1=0;
t++;
if(t==20)
{
t=0;
delay1s=1;
}
}
這一部分放到最後也就是大括弧的後邊
『貳』 51單片機的編程問題
1:C51編譯器如何區分位地址和位元組地址
是靠預定義實現的,比如:sfr P0 = 0x80; sbit P0_0 = 0x80;前者聲明了P0埠地址位於0x80,後者說明了P0埠的bit0,即P0.0位於位地址空間0x80處。這2個0x80具有完全不同的含義,靠關鍵字sfr和sbit來區別。這樣當程序被編譯時,編譯器會依此編譯成相應的匯編語言。例如:
C51語句: P0 = 1;
P0聲明為sfr,因此編譯成:mov 80h,01h,將把0x01數據送入0x80單元,由於0x80單元物理上對應P0埠,因此,P0.0腳將輸出高電平(其實是呈現高阻態,P0口獨有的),其他.1-.7腳輸出低電平。
C51語句: P0_0 = 1;
P0_0聲明為sbit,因此編譯成:setb 80h,這將把位地址空間的0x80地址的bit的值置1。這個位正是P0口的bit0,執行後,P0.0將輸出高阻態。而P0.1-.7不會變化。
2:C51為什麼要嵌套匯編
51單片機一個顯著優點就是指令執行時間固定,因此可以適應時序要求嚴格的場合。例如符合ISO7816協議的cpu卡的讀寫,對時序要求比較嚴格。其實就是用io腳做出來的同步半雙工串口。支持cpu卡的程序一般比較龐大,需要用c51來組織,但是由於c編譯的不確定性,必須把底層程序封裝成匯編語言模塊嵌入到工程中。這就帶來幾個問題:如何聲明函數、參數如何傳遞等。限於篇幅,不能說得很細。下面舉例:
匯編程序單獨保存一個文件,加入到工程中,函數如下:
_proc_a:
mov a, r7
inc a
mov r7, a
ret
用c語言在.h文件中聲明: extern unsigned char proc_a(unsigned char val);
調用時形如: retvalue = proc_a(0x11);
說明:
a:匯編程序如果帶參數,則需要在匯編程序前多加一個下劃線。而聲明它的地方不用加(偉福編譯器這么要求的)。
b:函數的形參中第一參數用R7傳遞,函數返回值用R7返回,這是C51的通用規范。其他參數都有相應規定。函數可以返回一個位,用psw的c位返回。c:上面的語句,執行順序是把0x11給R7,然後跳轉子程序,子程序將它加1後送回。
d:函數跳轉到匯編程序時,本區的R0-R7,A,B,PSW,DPTR等寄存器可以供子程序使用,不必考慮調用後是否要恢復這些常規資源。上例中,A的值被函數使用了,編程者不必恢復調用前的值。
『叄』 C51編譯器的全部作用
後面也少了兩個}
i的作用范圍是在整個main函數裡面,
K是在定義處到main的最後,
static int j 是靜態類型,也是在整個main函數里,只是跳出函數後值不變
另外,虛機團上產品團購,超級便宜
『肆』 C51單片機入門編程問題
1、你不要想它怎麼關聯的,它就是一種固定的寫法,語法就這樣。你只能這樣寫,也當你寫成這樣的時候,編譯器會認得出來它代表什麼的,寫成其它的話,編譯就會報錯了。所以不要再糾結這個問題。語法這樣定的,遵守就行了。
2、0xfe不是什麼地址,就是個簡單的賦值,OutData就是等於0xfe。
OutData要是指一個埠的話,最前面是要有宏定義的,比如
#define OutData P0
上面表示用OutData這個詞代替P0。
為什麼要麼定義,而不直接用P0就好了,你去查一下宏定義的好處就知道為什麼會有這種用法了~
『伍』 關於C51單片機單片機的幾個問題
1、徐漢斌版單片機微型計算機原理教材P144上說「中斷服務程序最後一條指令必須是中斷返回指令RETI」,
這句話是不是錯了?
如果最後一句話是跳轉指令不是也可以么,只不過程序不會回到斷點處罷了,PC也會填充跳轉處PC地址
--寫跳轉指令、或者寫其它什麼指令,都行,隨你便。單片機都會執行。
--只是,單片機沒有執行 RETI 指令,中斷程序就沒有結束。
--如果,你不寫 RETI,中斷後,單片機就永遠處於中斷程序之內。
2、在方式0定時器T0的初值為1E0CH,則TH0,TL0的初值分別為()
這題答案給的居然是F0H、0CH,我覺得分明是1EH、0CH啊,是不是答案錯了
--寫成二進制:1E0CH = 0001 1110 0000 1100B
--取其低 13 位,寫成高八位、低五位:11110000、01100
--方式0的初值,就應該是:F0、0C。
3、」MCS 51的程序計數器PC不能被用戶使用,因為他沒有地址「,
首先,不能被用戶使用指的收拾什麼?其次,它沒有地址那他到底在哪?
--PC 的數值,時時刻刻,在自動加一,這個特點,用戶對其,不可控制。
--但是,用戶,可以用 JMP 指令,改變 PC 的數值。
--說 PC 不能被用戶使用,實際上是他不會用。
--51 單片機裡面,確實沒有 PC 的地址,因為,誰都不需要這個地址。
4、MOV 20H,@DPTR 這個語句錯了是因為DPTR只能用於片外定址么
--這個指令,並不存在。
DPTR只能用於片外定址么
--查一下指令表,就知道了。
5、」80C51單片機子程序調用時能自動保護斷點和現場「,
這句話錯了是不是因為只能自動保護斷點不能自動保護現場?
--中斷時,51 單片機,採用壓棧的方法,自動的保護斷點地址。
--保護現場 ?
--單片機,不知道你的現場是什麼。
--把單片機和保護現場聯系在一起,就是狗戴嚼子,胡勒!
6、MOV A,#33H 是把33H當成無符號數吧?那麼如果我想移入一個帶符號數呢
就寫上負號即可。
MOV A, #-33H
這就行了。
7、向前轉移的偏移量為什麼等於(目的地址+0100H)-(原地址+3),0100H是什麼?
--編寫程序,現在都用編譯軟體來進行編譯。
--編譯軟體,會自動計算程序中的偏移量。
--編程人,根本不用討論偏移量的計算,以及推導公式。
--有些教材,作者的思維,還停留在人工編譯的階段,抱殘守缺,不用理他。
--0100H,是256。
『陸』 關於c51單片機使用keil編譯器的一些問題
1.如果沒有被調用,就不會被編譯,自然不佔用空間。
2.只要結構體有元素被使用,就要佔據整個結構體的空間。
3.多出來的0.2是位變數,表示你用了兩個bit的變數。
『柒』 「Keil C51」下如何讓編譯器優先使用片內「RAM」
C51內存結構深度剖析
在編寫應用程序時,定義一個變數,一個數組,或是說一個固定表格,到底存儲在什麼地方;當定義變數大小超過MCU的內存范圍時怎麼辦;如何控制變數定義不超過存儲范圍;以及如何定義變數才能使得變數訪問速度最快,寫出的程序運行效率最高。以下將一一解答。
1 六類關鍵字(六類存儲類型)
data idata xdata pdata code bdata
code: code memory (程序存儲器也即只讀存儲器)用來保存常量或是程序。code memory 採用16位地址線編碼,可以是在片內,或是片外,大小被限制在64KB
作用:定義常量,如八段數碼表或是編程使用的常,在定義時加上code 或明確指明定義的常量保存到code memory(只讀)
使用方法:
char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
此關鍵字的使用方法等同於const
data data memory (數據存儲區)只能用於聲明變數,不能用來聲明函數,該區域位於片內,採用8位地址線編碼,具有最快的存儲速度,但是數量被限制在128byte或更少。
使用方法:
unsigned char data fast_variable=0;
idata idata memory(數據存儲區)只能用於聲明變數,不能用來聲明函數. 該區域位於片內,採用8位地址線編碼,內存大小被限制在256byte或更少。該區域的低地址區與data memory地址一致;高地址區域是52系列在51系列基礎上擴展的並與特殊功能寄存器具有相同地址編碼的區域。即:data memory是idata memory的一個子集。
xdata xdata memory 只能用於聲明變數,不能用來聲明函數,該區域位於MCU
外部,採用16位地址線進行編碼,存儲大小被限制在64KB以內。
使用方法:
unsigned char xdata count=0;
pdata pdata memory 只能用於聲明變數,不能用來聲明函數,該區域位於MCU外部,採用8位地址線進行編碼。存儲大小限制在256byte. 是xdata memory的低256byte。為其子集。
使用方法
unsigned char pdata count=0;
bdata bdata memory 只能用於聲明變數,不能用來聲明函數。該區域位於8051內部位數據地址。定義的量保存在內部位地址空間,可用位指令直接讀寫。
使用方法:
unsigned char bdata varab=0
註:有些資料講,定義字元型變數時,在預設unsigned 時,字元型變數,默認為無符號,與標准C不同,但我在Keil uVision3中測試的時候發現並非如此。在預設的情況下默認為有符號。或許在以前的編譯器是默認為無符號。所以看到有的資料上面這樣講的時候,要注意一下,不同的編譯器或許不同。所以我們在寫程序的時候,還是乖乖的把unsigned signed 加上,咱也別偷這個懶。
2函數的參數和局部變數的存儲模式
C51 編譯器允許採用三種存儲器模式:SMALL,COMPACT 和LARGE。一個函數的存儲器模式確定了函數的參數的局部變數在內存中的地址空間。處於SMALL模式下的函數參數和局部變數位於8051單片機內部RAM中,處於COMPACT和LARGE模式下的函數參數和局部變數則使用單片機外部RAM。在定義一個函數時可以明確指定該函數的存儲器模式。方法是在形參表列的後面加上一存儲模式。
示例如下:
#pragma large //此預編譯必須放在所有頭文前面
int func0(char x,y) small;
char func1(int x) large;
int func2(char x);
註:
上面例子在第一行用了一個預編譯命令#pragma 它的意思是告訴c51編譯器在對程序進行編譯時,按該預編譯命令後面給出的編譯控制指令LARGE進行編譯,即本常式序編譯時的默認存儲模式為LARGE.隨後定義了三個函數,第一個定義為SMALL存儲模式,第二個函數定義為LARGE第三個函數未指定,在用C51進行編譯時,只有最後一個函數按LARGE存儲器模式處理,其它則分別按它們各自指定的存儲器模式處理。
本例說明,C51編譯器允許採用所謂的存儲器混合模式,即允許在一個程序中將一些函數使用一種存儲模式,而其它一些則按另一種存儲器模式,採用存儲器混合模式編程,可以充分利用8051系列單片機中有限的存儲器空間,同時還可以加快程序的執行速度。
3絕對地址訪問 absacc.h(相當重要)
#define CBYTE ((unsigned char volatile code *) 0)
#define DBYTE ((unsigned char volatile data *) 0)
#define PBYTE ((unsigned char volatile pdata *) 0)
#define XBYTE ((unsigned char volatile xdata *) 0)
功能:CBYTE 定址 CODE區
DBYTE 定址 DATA區
PBYTE 定址 XDATA(低256)區
XBYTE 定址 XDATA區
例: 如下指令在對外部存儲器區域訪問地址0x1000
xvar=XBYTE[0x1000];
XBYTE[0x1000]=20;
#define CWORD ((unsigned int volatile code *) 0)
#define DWORD ((unsigned int volatile data *) 0)
#define PWORD ((unsigned int volatile pdata *) 0)
#define XWORD ((unsigned int volatile xdata *) 0)
功能:與前面的一個宏相似,只是它們指定的數據類型為unsigned int .。
通過靈活運用不同的數據類型,所有的8051地址空間都是可以進行訪問。
如
DWORD[0x0004]=0x12F8;
即內部數據存儲器中(0x08)=0x12; (0x09)=0xF8
註:用以上八個函數,可以完成對單片機內部任意ROM和RAM進行訪問,非常方便。還有一種方法,那就是用指鍾,後面會對C51的指針有詳細的介紹。
4寄存器變數(register)
為了提高程序的執行效率,C語言允許將一些頻率最高的那些變數,定義為能夠直接使用硬體寄存器的所謂的寄存器變數。定義一個變數時,在變數類型名前冠以「register」 即將該變數定義成為了寄存器變數。寄存器變數可以認為是一自動變數的一種。有效作用范圍也自動變數相同。由於計算機寄存器中寄存器是有限的。不能將所有變數都定義成為寄存器變數,通常在程序中定義寄存器變數時,只是給編譯器一個建議,該變數是否真正成為寄存器變數,要由編譯器根據實際情況來確定。另一方面,C51編譯器能夠識別程序中使用頻率最高的變數,在可能的情況下,即使程序中並未將該變數定義為寄存器變數,編譯器也會自動將其作為寄存器變數處理。被定義的變數是否真正能成為寄存器變數,最終是由編譯器決定的。
5內存訪問雜談
1指鍾
指鍾本身是一個變數,其中存放的內容是變數的地址,也即特定的數據。8051的地址是16位的,所以指針變數本身佔用兩個存儲單元。指針的說明與變數的說明類似,僅在指針名前加上「*」即可。
如 int *int_point; 聲明一個整型指針
char *char_point; 聲明一個字元型指針
利用指針可以間接存取變數。實現這一點要用到兩個特殊運算符
& 取變數地址
* 取指針指向單元的數據
示例一:
int a,b;
int *int_point; //定義一個指向整型變數的指針
a=15;
int_point=&a; //int_point指向 a
*int_point=5; //給int_point指向的變數a 賦值5 等同於a=5;
示例二:
char i,table[6],*char_point;
char_point=table;
for(i=0;i<6;i++)
{
char_point=i;
char_point++;
}
註:
指針可以進行運算,它可以與整數進行加減運算(移動指針)。但要注意,移動指針後,其地址的增減量是隨指針類型而異的,如,浮點指針進行自增後,其內部將在原有的基礎上加4,而字元指針當進生自增的時候,其內容將加1。原因是浮點數,佔4個內存單元,而字元佔一個位元組。
宏晶科技最新一代STC12C5A360S2系列,每一個單片機出廠時都有全球唯一身份證號碼(ID號),用戶可以在單片機上電後讀取內部RAM單元F1H~F7H的數值,來獲取此單片機的唯一身份證號碼。使用MOV @Ri 指令來讀取。下面介紹C51 獲取方法:
char id[7]={0};
char i;
char idata *point;
for(i=0;i<7;i++)
{
id[i]=*point;
point++;
}
(此處只是對指針做一個小的介紹,達到訪問內部任何空間的方式,後述有對指針使用的詳細介紹)
2對SFR,RAM ,ROM的直接存取
C51提供了一組可以直接對其操作的擴展函數
若源程序中,用#include包含頭文件,io51.h 後,就可以在擴展函數中使用特殊功能寄存器的地址名,以增強程序的可讀性:
注 此方法對SFR,RAM,ROM的直接存取不建議使用.因為,淡io51.h這個頭文件在KEIL中無法打開,可用指針,或是採用absacc.h頭文件,
『捌』 要運行C51單片機軟體 需要安裝什麼軟體
mcs-51是intel到51系列單片機;
c51的話,一般認定為51到c語言編寫的程序;
c51的程序,需要相應的編譯器編程成十六進制代碼,在燒寫到51系列單片機中運行;
至於編譯軟體,最廣泛的就是keil
c51了,至於操作,就是編譯下載。事先必須選擇好模擬板(你的設計電路和ICE調試器),在硬體上運行和調試程序;也可以選擇simulator使用軟體模擬的方式。
最強的軟體模擬方式就是keil+Proteus這個兩個軟體配合沒任何硬體也可以調試很多項目。keil是編寫和編譯代碼的,Proteus是畫模擬原理圖,庫里有51的模擬模塊。我有這方面到資料,你可以發郵件或消息我。[email protected]
『玖』 keil c51的編程問題
編譯器首先取用通用寄存器來進行計算,變數命名壽命周期,在最後次時候用編譯器將對這個變數排除。很多編譯器,到第4步計算結束之後就不會顯示nVar2 nVar1了,變數壽命已經結束,保存也沒用。所以在最後一次使用變數,會對這個變數的產生改變也是正常的。你若在後面再加入nVar1++;就不會有這樣的結果了。
『拾』 keil c51編譯器的問題
51的標準定址空間的確只有16位、64kB。不過藉助外部擴展的手段(Px口或分時鎖存)理論上可以訪問無限大的存儲空間。
Keil C51本身支持最大16MB的定址空間,不過單片機的管腳連接必須符合一定規定。具體可翻閱一下說明書。
