㈠ 單片機C語言編程,要使用C語言自帶的庫函數,使用哪個宏包含命令
使用#include調用庫函數。
C51語言的編譯器中包含有豐富的庫函數,使用庫函數可以大大簡化用戶程序設計的工作量,提高編程效率。每個庫函數都在相應的頭文件中給出了函數原型聲明,在使用時,必須在源程序的開始處使用預處理命令#include將有關的頭文件包含進來。
C51庫函數中類型的選擇考慮到了8051單片機的結構特性,用戶在自己的應用程序中應盡可能地使用最小的數據類型,以最大限度地發揮8051單片機的性能,同時可減少應用程序的代碼長度。
單片機c語言編程是基於C語言的單片機編程。單片機的C語言採用C51編譯器(簡稱C51)。由C51產生的目標代碼短,運行速度高,存儲空間小,符合C語言的ANSI標准,生成的代碼遵循Intel目標文件格式,而且可與A51匯編語言PL/M51語言目標代碼混合使用。51單片機支持三種高級語言,即PL/M,C和BASIC。C語言是一種通用的程序設計語言,其代碼率高,數據類型及運算符豐富,並具有良好的程序結構,適用於各種應用的程序設計,是使用較廣的單片機編程語言。
㈡ 51單片機求這個時鍾的c語言程序
以下是四位數碼管可調時帶秒閃爍的c51單片機電子鍾程序(c語言)。
/**** 本程序中,晶振為12MHz, ****/
/**** 時間控制採用定時中斷控制方式。 ****/
/**** 模式和時間調整採用查詢方式。 ****/
#include<reg52.h>
sbit P20=P2^0; //分個位控制端
sbit P21=P2^1; //分十位控制端
sbit P22=P2^2; //時個位控制端
sbit P23=P2^3; //時十位控制端
sbit led=P2^7; //second display led
sbit key0=P3^0; //模式設置
sbit key1=P3^1; //加
sbit key2=P3^2; //減
unsigned char hour,min,sec,T50ms;
unsigned char modstate; //模式狀態
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};//段碼
void init(); //初始化子程序聲明
void delay500us(unsigned char X); //延時子程序聲明
void display(); //顯示子程序聲明
void display001(); //顯示子程序聲明
void display002(); //顯示子程序聲明
void keyscan(); //按鍵識別子程序聲明
void main()
{
init();
while(1)
{
keyscan();
}
}
void init() //初始化子程序
{
TMOD=0x01;
TH0=(65536-49990)/256;
TL0=(65536-49990)%256;
ET0=1;
EA=1;
TR0=1;
}
void delay500us(unsigned char X)
{
unsigned char i,j;
for(i=X;i>0;i--)
for(j=248;j>0;j--);
}
void timer0() interrupt 1 //timer0中斷服務子程序,定時時間為50ms,本程序加了10us的時間修正量
{
TMOD=0x01;
TH0=(65536-49990)/256;
TL0=(65536-49990)%256;
T50ms++;
if(T50ms>=20)
{
T50ms=0;
sec++;
if(sec>=60)
{
sec=0;
min++;
if(min>=60)
{
min=0;
hour++;
if(hour>=24)hour=0;
}
}
}
}
void display()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour/10];
P23=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour%10];
P22=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min/10];
P21=0;
delay500us(5);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min%10];
P20=0;
delay500us(5);
if(T50ms<=10)led=0;
if(T50ms>10)led=1;
}
void display001()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour/10];
P23=0;
delay500us(10);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[hour%10];
P22=0;
delay500us(10);
}
void display002()
{
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min/10];
P21=0;
delay500us(10);
P20=1;
P21=1;
P22=1;
P23=1;
P0=table[min%10];
P20=0;
delay500us(10);
}
void keyscan() //按鍵識別鍾程序
{
while(modstate==0)
{
display();
if(key0==0)
{
display();
if(key0==0)modstate++; //這兩句加在一起為延時10ms軟體防抖設計。
while(key0==0)display001(); //等待按鍵釋放。
}
}
//****************************************************************************//
while(modstate==1)
{
display001();
if(key0==0)
{
display001();
if(key0==0)modstate++; //這兩句加在一起為延時10ms軟體防抖設計。
while(key0==0)display002(); //等待按鍵釋放。
}
if(key1==0)
{
display001();
if(key1==0)
{
hour++;
if(hour>=24)hour=0;
while(key1==0)display001();
}
}
if(key2==0)
{
display001();
if(key2==0)
{
hour--;
if(hour>=24)hour=0;
while(key2==0)display001();
}
}
}
//****************************************************************************//
while(modstate==2)
{
display002();
if(key0==0)
{
display002();
if(key0==0)modstate=0; //這兩句加在一起為延時10ms軟體防抖設計。
while(key0==0)display(); //等待按鍵釋放。
}
if(key1==0)
{
display002();
if(key1==0)
{
min++;
if(min>=60)min=0;
while(key1==0)display002();
}
}
if(key2==0)
{
display002();
if(key2==0)
{
min--;
if(min>=60)min=0;
while(key2==0)display002();
}
}
}
}
㈢ 很簡的51單片機C語言流水燈程序
#include<reg52.h>
#include <intrins.h>
#define LED P2
void delay(char i);
void main()
{ unsigned char LedVablue=0xFE;
while(1)
{
LedVablue= _crol_(LedVablue,1); //_crol_(x,Y)是<intrins.h>
//裡面的一個庫函數,相當於匯編版的帶進位循環權
LED=LedVablue;
delay(100);
}
}
void delay(char i)
{
char j;
for(;i>0;i--)
for(j=0;j<250;j++);
}
㈣ 51單片機顯示八位數碼管的C語言程序
1、最開始,我們先打開keil。
㈤ 求51單片機的c語言程序
#include<stc89.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,
0x00};
uchar led[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0x00,0xFF};
sbit adrd=P3^7;
sbit adwr=P3^6;
sbit la=P2^6;
sbit wela=P2^7;
uchar date1=0;
uchar date2=50;
uchar date3=100;
uchar date4=150;
uchar date5=200;
uchar date6=255;
uchar a,sz;
void init();
void delay(uint z);
uchar adchushihua();
void shumaguan(uint shu);
void processing();
void main()
{
init();
while(1)
{
sz=adchushihua();
for(a=10;a>0;a--)
{
shumaguan(sz);
processing();
}
}
}
void init()
{
P0=0x7f;
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
uchar adchushihua()
{
uchar shu;
adwr=1;
_nop_();
adwr=0;
_nop_();
adwr=1;
P1=0xff;
adrd=1;
_nop_();
adrd=0;
_nop_();
shu=P1;
adrd=1;
return shu;
}
void shumaguan(uint shu)
{
uchar ,shi,ge;
=shu/100;
shi=shu%100/10;
ge=shu%10;
la=1;
P0=table[];
la=0;
P0=0xff;
wela=1;
P0=0x7e;
wela=0;
delay(5);
la=1;
P0=table[shi];
la=0;
P0=0xff;
wela=1;
P0=0x7d;
wela=0;
delay(5);
la=1;
P0=table[ge];
la=0;
P0=0xff;
wela=1;
P0=0x7b;
wela=0;
delay(5);
}
void processing()
{
if((sz>=date1)&&(sz<=date2))
{
P1=0xfe;
}
else if((sz>=date2)&&(sz<=date3))
{
P1=0xfd;
}
else if((sz>=date3)&&(sz<=date4))
{
P1=0xfb;
}
else if((sz>=date4)&&(sz<=date5))
{
P1=0xf7;
}
else if((sz>=date5)&&(sz<date6))
{
P1=0xef;
}
else if(sz==date6)
{
P1=~P1;
delay(20);
}
}
這個是我剛剛寫的 根據你的需要 反正閑來無事 我寫的比較籠統 需要你自己根據 自己的實際情況來判斷確定 我只是利用AD簡單的處理 成數碼管顯示的數字 你要是 轉換成電壓 那就把裡面的變數 修改一下 我寫的那個控制LED燈亮就不要動了 只是修改一下他前面定義的數字就可以 最後那個是我自己加上去的有點趣味性 希望對你有幫助
㈥ 一個51單片機C程序,裡面有一個bin的文件,這個bin文件應該包含了幾個重要的函數;能用什麼打開!
這個一般是打不開的,打開就等於是盜用人家的代碼。
lib文件
意義:
lib有靜態lib和動態lib之分。
使用:
lib文件通過編譯才可以使用,編譯分靜態與動態之分。
靜態:
靜態lib將導出聲明和實現都放在lib中。編譯後所有代碼都嵌入到宿主程序
動態:
動態lib相當於一個h文件,是對實現部分(.dll文件)的導出部分的聲明。編譯後只是將導出聲明部分編譯到宿主程序中,運行時候需要相應的dll文件支持
詳細說明:
lib文件是不對外公開的,不能查看一個編譯過後的文件
有幾個選擇:
1。如果你查看有同名的dll文件,可以通過vc自帶的depends查看dll介面
2。通過msdn看你使用的該lib包含的函數名,來查找其對應的頭文件,頭文件裡面有整個lib的函數聲明(可能不全)
3。查看vc或者其他工具安裝目錄下的src目錄,查看函數的代碼
lib文件是二進制文件,所以要查看它的內容,只能反匯編。
用編程語言,打開lib文件的辦法有三個:
1、在object/library moles使用全路徑名;
2、把*.lib放在VC的Lib目錄中
3、修改project setting的Link->Input中的Addtional library path,加入你的目錄。
LIB文件是庫文件(與DLL文件相類似),供其它程序調用的,直接打不開。
內容
一個lib文件是obj文件的集合。當然,其中還夾雜著其他一些輔助信息,目的是為了讓編譯器能夠准確找到對應的obj文件。我們可以通過tlib.exe(在tc2.0下的根目錄)來對lib文件進行操作,你可以把自己生成的obj文件通過tlib命令加入到一個lib文件中,也可以把lib文件內的obj文件進行刪除操作,還可以把內部的obj文件給提取出來。明白了lib文件的大致結構以及對它的具體操作,在學習C語言的過程中,就會又多了一個切入點對C語言具體實現進行研究。
使用步驟
在command下,把當前目錄設置為tlib.exe所在目錄,然後輸入tlib命令回車,此時顯示的內容就是對tlib命令的詳細解釋,語法如下:
Syntax: TLIB libname [/C] [/E] commands, listfile
libname library file pathname
commands sequence of operations to be performed (optional)
listfile file name for listing file (optional)
A command is of the form: <symbol>molename, where <symbol> is:
+ add molename to the library
- remove molename from the library
* extract molename without removing it
-+ or +- replace molename in library
-* or *- extract molename and remove it
/C case-sensitive library
/E create extended dictionary
具體解釋:
tlib libname [/C] [/E] commands, listfile
/C:大小寫敏感標志。該選項不常用,此參數為可選項。
/E:建立擴展字典。建立擴展字典可以加速大的庫文件的連接過程,此參數同樣為可選項。
操作命令(可選項):
+ obj文件名 把指定obj文件添加到lib文件中
- obj文件名 把指定obj文件從lib文件中刪除
* obj文件名 導出指定的obj文件(導出後對應的obj文件在lib文件內仍然存在)
-+ obj文件名 替換指定的obj文件(前提是在lib文件中存在與指定obj文件同名的obj)
-* obj文件名 導出指定的obj文件(導出後把對應的obj文件從lib文件內刪除)
lib文件中obj文件列表(可選項)
此參數說明了命令運行後,生成的對應lib文件的列表文件名。它記錄了當前lib文件內obj文件列表
與dll區別編輯
(1)lib是編譯時需要的,dll是運行時需要的。
如果要完成源代碼的編譯,有lib就夠了。
如果也使動態連接的程序運行起來,有dll就夠了。
在開發和調試階段,當然最好都有。
(2)一般的動態庫程序有lib文件和dll文件。lib文件是必須在編譯期就連接到應用程序中的,而dll文件是運行期才會被調用的。如果有dll文件,那麼對應的lib文件一般是一些索引信息,具體的實現在dll文件中。如果只有lib文件,那麼這個lib文件是靜態編譯出來的,索引和實現都在其中。靜態編譯的lib文件有好處:給用戶安裝時就不需要再掛動態庫了。但也有缺點,就是導致應用程序比較大,而且失去了動態庫的靈活性,在版本升級時,同時要發布新的應用程序才行。
(3)在動態庫的情況下,有兩個文件,一個是引入庫(.LIB)文件,一個是DLL文件,引入庫文件包含被DLL導出的函數的名稱和位置,DLL包含實際的函數和數據,應用程序使用LIB文件鏈接到所需要使用的DLL文件,庫中的函數和數據並不復制到可執行文件中,因此在應用程序的可執行文件中,存放的不是被調用的函數代碼,而是DLL中所要調用的函數的內存地址,這樣當一個或多個應用程序運行時再把程序代碼和被調用的函數代碼鏈接起來,從而節省了內存資源。從上面的說明可以看出,DLL文件必須隨應用程序一起發行,否則應用程序將會產生錯誤。
載入方法編輯
直接加入
在VC中打開File View一頁,選中工程名,單擊滑鼠右鍵,然後選中"Add Files to Project"菜單,在彈出的文件對話框中選中要加入DLL的LIB文件即可。
設置
打開工程的 Project Settings菜單,選中Link,然後在Object/library moles下的文本框中輸入DLL的LIB文件。
程序代碼
加入預編譯指令#pragma comment (lib,"*.lib"),這種方法優點是可以利用條件預編譯指令鏈接不同版本的LIB文件。因為,在Debug方式下,產生的LIB文件是Debug版本,如Regd.lib;在Release方式下,產生的LIB文件是Release版本,如Regr.lib。
當應用程序對DLL的LIB文件載入後,還需要把DLL對應的頭文件(*.h)包含到其中,在這個頭文件中給出了DLL中定義的函數原型,然後聲明。
詳解
節的概念編輯
Lib格式只有四種類型的節(Section),即First Sec,Second Sec,Longname Sec和Obj Sec;其中Second Sec與Longname Sec是可選節,很多Lib文件中都沒有。而開頭的Singature只是一個標識,它相當於COFF目標文件中的魔法數字。它是一個長度為8的字元串,值為「!<arch>\n」。
First Sec 顧名思義,就是第一個節。它包含了庫中所有的符號名以及這些符號所在的目標文件在庫中的位置(絕對偏移)。
Second Sec 就是第二節。它的內容和First Sec是相同的。不同的是,Second Sec是一個有序表,通過它來查找庫中的符號比通過First Sec來查找要快很多。
Longname Sec 是長名稱節。這一節是一個字元串表。它包含了所有長目標文件名。如果後面的Obj Sec中沒有給出相應的目標文件名,我們就要到這一節中來查找。
Obj Sec 就是目標文件節。這些節中存儲著不同的目標文件的原始數據。
在庫文件中,每一節都有兩個部分。一個部分是頭,另一個部分才是該節的數據;數據緊跟在頭的後面。頭描述了該節數據的類型、長度等信息。這些頭的格式都是相同的。其結構用C語言描述如下:
typedef struct {
char Name[16]; // 名稱
char Time[12]; // 時間
char UserID[6]; // 用戶ID
char GroupID[6]; // 組ID
char Mode[8]; // 模式
char Size[10]; // 長度
char EndOfHeader[2];// 結束符
} SectionHeader;
可以看到,頭中的數據全都是字元串。用字元串的好處是可以提高格式的兼容性,因為在不同的機器上,數據的排列方式是不同的。有的機器是以Little-Endian方式工作,還有的是以Big-Endian方式工作,它們互不兼容(這兩種方式的區別!?請看我的《COFF格式》一文,其中的文件頭一節有說明)。用字元串就不會有這種問題(後面我們將會遇到)。但它也有不方便的地方,就是必須把字元串轉換成數值,多了一個步驟。
在這個結構中,最常用的Name、Size以及EndOfHeader三個成員。Name就是節的名稱啦!Size也很好理解,就是該節數據的長度。其內容為「`\n」(注意,這里沒有打錯,是兩個字元「`」和「\n」)。怎麼樣?有點奇怪吧?為什麼要有這個結束符?每一節的頭長度一定,每節中的數據長度也知道。按順序向下讀不行嗎?答案是:不行!因為每一節之間存在間隙!通常是一個位元組或零個位元組。如果是零個位元組倒好,按順序向下讀是OK的。可是如果不為零的話,這樣讀就要錯位了。要知道錯位沒有,只好用一個結束符來定位了。如果在讀頭的時候發現結束符不對,那就要一個位元組一個位元組地向下查找,直到找到結束符,才能算是對齊了。切記!切記!
當然,通過First Sec或Second Sec中給出的偏移來讀數據就不存在這個問題。不會發生錯位,放心讀吧!
First Sec
第一節,通常就是Lib中的每一個小節。它的名稱是「/」。其數據部分的結構如下:
typedef struct {
unsigned long SymbolNum; // 庫中符號的數量
unsigned long SymbolOffset[n]; // 符號所在目標節的偏移
char StrTable[m]; // 符號名稱字元串表
}FirstSec;
第一個成員SymbolNum是符號的數量。注意!它是以Big-Endian方式儲存的(x86平台上的數據是以Little-Endian方式儲存的。這里應該注意轉換。後面給出的convert函數可以在Little-Endian格式與Big-Endian格式之間進行相互轉換)。
第二個成員SymbolOffset是一個數組,它的長度n就是符號的數量,也就是SymbolNum。這個數組儲存了每一個符號所在的目標節的偏移。我們可以方便地通過它來查找符號所在的目標文件。注意!它也是以Big-Endian格式儲存的。
第三個成員StrTable是一個字元串表,它的長度m就是SectionHeader.Size的值減去(SymbolNum+1)*4。其結構很簡單,就是一堆以『\0』結尾的字元串(和COFF文件中的字元串表結構相同)。在有的系統中,它還可能是以「/\n」這兩個字元結尾的字元串的集合。
很簡單的一個結構,不過有兩個成員的長度是不定的。怎麼才能方便地從Lib中讀出這些數據,留給大家自己想吧!下面我只給出一個進行Little-Endian與Big-Endian互轉的函數。
inline void convert(void * p // 要轉換的數據的指針
,size_tsize = 4 // 數據的長度,long為4,short為2
) {
char * buf=(char*)p;
char temp;
for ( size_t i=0;i<size/2;i++ ) {
temp=buf[i];
buf[i]=buf[size-i-1];
buf[size-i-1]=temp;
}
}
Second Sec
第二節
這一節與第一節很相似!它通常也就是Lib文件的第二個節。它的名字也是「/」(注意:文件中第一個叫「/」的節是第一節,第二個就是第二節)。不過它的結構與第一節有些不同,如下:
typedef struct {
unsigned long ObjNum; // Obj Sec的數量
unsigned long ObjOffset[x]; // 每一個Obj Sec的偏移
unsigned long SymbolNum; // 庫中符號的數量
unsigned short SymbolIdx[n]; // 符號在ObjOffset表中的索引
char StrTable[m]; // 符號名稱字元串表
}SecondSec;
第一個成員ObjNum是庫中Obj Sec的數量。
第二個成員ObjOffset是一個偏移表,它記錄了庫中所有Obj Sec的偏移。這個表的記錄數x就是ObjNum。
第三個成員SymbolNum與First Sec中的SymbolNum意義相同。
第四個成員SymbolIdx變成了一個索引,它記錄了相應名稱字元串在ObjOffset這個表中的位置,我們要通過兩次索引才能找到我們所要符號的Obj Sec位置。它的項目數n為SymbolNum。但請注意,這個索引是unsigned short型,不再是unsigned long型。
第五個成員StrTable結構與First Sec中的一樣。不過,它的長度m為SectionHeader.Size的值減去((ObjNum+1)*4+(SymbolNum+2)*2)。
值得注意的是,這里的所有數據都是Little-Endian格式的。千萬不要弄錯了!Longname Sec
這個小節就是一個字元串表,它的名稱為「//」,其結構同FirstSec.StrTable。這里就不多說了。
Obj Sec
這一節中的數據就是COFF文件的原始數據,把它讀出來存成文件,就是一個COFF文件。它的格式請參考《COFF格式》一文。
要指出的是它的命名方式有些特殊。如果Obj文件的名稱少於16個字元,它就會被保存在SectionHeader的Name成員中,以『/』字元結尾。如果無法保存在Name成員中,則Name成員的第一個字元就為『/』,之後再跟上這個名稱在Longname Sec中的偏移。
例如:
!<arch>\n
……
LongName Sec:
This_Is_Long_Name0001\0
This_Is_Long_Name0002\0
……
Obj Sec1:
Name[16]:「shortname/」
……
Obj Sec2:
Name[16]:「/0」 // 這里使用了第一個長文件名This_Is_Long_Name0001
……
Obj Sec3:
Name[16]:「/22」 // 這里使用了第二個長文件名This_Is_Long_Name0002