㈠ C51語言的混合編程
C51編譯器能對C語言源程序進行高效率的編譯,生成高效簡潔的代碼,在絕大多數場合採用C語言編程即可完成預期的目的。但有時為了編程直觀或某些特殊地址的處理,還須採用一定的匯編語言編程。而在另一些場合,出於某種目的,匯編語言也可調用C語言。在這種混合編程中,關鍵是參數的傳遞和函數的返回值。它們必須有完整的約定,否則數據的交換就可能出錯,例 C語言程序與匯編語言程序的調用,其子程序如下:
PUBLIC AD ;入口地址
SEG_AD SEGMENT CODE;程序段
RSEG SEG_AD
USING 0
AD: MOV R6,#00
MOV R7,#00
SETB P1.1
ACALL DELAY
CLR P1.1
ACALL DELAY
MOV R0,#10
RR0: SETB P1.2
NOP
CLR P1.2
DJNZ R0,RR0
ACALL DELAY
MOV 30H,R6 ;A/D轉換的高
;兩位保存在R6中
ACALL CIR
MOV R6,30H
SETB P1.2
NOP
CLR P1.2
MOV 30H,R6
ACALL CIR
MOV R6,30H
MOV R0,#8 ;A/D轉換的低
;8位保存在R7中
RR2: SETB P1.2
NOP
CLR P1.2
MOV 30H,R7
ACALL CIR
MOV R7,30H
DJNZ R0,RR2
RET
CIR: CLR C
MOV C,P1.0
MOV A,30H
RLC A
MOV 30H,A
RET
END
在以上程序中,函數的返回值為一無符號整型數,根據調用規則,返回值的高位必須在R6中,低位在R7中,這樣才可保證數據的傳遞不出錯。另外,在調用過程中,必須注意寄存器的入棧。這樣在以後用到A/D轉換時,在C語言中調用匯編語言子程序AD()即可。
㈡ C51編程時,可以使用標准C語言的所有數據類型。為什麼「編程時常用unsigned c
這體現了嵌農和碼農的價值觀區別。
嵌農會精心計算一個變數的范圍,而碼農很少這么做,因為碼農默認的數值類型一般是int32,可以滿足日常范圍需求,甚至像Python那樣的語言自帶大整數特性,根本不用考慮范圍。然而嵌農呢,尤其是你說的c51,是個Intel祖傳8位機,本來ram就很少,當然要精心考慮變數的大小了。像int32這樣的東西太奢侈了,只能精打細算,根據現實情況精選一個范圍合適的類型。鑒於大部分情況並不需要負數,所以用unsigned類型能提高0以上的數值范圍。另外需要指出的是很多c51編譯器里int類型是16位的。所以嵌農的悲傷就在這里,別人已經開始寫演算法了,你還在研究這個變數存不存得下的問題。
C51語言,由C語言繼承而來的單片機編程語言。
和C語言不同的是,C51語言運行於單片機平台,而C語言則運行於普通的桌面平台。C51語言具有C語言結構清晰的優點,便於學習,同時具有匯編語言的硬體操作能力。對於具有C語言編程基礎的讀者,能夠輕松地掌握單片機C51語言的程序設計。
㈢ C51單片機能做什麼樣的系統
主要用於邏輯控制方面的
比如日常的洗衣機,電磁爐這些,也可以做個小的MP3,MP4播放器啊,不過這不是單片機的專長。
工業上用的各種測量設備,都可以用單片機完成。當然,比較強悍的單片機,可以嵌入一個小的操作系統,那就是一台真正的電腦了。
㈣ c語言51單片機
沒有問題,只要IDE模塊裡面支持你的型號即可。編譯器可以將C51編譯生成對應的匯編代碼。
㈤ gcc編譯器和嵌入式keil的C51編譯器有什麼不
前者是通用的C語言編譯器,後者相當於是個定製版。C51中定義了一些原先C語言中沒有的類型以及寄存器定義、同時鑒於單片機通常只有幾KB的內存空間進行了代碼生成量優化,專門用於單片機的開發,這些都是在GCC這樣標準的ANSI C編譯器中所沒有的。
㈥ keil c51軟體的作用是什麼
編譯程序,是單片機C語言的主要編譯工具
㈦ C51編譯器的全部作用
後面也少了兩個}
i的作用范圍是在整個main函數裡面,
K是在定義處到main的最後,
static int j 是靜態類型,也是在整個main函數里,只是跳出函數後值不變
另外,虛機團上產品團購,超級便宜
㈧ keil c51的所有頭文件,其作用。
我來回答你的問題吧,前幾天對這個方面有一定的深入了解,也寫下了大量的筆記
雖然C編程的時候,對於不同的晶元,有不同的頭文件,但是,萬變不離其宗。
只要學會了寫自己的頭文件,就可以應付各類型號單片機了,就算你用的是AT89C2052,還是AT89C51,STC12C等等,都可以用一個頭文件reg51.h 不過要做相應的修。
以下是我對reg51.h個人的見解:(對於你很有用的) 後面帶上了在編寫C51時帶用的頭文件,及其內部函數和宏定義的詳細解說。
想了解如下方面的知識來來郵[email protected]
一, C51內存結構深度剖析
二, reg51.頭文件剖析
三, 淺淡變數類型及其作用域
四, C51常用頭文件
五, 淺談中斷
六, C51編譯器的限制
七, 小淡C51指針
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
reg51.頭文件剖析
我們平時寫單片機應用程序的時候,所使用的頭文件大多都是用的的reg51.h或是用reg52.h。會寫C51的人都會用,但對其頭文件內部的定義有所了解的人確並不多。
下面對其內部做詳細解釋,方便讀者作進一步的了解,並能運用各類型號的單片機。因為增強型號的單片機的增強功能都是通過特殊功能寄存器控制。
打開 reg52.h 頭文件,會發現是由大量的 sfr ,sbit的聲明組成,甚至於還有sfr16.其實這樣的聲明都是與單片機內部功能寄存器(特殊功能寄存器)聯系起來的,下面對其做出詳細解釋
sfr: 聲明變數
SFR 聲明一個變數,它的聲明與其它的C變數聲明基本相同,唯一的區別,SFR在聲明的同時為其指定特殊功能寄存器作為存儲地址,而不同於C變數聲明的整型,字元型等等由編譯器自動分配存儲空間。
如reg52.h頭文件,第一條聲明就是sfr P0 = 0x80;
此處聲明一個變數P0,並指定其存儲地址為特殊功能寄存器0x80;,在加入reg52.h頭文件後。編寫應用程序時P0就可以直接使用而無需定義,對P0的操作就是,對內部特殊功能寄存器(0x80對應用MCU的P0口)的操作,可進行讀寫操作。
如果將第一條聲明改為sfr K0 = 0x80; 那麼,如果要把單片機的P0口全部拉低,則不能寫P0=0x00;而應保存後再在應用程序中寫成K0=0x00;否則編譯器會提示「P0為未定義標識符」
使用方法:
sfr [variable] = [address] //為變數分配一個特殊功能寄存器。
1 等號右邊,只能是十進制,十六進制整型的數據常量,,不允許帶操作符的表達式
經典的8051內核支持的SFR地址從0x80H~0xFF 飛利浦80C51MX系列0x180H~0x1FF
2 SFR不能聲明於任何函數內部,包括main函數。只能聲明於函數外。
3 用SFR聲明一個變數後,不能用取地址運算符&獲取其地址, 編譯無法通過,編譯器會提示非法操作。
4 有一點須特別注意,51內核0x80~0xff,為特殊功能寄存器地址區間,但並不是所有的地址都有定義,如果說你所用的MCU晶元上對於某個地址沒有定義,那麼用sfr在定義變數的時候,不要把變數的地址分配到未定義的特殊功能寄存器上,雖然編譯時能通過,用KEIL模擬時貌似是沒有問題,但下載到晶元里運行時,是會出問題的。比如說,向一個未定義的特殊功能寄存器執行讀操作,讀出來的就是一個未知的數。(讀者可自行測試,先把串口通信調通,然後做一個簡單的人機交互。讀出一個數後,再發給計算機,用串口調試助手或是串口監控查看。這用方法在模擬的時候很有用。)所以具體那些特殊功能寄存器能夠用,就要查看你使用的晶元手冊。
5 若遇到增強性的單片機,只要知道其擴展的特殊功能寄存器的地址,用SFR定
就可以很方便進行編程。
sbit: 聲明變數
sbit 同樣是聲明一個變數,和SFR 使用方法類似,但是SBIT是用來聲明一個位變數,因為,在51系列的應用中,非常有必要對SFR的單個位進行存取,而通過bit 數據類型,使其具備位定址功能。
如,在reg52.h中有如下聲明
sfr IE = 0xA8;
sbit EA = IE^7;
sbit ET2 = IE^5; //8052 only
sbit ES = IE^4;
sbit ET1 = IE^3;
sbit EX1 = IE^2;
sbit ET0 = IE^1;
sbit EX0 = IE^0;
所以,對EA的操作即是對IE最高位的操作。
但如果想讓 SP DPL DPH PCON TMOC TL0 TL1 TH0 TH1 SBUF這些特殊功能寄存器具備位定址,採用上述如IE類似的定義,是不行的,雖然修改後,在編譯的時候不會出現錯誤,但只要用到你定義的位變數名時就會出錯。原因是,只有特殊功能寄存器的地址是8的倍數(十六進制以0或8結尾)才能進行位定址。
打開reg52.h頭文件可以看到,所有用sbit聲明了的特殊功能寄存器的地址均是以0或8結尾
如硬要達到上述要求,可用帶參的宏定義來完成。此處不做詳細說明(意義並不大)。
下面對sbit的使用做詳細介紹:
隨著8051的應用,非常有必要對特殊功能寄存器的單個bit位進行存取,C51編譯器通過sbit 數據類型,提供了對特殊功能寄存器的位操作。
以下是sbit的三種應用形式:
一, sbit name = sfr-name^bit-position;
sfr PSW =0xD0;
sfr IE =0xA8;
sbit OV= PSW^2;
sbit CY=PSW^7;
sbit EA= IE^7;
二, sbit name= sft-address^bit-position;
sbit OV =0xD0^2;
sbit CY =0xD0^7;
sbit EA =0xA8^7;
三, sbit name= sbit-address;
sbit OV =0xD2;
sbit CY =0xD7;
sbit EA =0xAF;
現對上述三種形式的聲明做必要的說明
第一種形式sbit name = sfr-name^bit-position;如sbit OV= PSW^2; 當中的這個特殊功能寄存器必須在此之前已經用sfr 定義,否則編譯會出錯。
bit-position范圍從0~7;
第二種形式 sbit name= sft-address^bit-position如sbit OV =0xD0^2; 與第一種形式不同之外在於,此處直接使用PSW的地址.第一種形式須先定義PSW
第三種形式. sbit name= sbit-address 如sbit OV =0xD2 是直接用的OV的地址
OV的地址計算方式,是OV所在的寄存器地址加上OV的bit-position
注意:
不是所有的SFR都可位定址。只有特殊功能寄存器的地址是8的倍數(十六進制以0或8結尾)才能進行位定址,並且sbit聲明的變數名,雖可以是任意取,但是最好不要以下劃線開頭,因為以下劃線開頭的都保留給了C51的頭文件做保留字。
sfr16: 聲明變數
許多8051的派生型單片機,用兩個連續地址的特殊功能寄存器,來存儲一個16bit的值。例如,8052就用了0xCC和0xCD來保存定時/計數寄存器2的高位元組和低位元組。編譯器提供sfr16這種數據類型,來保存兩個位元組的數據。虛擬出一個16bit的寄存器。
如下:
sfr16 T2 = 0xCC
存儲方面為小端存儲方式,低位元組在前,高位元組在後。定義時,只寫低位元組地址,如上,則定義T2為一個16位的特殊功能寄存器。 T2L= 0CCh, T2H= 0CDh
使用方法:
sfr [variable] = [low_address]
1 等號右邊,只寫兩個特殊功能寄存器的低地址,且只能是十進制,十六進制的整型數據常量,不允許帶操作符的表達式
2 SFR不能聲明於任何函數內部,包括main函數。只能聲明於函數外。
3 用SFR聲明一個變數後,不能用取地址運算符&獲取其地址, 編譯無法通過,編譯器會提示非法操作。
4 當你向一個sfr16寫入數據的時候,KEIL CX51 編譯器生成的代碼,是先寫高位元組,後寫低位元組,(可通過返匯編窗口查看)在有些情況下,這並非我們所想要的操作順序。使用時,須注意。
5 當你所要寫入sfr16的數據,當是高位元組先寫還是低位元組先寫非常重要的時候,就只能用sfr 這個關鍵字來定義,並且任意時刻只保存一個位元組,這樣操作才能保證寫入正確。
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
C51常用頭文件
在KEIL 中,對於單片機所使用的頭文件,除了reg51 reg52以外,還有一些從各晶元制商的官網下載與reg51,reg52功能類似的頭文件,需了解透外,還要對各類型單片機均可通用且相當有用的的頭文件,做相應的了解。因為,內部所包含的函數與宏定義,可以及大的方便我們編寫應用程序。
1字元函數 ctype.h
1 extern bit isalpha(char);
功能:檢查參數字元是否為英文字母,是則返回1
2 extern bit isalnum(char)
功能:檢查字元是否為英文字母或數字字元,是則返回1
3 extern bit iscntrl(char)
功能:檢查參數值是否在0x00~0x1f 之間或等於0x7f,是則返回1
4 extern bit isdigit(char)
功能: 檢查參數是否為數字字元,是則返回1
5 extern bit isgraph(char)
功能: 檢查參數值是否為可列印字元,是則返回1,可列印字元為0x21~0x7e
6 extern bit isprint(char)
功能:除了與isgraph相同之外,還接受空格符0x20
7 extern bit ispunct(char)
功能:不做介紹。
8 extern bit islower(char)
功能:檢查參數字元的值是否為小寫英文字母,是則返回1
9 extern bit isupper(char)
功能:檢查參數字元的值是否為大寫英文字母,是則返回1
10 extern bit isspace(char)
功能:檢查字元是否為下列之一,空格,製表符,回車,換行,垂直製表符和送紙。如果為真則返回1
11 extern bit isxdigit(char)
功能:檢查參數字元是否為16進制數字字元,是則返回1
12 extern char toint(char)
功能:將ASCII字元0~9 a~f(大小寫無關)轉換成對應的16進制數字,
返回值00H~0FH
13 extern char tolower(char)
功能:將大寫字元轉換成小寫形式,如字元變數不在A~Z之間,則不作轉換而直接返回該字元
14 extern char toupper(char)
功能:將小寫字元轉換成大寫形式,如字元變數不在a~z之間,則不作轉換而直接返回該字元
15 define toascii(c) ((c)&0x7f)
功能:該宏將任何整形數值縮小到有效的ASCII范圍之內,它將變數和0x7f相與從而去掉第7位以上的所有數位
16 #define tolower(c) (c-『A』+』a』)
功能:該宏將字元與常數0x20 逐位相或
17 #define toupper(c) ((c)-『a』+』A』)
功能:該宏將字元與常數0xdf 逐位相與
2數學函數 math.h
extern int abs (int val);
extern char cabs (char val);
extern long labs (long val);
extern float fabs (float val);
功能:返回絕對值。上面四個函數,除了形參和返回值不一樣之外,
其它功能完全相同。
extern float exp (float val);
extern float log (float val);
extern float log10 (float val);
功能: exp 返回eval
log 返回 val 的自然對數
log10 返回 以10為底,val的對數
extern float sqrt (float val);
功能: 返回val的正平方根
extern int rand();
extern void srand(int n);
功能: rand返回一個0到32767之間的偽隨機數,srand用來將隨機數發生器初始化成一個已知的(期望)值。
Keil uVision3中的math.h庫中,不包含此函數。
extern float sin (float val);
extern float cos (float val);
extern float tan (float val);
功能: 返回val的正弦,餘弦,正切值。val為弧度 fabs(var) <=65535
extern float asin (float val);
extern float acos (float val);
extern float atan (float val);
extern float atan2 (float y, float x);
功能: asin 返回val的反正弦值。acos 返回val的反餘弦值。
atan 返回val的反正切值。
asin atan acos的值域均為 -π/2~+π/2
atan2返回x/y,的反正切值,其值域為-π~+π
extern float sinh (float val);
extern float cosh (float val);
extern float tanh (float val);
功能:cosh返回var的雙曲餘弦值,sinh返回var的雙曲正弦值,
tanh返回var的雙曲正切值。
extern float ceil (float val);
功能: 向上取整,返回一個大於val的最小整數。
extern float floor (float val);
功能: 向下取整,返回一個小於val的最大整數。
extern float pow (float x, float y);
功能: 計算計算xy的值。當(x=0,y<=0)或(x<0.y不是整數)時會發生錯誤。
extern void fpsave(struct FPBUF *p)
extern void fprestore(struct FPBUF *p)
功能:fpsave 保存浮點了程序的狀態,fprestore恢復浮點子程序的原始狀態,當中斷程序中需要執行浮點運算時,這兩個函數是很有用的。
註: Keil uVision3中的math.h庫中,不包含此函數。
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
4 內部函數 intrins.h
extern unsigned char _cror_ (unsigned char var, unsigned char n);
extern unsigned int _iror_ (unsigned int var, unsigned char n);
extern unsigned long _lror_ (unsigned long var, unsigned char n);
功能:將變數var 循環右移 n 位。
上三個函數的區別在於,參數及返回值的類型不同
extern unsigned char _crol_ (unsigned char var, unsigned char n);
extern unsigned int _irol_ (unsigned int var, unsigned char n);
extern unsigned long _lrol_ (unsigned long var, unsigned char n);
功能:將變數var 循環左移 n 位。
上三個函數的區別在於,參數及返回值的類型不同
例如:
#include<intrins.h>
void main()
{
unsigned int y;
y=0x0ff0;
y=_irol_(y,4); //y=0xff00
y=_iror_(y,4); //y=0x0ff0
}
void _nop_(void);
功能:_nop_產生一個8051單片機的NOP指令,C51編譯器在程序調用_nop_ 函數的地方,直接產生一條NOP指令。
㈨ Keil u Vision2 和keil C51 v7 什麼關系有什麼區別他們分別可以用來干什麼了求解。。
μVision是集成編譯環境。
C51是編譯器包。
形象地說μVision就是在外面跟用戶打交道的(就像一個公司的銷售人員,衣著光鮮,油頭粉面。幫助你建立工程、調試、獲取數據,端茶倒水提供服務),C51編譯器包是在家裡默默幹活創造價值的(核心之核心其實就是幾個exe文件,負責完成編譯、匯編、鏈接等核心工作。此外由各種DLL與μVision以及操作系統介面實現後台功能)。
早期的版本(例如Keil μVision2)與51編譯器包是緊密結合在一起的。如今二者已經相對比較獨立了。
㈩ C語言編譯器是用來做什麼的
1.
C語言是一種結構化語言。它層次清晰,便於按模塊化方式組織程序,易於調試和維護。
2.
C語言的表現能力和處理能力極強。它不僅具有豐富的運算符和數據類型,便於實現各類復雜的數據結構。它還可以直接訪問內存的物理地址,進行位(bit)一級的操作。由於C語言實現了對硬體的編程操作,因此C語言集高級語言和低級語言的功能於一體。既可用於系統軟體的開發,也適合於應用軟體的開發。此外,C語言還具有效率高,可移植性強等特點。因此廣泛地移植到了各類各型計算機上,從而形成了多種版本的C語言。