欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: 51單片機開發經驗總結 [打印本頁]

作者: 51hei團團    時間: 2018-7-14 21:01
標題: 51單片機開發經驗總結
                          Bit 用法
bit是C51編譯器的一種擴充數據類型,利用它可定義一個位標量,但不能定義位指針,也不能定義位數組。它的值是一個二進制位,不是0就是1,類似一些高級語言中的Boolean類型中的True和False。事實上,bit和數據類型為int,char等具有許多相同特性。

1. 值域:
以char為例。Char為8位一個字節的數據類型,取值范圍為 -128到+127。而bit只有1位,只能表示0和1兩種值。通常bit定義的變量作為一個標志位用。

2.類型定義:
   例如一個數據為25,那么它就可以定義為char型、int型等。因為他們都在自己的值域內。同樣一個在自己值域的數0和1就可以定義為bit型。Bit可以指定函數返回值的類型,如bit display(),也可對別的類型的數據進行數據強制轉換,如x=(bit)y, (y為char,int型等)。此時,x的值便為0或1。那么如何確定x是0還是1呢?現在看下面例題:
bit lcd_busy()
{      
     bitresult;
   LCD_RS = 0;
    LCD_RW= 1;
   LCD_EN = 1;
   delayNOP();
   result = (bit)(P0&0x80);
   LCD_EN = 0;
   return(result);
  }
  在上面例題中我們可以看到,bit定義了一個函數返回值類型bit lcd_busy(),一個變量 result 和 一個運算表達式 P0&0x80 .由此可以bit的用法和char、int等相同。那么resulit的值如何確定呢? 這個和運算表達式 P0&0x80有關。如果表達式 P0&0x80的運算結果為非零的值,那么resulit的值為1,否則為0。



總結:由上面等內容可以看出,我們完全可以像charint那樣使用bit。只是在使用過程要注意bit的取值范圍以及bit對運算表達式進行數據強制轉換時的規則和bit定義的變量作為標志位的特性。





        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, 建議少用。但也有他的優點,具體用法屬于中級問題,這里不提。
  
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,如果你明白它的特性。
  
bit
  
  
是在內部數據存儲空間中 20H .. 2FH 區域中一個位的地址,這在DATA的20H以后以字節形式出現,可互相參照。另外加上8051 可尋址 的SFR,但剛剛試過,只是00H--7FH起作用,也就是說當數據有變化時顏色變紅,以后的從80H到--FFH就不是位尋址區了,是位尋址的特殊寄存器,如涉及到了可位尋址的那11個當然會有反應。
  
復位后,程序計數器PC的內容為0000H,內部RAM各單元的值不確定。各功能寄存器的復位值如下:堆棧指針SP的復位值為07H,累加器ACC、寄存器B的復位值為00H,數據指針DPTR的復位值為0000H,而p0、p1、p2、p3四個口的復位值為0FFH。其他SFR如PSW、TCON、TMOD、TL0、TH0、TL1、TH1的復位值也為00H。
  
wave中是低128字節和高128字節(0-7FH),低128字節是片內RAM區,高128字節(80-FFH)是SFR(特殊功能寄存器)bit則是位于低128字節的20H  .. 2FH 區域,即data的20H .. 2FH 區域
  
  code
  
是在 0000H ..  0FFFFH 之間的一個代碼地址。
  
我用
  ORG     5000H
  TAB:    DB       22H,3BH,43H,66H,5H,6DH,88H后,
  
CODE從5000H開始以后變成DB各位
  

  data
  
  
是在 0 到 127 之間的一個數據存儲器地址,或者加 128 .. 255 范圍內的一個特殊功能寄存器(SFR)地址。兩者訪問的方式不同。實際上由于PSW的復位設置PSW.3=RS0和PSW.4=RS1皆為0,所以通用工作寄存器區就是第0區,所以data的00--07H部分是與REG欄中的R0--R7對應的。以后的則僅代表低128字節的內部RAM。
  
  
  idata
  是 0 to 255 范圍內的一個 idata 存儲器地址。
  
idata與data重合低128字節,有的地方只有DATA表示256字節的片內RAM,
  xdata
是 0 to 65535 范圍內的一個 xdata 存儲器地址。
  
指針類型和存儲區的關系詳解
  
  一、存儲類型與存儲區關系
  
       data      --->     可尋址片內ram
       bdata      --->     可位尋址的片內ram
       idata      --->     可尋址片內ram,允許訪問全部內部ram
       pdata      --->     分頁尋址片外ram (MOVX @R0)  (256 BYTE/頁)
       xdata      --->    可尋址片外ram (64k 地址范圍FFFFH)
        code     --->    程序存儲區 (64k 地址范圍),對應MOVC @DPTR
  
  二、指針類型和存儲區的關系
  
       對變量進行聲明時可以指定變量的存儲類型如:
       uchar data x和data uchar x相等價都是在內ram區分配一個字節的變量。
  
       同樣對于指針變量的聲明,因涉及到指針變量本身的存儲位置和指針所指向的存儲區位置不同而進行相應的存儲區類型關鍵字的
  使用如:
  
       uchar xdata * data pstr
  
       是指在內ram區分配一個指針變量("*"號后的data關鍵字的作用),而且這個指針本身指向xdata區("*"前xdata關鍵字的作用),
  可能初學C51時有點不好懂也不好記。沒關系,我們馬上就可以看到對應“*”前后不同的關鍵字的使用在編譯時出現什么情況。
  
       ......
       uchar xdata tmp[10];     //在外ram區開辟10個字節的內存空間,地址是外ram的0x0000-0x0009
       ......
  
       第1種情況:
  
       uchar data * data pstr;
       pstr="tmp";
  
       首先要提醒大家這樣的代碼是有bug的, 他不能通過這種方式正確的訪問到tmp空間。 為什么?我們把編譯后看到下面的匯編
  代碼:
  
       MOV  0x08,#tmp(0x00)         ;0x08是指針pstr的存儲地址
  
       看到了嗎!本來訪問外ram需要2 byte來尋址64k空間,但因為使用data關鍵字(在"*"號前的那個),所以按KeilC編譯環境來說
  就把他編譯成指向內ram的指針變量了,這也是初學C51的朋友們不理解各個存儲類型的關鍵字定義而造成的bug。特別是當工程中的
  默認的存儲區類為large時,又把tmp[10] 聲明為uchar tmp[10] 時,這樣的bug是很隱秘的不容易被發現。
  
       第2種情況:
  
       uchar xdata * data pstr;
       pstr = tmp;
  
       這種情況是沒問題的,這樣的使用方法是指在內ram分配一個指針變量("*"號后的data關鍵字的作用),而且這個指針本身指向
  xdata區("*"前xdata關鍵字的作用)。編譯后的匯編代碼如下。
  
       MOV  0x08,#tmp(0x00)         ;0x08和0x09是在內ram區分配的pstr指針變量地址空間
       MOV 0x09,#tmp(0x00)
  
       這種情況應該是在這里所有介紹各種情況中效率最高的訪問外ram的方法了,請大家記住他。
  
       第3種情況:
  
       uchar xdata * xdata pstr;
       pstr="tmp";
  
       這中情況也是對的,但效率不如第2種情況。編譯后的匯編代碼如下。
  
       MOV DPTR,  #0x000A         ;0x000A,0x000B是在外ram區分配的pstr指針變量地址空間
       MOV A, #tmp(0x00)
       MOV @DPTR, A
       INC DPTR
       MOV A, #tmp(0x00)
       MOVX @DPTR, A
  
       這種方式一般用在內ram資源相對緊張而且對效率要求不高的項目中。
  
       第4種情況:
  
       uchar data * xdata pstr;
       pstr="tmp";
  
       如果詳細看了第1種情況的讀者發現這種寫法和第1種很相似,是的,同第1 種情況一樣這樣也是有bug的,但是這次是把pstr分
  配到了外ram區了。編譯后的匯編代碼如下。
  
       MOV DPTR,  #0x000A         ;0x000A是在外ram區分配的pstr指針變量的地址空間
       MOV A, #tmp(0x00)
       MOVX @DPTR, A
  
       第5種情況:
  
       uchar * data pstr;
       pstr="tmp";
  
       大家注意到"*"前的關鍵字聲明沒有了,是的這樣會發生什么事呢?下面這么寫呢!對了用齊豫的一首老歌名來說就是 “請跟我
  來”,請跟我來看看編譯后的匯編代碼,有人問這不是在講C51嗎?  為什么還要給我們看匯編代碼。C51要想用好就要盡可能提升C51
  編譯后的效率,看看編譯后的匯編會幫助大家盡快成為生產高效C51代碼的高手的。還是看代碼吧!
  
       MOV 0x08,  #0X01              ;0x08-0x0A是在內ram區分配的pstr指針變量的地址空間
       MOV 0x09, #tmp(0x00)
       MOV 0x0A, #tmp(0x00)
  
       注意:這是新介紹給大家的,大家會疑問為什么在前面的幾種情況的pstr指針變量都用2 byte空間而到這里就用3 byte空間了
  呢?這是KeilC的一個系統內部處理,在KeilC中一個指針變量最多占用 3 byte空間,對于沒有聲明指針指向存儲空間類型的指針,
  系統編譯代碼時都強制加載一個字節的指針類型分辯值。具體的對應關系可以參考KeilC的help中C51 User's Guide。
  
       第6種情況:
  
       uchar * pstr;
       pstr="tmp";
  
       這是最直接最簡單的指針變量聲明,但他的效率也最低。還是那句話,大家一起說好嗎!編譯后的匯編代碼如下。
  
       MOV DPTR,  #0x000A         ;0x000A-0x000C是在外ram區分配的pstr指針變量地址空間
       MOV A, #0x01
       MOV @DPTR, A
       INC DPTR
       MOV DPTR, #0x000A
       MOV A, #tmp(0x00)
       MOV @DPTR, A
       INC DPTR
       MOV A, #tmp(0x00)
       MOVX @DPTR, A
  
       這種情況很類似第5種和第3種情況的組合,既把pstr分配在外ram空間了又增加了指針類型的分辨值。
  







1 電感在電路中的作用
電感在電路中的作用
基本作用:濾波、振蕩、延遲、陷波等

形象說法:“通直流,阻交流
通直流:所謂通直流就是指在直流電路中,電感的作用就相當于一根導線,不起任何作用。
阻交流:在交流電路中,電感會有阻抗,即XL,整個電路的電流會變小,對交流有一定的阻礙作用。
細化解說:在電子線路中,電感線圈對交流有限流作用,它與電阻器或電容器能組成高通或低通濾波器、移相電路及諧振電路等;

電感的作用是阻礙電流的變化,但是這種作用與電阻阻礙電流流通作用是有區別的。
電阻阻礙電流流通作用是以消耗電能為其標志,而電感阻礙電流的變化則純粹是不讓電流變化,當電流增加時電感阻礙電流的增加,當電流減小時電感阻礙電流的減小。電感阻礙電流變化過程并不消耗電能,阻礙電流增加時它將電的能量以磁場的形式暫時儲存起來,等到電流減小時它也將磁場的能量釋放出來,以結果來說,就是阻礙電流的變化。


2三極管在電路中的作用
在設計一些線路時。需用到npn/pnp。在哪種時候用呢?下面來介紹一下。
1.如果輸入一個高電平,而輸出需要一個低電平時,首選擇npn。
2.如果輸入一個低電平,而輸出需要一個低電平時,首選擇pnp。
3.如果輸入一個低電平,而輸出需要一個高電平時,首選擇npn。
4.如果輸入一個高電平,而輸出需要一個高電平時,首選擇pnp。
npn基極高電壓,極電極與發射極短路,如果基極加低電壓,極電極與發射極開路.也就是不工作。
pnp基極高電壓.極電極與發射極開路,也就是不工作。如果基極加低電位,集電極與發射極短路。
即工作與不工作



                  電容在電路中的作用
熟悉電容器在不同電路中的名稱意義,有助于我們讀懂電子電路圖。
電容器在電子電路中幾乎是不可缺少的儲能元件,它具有隔斷直流、連通交流、阻止低頻的特性。廣泛應用在耦合、隔直、旁路、濾波、調諧、能量轉換和自動控制等電路中。
1.濾波電容 它接在直流電源的正、負極之間,以濾除直流電源中不需要的交流成分,使直流電平滑。一般常采用大容量的電解電容器,也可以在電路中同時并接其他類型的小容量電容以濾除高頻交流電。

2.退耦電容 并接于放大電路的電源正、負極之間,防止由電源內阻形成的正反饋而引起的寄生振蕩。

3.旁路電容 在交、直流信號的電路中,將電容并接在電阻兩端或由電路的某點跨接到公共電位上,為交流信號或脈沖信號設置一條通路,避免交流信號成分因通過電阻產生壓降衰減。

4.耦合電容 在交流信號處理電路中,用于連接信號源和信號處理電路或者作兩放大器的級間連接,用以隔斷直流,讓交流信號或脈沖信號通過,使前后級放大電路的直流工作點互不影響。

5.調諧電容 連接在諧振電路的振蕩線圈兩端,起到選擇振蕩頻率的作用。

電解電容在電路中的作用
  
電解電容在電路中的作用
  
  1,濾波作用,在電源電路中,整流電路將交流變成脈動的直流,而在整流電路之后接入一個較大容量的電解電容,利用其充放電特性,使整流后的脈動直流電壓變成相對比較穩定的直流電壓。在實際中,為了防止電路各部分供電電壓因負載變化而產生變化,所以在電源的輸出端及負載的電源輸入端一般接有數十至數百微法的電解電容.由于大容量的電解電容一般具有一定的電感,對高頻及脈沖干擾信號不能有效地濾除,故在其兩端并聯了一只容量為0.001--0.lpF的電容,以濾除高頻及脈沖干擾.
  2,耦合作用:在低頻信號的傳遞與放大過程中,為防止前后兩級電路的靜態工作點相互影響,常采用電容藕合.為了防止信號中韻低頻分量損失過大,一般總采用容量較大的電解電容。
  
二、電解電容的判斷方法
  
電解電容常見的故障有,容量減少,容量消失、擊穿短路及漏電,其中容量變化是因電解電容在使用或放置過程中其內部的電解液逐漸干涸引起,而擊穿與漏電一般為所加的電壓過高或本身質量不佳引起。判斷電源電容的好壞一般采用萬用表的電阻檔進行測量.具體方法為:將電容兩管腳短路進行放電,用萬用表的黑表筆接電解電容的正極。紅表筆接負極(對指針式萬用表,用數字式萬用表測量時表筆互調),正常時表
  
針應先向電阻小的方向擺動,然后逐漸返回直至無窮大處。表針的擺動幅度越大或返回的速度越慢,說明電容的容量越大,反之則說明電容的容量越小.如表針指在中間某處不再變化,說明此電容漏電,如電阻指示值很小或為零,則表明此電容已擊穿短路.因萬用表使用的電池電壓一般很低,所以在測量低耐壓的電容時比較準確,而當電容的耐壓較高時,打時盡管測量正常,但加上高壓時則有可能發生漏電或擊穿現象.
  
三、電解電容的使用注意事項
  1、電解電容由于有正負極性,因此在電路中使用時不能顛倒聯接。在電源電路中,輸出正電壓時電解電容的正極接電源輸出端,負極接地,輸出負電壓時則負極接輸出端,正極接地.當電源電路中的濾波電容極性接反時,因電容的濾波作用大大降低,一方面引起電源輸出電壓波動,另一方面又因反向通電使此時相當于一個電阻的電解電容發熱.當反向電壓超過某值時,電容的反向漏電電阻將變得很小,這樣通電工作不久,即可使電容因過熱而炸裂損壞.
  2.加在電解電容兩端的電壓不能超過其允許工作電壓,在設計實際電路時應根據具體情況留有一定的余量,在設計穩壓電源的濾波電容時,如果交流電源電壓為220~時變壓器次級的整流電壓可達22V,此時選擇耐壓為25V的電解電容一般可以滿足要求.但是,假如交流電源電壓波動很大且有可能上升到250V以上時,最好選擇耐壓30V以上的電解電容。
  3,電解電容在電路中不應靠近大功率發熱元件,以防因受熱而使電解液加速干涸.
  4、對于有正負極性的信號的濾波,可采取兩個電解電容同極性串聯的方法,當作一個無極性的電容。
  


從名稱認識電容在電路中的作用0

電容器在電子電路中幾乎是不可缺少的儲能元件,它具有隔斷直流、連通交流、阻止低頻的特性。廣泛應用在耦合、隔直、旁路、濾波、調諧、能量轉換和自動控制等電路中。熟悉電容器在不同電路中的名稱意義,有助于我們讀懂電子電路圖。

    1.濾波電容  它接在直流電源的正、負極之間,以濾除直流電源中不需要的交流成分,使直流電平滑。一般常采用大容量的電解電容器,也可以在電路中同時并接其他類型的小容量電容以濾除高頻交流電。

2.退耦電容     并接于放大電路的電源正、負極之間,防止由電源內阻形成的正反饋而引起的寄生振蕩。

    3.旁路電容  在交、直流信號的電路中,將電容并接在電阻兩端或由電路的某點跨接到公共電位上,為交流信號或脈沖信號設置一條通路,避免交流信號成分因通過電阻產生壓降衰減。

    4.耦合電容  在交流信號處理電路中,用于連接信號源和信號處理電路或者作兩放大器的級間連接,用以隔斷直流,讓交流信號或脈沖信號通過,使前后級放大電路的直流工作點互不影響。

    5.調諧電容  連接在諧振電路的振蕩線圈兩端,起到選擇振蕩頻率的作用。

    6.襯墊電容  與諧振電路主電容串聯的輔助性電容,調整它可使振蕩信號頻率范圍變小,并能顯著地提高低頻端的振蕩頻率。適當地選定襯墊電容的容量,可以將低端頻率曲線向上提升,接近于理想頻率跟蹤曲線。

    7.補償電容 它是與諧振電路主電容并聯的輔助性電容,調整該電容能使振蕩信號頻率范圍擴大。

    8.中和電容  并接在三極管放大器的基極與發射極之間,構成負反饋網絡,以抑制三極管極間電容造成的自激振蕩。

    9.穩頻電容  在振蕩電路中,起穩定振蕩頻率的作用。

    10.定時電容  在RC時間常數電路中與電阻R串聯,共同決定充放電時間長短的電容。

    11.加速電容 接在振蕩器反饋電路中,使正反饋過程加速,提高振蕩信號的幅度。

    12.縮短電容  在UHF高頻頭電路中,為了縮短振蕩電感器長度而串接的電容。

    13.克拉潑電容  在電容三點式振蕩電路中,與電感振蕩線圈串聯的電容,起到消除晶體管結電容對頻率穩定性影響的作用。

    14.錫拉電容  在電容三點式振蕩電路中,與電感振蕩線圈兩端并聯的電容,起到消除晶體管結電容的影響,使振蕩器在高頻端容易起振。

    15.穩幅電容  在鑒頻器中,用于穩定輸出信號的幅度。

    16.預加重電容  為了避免音頻調制信號在處理過程中造成對分頻量衰減和丟失,而設置的RC高頻分量提升網絡電容。

    17.去加重電容  為恢復原伴音信號,要求對音頻信號中經預加重所提升的高頻分量和噪聲一起衰減掉,設置在RC網絡中的電容。

    18.移相電容  用于改變交流信號相位的電容。

    19.反饋電容  跨接于放大器的輸入與輸出端之間,使輸出信號回輸到輸入端的電容。

    20.降壓限流電容 串聯在交流電回路中,利用電容對交流電的容抗特性,對交流電進行限流,從而構成分壓電路。

    21.逆程電容  用于行掃描輸出電路,并接在行輸出管的集電極與發射極之間,以產生高壓行掃描鋸齒波逆程脈沖,其耐壓一般在1500V以上。

    22.校正電容  串接在偏轉線圈回路中,用于校正顯像管邊緣的延伸線性失真。

    23.自舉升壓電容  利用電容器的充、放電儲能特性提升電路某點的電位,使該點電位達到供電端電壓值的2倍。

    24.消亮點電容  設置在視放電路中,用于關機時消除顯像管上殘余亮點的電容。

    25.軟啟動電容  一般接在開關電源的開關管基極上,防止在開啟電源時,過大的浪涌電流或過高的峰值電壓加到開關管基極上,導致開關管損壞。

    26.啟動電容  串接在單相電動機的副繞組上,為電動機提供啟動移相交流電壓。在電動機正常運轉后與副繞組斷開。

    27.運轉電容  與單相電動機的副繞組串聯,為電動機副繞組提供移相交流電流。在電動機正常運行時,與副繞組保持串接。  


單片機晶振的兩個電容的作用  
這兩個電容叫晶振的負載電容,分別接在晶振的兩個腳上和對地的電容,一般在幾十皮發。它會影響到晶振的諧振頻率和輸出幅度,一般訂購晶振時候供貨方會問你負載電容是多少。
    晶振的負載電容=[(Cd*Cg)/(Cd+Cg)]+Cic+△C式中Cd,Cg為分別接在晶振的兩個腳上和對地的電容,Cic(集成電路內部電容)+△C(PCB上電容)經驗值為3至5pf。
    各種邏輯芯片的晶振引腳可以等效為電容三點式振蕩器。晶振引腳的內部通常是一個反相器, 或者是奇數個反相器串聯。在晶振輸出引腳 XO 和晶振輸入引腳 XI 之間用一個電阻連接, 對于 CMOS 芯片通常是數 M 到數十M 歐之間. 很多芯片的引腳內部已經包含了這個電阻, 引腳外部就不用接了。這個電阻是為了使反相器在振蕩初始時處與線性狀態, 反相器就如同一個有很大增益的放大器, 以便于起振. 石英晶體也連接在晶振引腳的輸入和輸出之間, 等效為一個并聯諧振回路, 振蕩頻率應該是石英晶體的并聯諧振頻率. 晶體旁邊的兩個電容接地, 實際上就是電容三點式電路的分壓電容, 接地點就是分壓點. 以接地點即分壓點為參考點, 振蕩引腳的輸入和輸出是反相的, 但從并聯諧振回路即石英晶體兩端來看, 形成一個正反饋以保證電路持續振蕩. 在芯片設計時, 這兩個電容就已經形成了, 一般是兩個的容量相等, 容量大小依工藝和版圖而不同, 但終歸是比較小, 不一定適合很寬的頻率范圍. 外接時大約是數 PF 到數十 PF, 依頻率和石英晶體的特性而定. 需要注意的是: 這兩個電容串聯的值是并聯在諧振回路上的, 會影響振蕩頻率. 當兩個電容量相等時, 反饋系數是 0.5, 一般是可以滿足振蕩條件的, 但如果不易起振或振蕩不穩定可以減小輸入端對地電容量, 而增加輸出端的值以提高反饋量.
晶振起振后的頻率準確與否,和選取的C1,C2是否與晶振規格要求的負載電容要求相吻合有直接關系,計算公式如下:CL=C1*C2/(C1+C2)+5pF;算出的CL值要與晶振規格要求的負載電容盡量接近才能獲得晶振的標稱頻率的振蕩頻率.
一般電容的計算公式是:
兩邊電容為Cg,Cd,負載電容為Cl,則
cl=cg*cd/(cg+cd)+a
就是說負載電容15pf的話,兩邊個接27pf的差不多了,一般a為6.5~13.5pF
晶振的作用:單片機工作時,就必須要一個時鐘信號,也是說它能分出一個時間單位能做多少事情(就像出操時的口令)才能步調一致,要過到這個條件,就必須要有一個人來吹這個口哨,所以我們就給他一個發指令的"人"(這就是我們常用的晶振),當然不用晶振也行,只要做個能發送穩定脈沖的電路送入CPU同樣能工作(當然必須在工作頻率范圍之內)。


標題:單片機c語言教程第十六課 C51指針的使用
2009-04-06 08:12:00
  指針就是指變量或數據所在的存儲區地址。如一個字符型的變量 STR 存放在內存單元DATA 區的 51H 這個地址中,那么 DATA 區的 51H 地址就是變量 STR 的指針。在 C 語言中 指針是一個很重要的概念,正確有效的使用指針類型的數據,能更有效的表達復雜的數據 結構,能更有效的使用數組或變量,能方便直接的處理內存或其它存儲區。指針之所以 能這么有效的操作數據,是因為無論程序的指令、常量、變量或特殊寄存器都要存放在內 存單元或相應的存儲區中,這些存儲區是按字節來劃分的,每一個存儲單元都能用唯一的 編號去讀或寫數據,這個編號就是常說的存儲單元的地址,而讀寫這個編號的動作就叫做尋 址,通過尋址就能訪問到存儲區中的任一個能訪問的單元,而這個功能是變量或數組等 是不可能代替的。C 語言也因此引入了指針類型的數據類型,專門用來確定其他類型數據的 地址。用一個變量來存放另一個變量的地址,那么用來存放變量地址的變量稱為指針變量 如用變量 STRIP 來存放文章開頭的 STR 變量的地址 51H,變量 STRIP 就是指針變量。下面 用一個圖表來說明變量的指針和指針變量兩個不一樣的概念。
  file:///Z:\TEMP\msohtmlclip1\01\clip_image001.png
  變量的指針就是變量的地址,用取地址運算符&取得賦給指針變量。&STR  就是把 變量 STR 的地址取得。用語句 STRIP  = &STR 就能把所取得的 STR 指針存放在 STRIP 針變量中。STRIP 的值就變為 51H。可見指針變量的內容是另一個變量的地址,地址所屬的 變量稱為指針變量所指向的變量。
  要訪問變量 STR 除了能用STR這個變量名來訪問之外,還能用變量地址來訪 問。方法是先用&STR  取變量地址并賦于 STRIP 指針變量,然后就能用*STRIP 來對 STR 進行訪問了。*是指針運算符,用它能取得指針變量所指向的地址的值。在上圖中指針 變量 STRIP 所指向的地址是 51H,而 51H 中的值是 40H,那么*STRIP 所得的值就是 40H 使用指針變量之前也和使用其它類型的變量那樣要求先定義變量,而且形式也相類似,
  一般的形式如下:
  數據類型 [存儲器類型] * 變量名;
  unsigned char xdata *pi //指針會占用二字節,指針自身存放在編譯器默認存儲區,指
   xdata 存儲區的 char 類型
  unsigned char xdata * data pi; //除指針自身指定在 data 區,其它同上
  int * pi; //定義為一般指針,指針自身存放在編譯器默認存儲區,占三個字節 在定義形式中數據類型是指所定義的指針變量所指向的變量的類型。存儲器類型
  是編譯器編譯時的一種擴展標識,它是可選的。在沒有存儲器類型選項時,則定義為一
  般指針,如有存儲器類型選項時則定義為基于存儲器的指針。限于 51 芯片的尋址范圍,
  
  指針變量最大的值為  0xFFFF,這樣就決定了一般指針在內存會占用 3 個字節,第一字節存 放該指針存儲器類型編碼,后兩個則存放該指針的高低位址。而基于存儲器的指針因為不用 識別存儲器類型所以會占一或二個字節,idata,data,pdata  存儲器指針占一個字節,code,xdata 則會占二個字節。由上可知,明確的定義指針,能節省存儲器的開銷,這在嚴格要求程序 體積的項目中很有用處。
  指針的使用方法很多,限于篇幅以上只能對它做一些基礎的介紹。下面用在講述常量時 的例程改動一下,用以說明指針的基本使用方法。
  #include //預處理文件里面定義了特殊寄存器的名稱如 P1 口定義為 P1
  void main(void)
  {
  //定義花樣數據,數據存放在片內 CODE 區中
  unsigned char code  design[]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,
  0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,
  0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,
  0xE7,0xDB,0xBD,0x7E,0xFF};
  unsigned int a; //定義循環用的變量
  unsigned char b;
  unsigned char code * dsi; //定義基于 CODE 區的指針
  
  do{
  dsi = &design[0]; //取得數組第一個單元的地址
  for (b=0; b<32; b++)
  {
  
  }
  }while(1);
  }
  for(a=0; a<30000; a++); //延時一段時間
  P1 = *dsi; //從指針指向的地址取數據到 P1
  dsi++; //指針加一,
  為了能清楚的了解指針的工作原理,能使用 keil  uv2 的軟件仿真器查看各變量和存儲器的
  值。編譯程序并執行,然后打開變量窗口,如圖。用單步執行,就能查到到指針的變量。 如圖中所示的是程序中循環執行到第二次,這個時候指針 dsi 指向 c:0x0004 這個地址,這個地址 的值是 0xFE。在存儲器窗口則能察看各地址單元的值。使用這種方法不但在學習時能 幫助更好的了解語法或程序的工作,而且在實際使用中更能讓你更快更準確的編寫程序或解 決程序中的問題。
  
  





  
  
  
   
      
在程序運行中,函數代碼是程序的算法指令部分,它們和數組一樣也占用存儲空間,都有相應的地址。可以使用指針變量指向數組的首地址,也可以使用指針變量指向函數代碼的首地址,指向函數代碼首地址的指針變量稱為函數
      
        
   
  file:///Z:\TEMP\msohtmlclip1\01\clip_image003.png
  

  file:///Z:\TEMP\msohtmlclip1\01\clip_image004.png
  
  file:///Z:\TEMP\msohtmlclip1\01\clip_image002.png
  
  file:///Z:\TEMP\msohtmlclip1\01\clip_image005.png
  
  
  





在程序運行中,函數代碼是程序的算法指令部分,它們和數組一樣也占用存儲空間,都有相應的地址。可以使用指針變量指向數組的首地址,也可以使用指針變量指向函數代碼的首地址,指向函數代碼首地址的指針變量稱為函數指針。
1.函數指針定義
函數類型 *指針變量名)(形參列表)
函數類型說明函數的返回類型,由于“()”的優先級高于“*”,所以指針變量名外的括號必不可少,后面的形參列表表示指針變量指向的函數所帶的參數列表。
例如:
int (*f)(int x);
double (*ptr)(double x);
在定義函數指針時請注意:
   
函數指針和它指向的函數的參數個數和類型都應該是致的;
函數指針的類型和函數的返回值類型也必須是一致的。
2.函數指針的賦值
函數名和數組名一樣代表了函數代碼的首地址,因此在賦值時,直接將函數指針指向函數名就行了。
例如,
int func(int x);   /* 聲明一個函數*/
int (*f) (int x);    /*聲明一個函數指針 */
f=func;            /* func函數的首地址賦給指針f*/
賦值時函數func不帶括號,也不帶參數,由于func代表函數的首地址,因此經過賦值以后,指針f就指向函數func(x)的代碼的首地址。
3.通過函數指針調用函數
函數指針是通過函數名及有關參數進行調用的。
與其他指針變量相類似,如果指針變量pi是指向某整型變量i的指針,則*p等于它所指的變量i;如果pf是指向某浮點型變量f的指針,則*pf就等價于它所指的變量f。同樣地,*f是指向函數func(x)的指針,則*f就代表它所指向的函數func。所以在執行了f=func;之后,(*f)func代表同一函數。
由于函數指針指向存儲區中的某個函數,因此可以通過函數指針調用相應的函數。現在我們就討論如何用函數指針調用函數,它應執行下面三步:
首先,要說明函數指針變量。
例如:int (*f)(int x);
其次,要對函數指針變量賦值。
例如: f=func;    (func(x)必須先要有定義)
最后,要用 (*指針變量)(參數表);調用函數。
例如:   (*f)(x);(x必須先賦值)

【例】任意輸入n個數,找出其中最大數,并且輸出最大數值。
main()
{
        int f();
        int iab;
        int(*p)();    /* 定義函數指針*/
        scanf('%d'&a);
        p=f;            /* 給函數指針p賦值,使它指向函數f*/
        for(i1;i<9;i++)
        {
                scanf('%d'
&b);
                a(*p)(ab);    /* 通過指針p調用函數f*/
        }
        printf('The MaxNumber is:%d'a)
}

f(int xint y)
{
    int z;
    z(x>y)?x:y;
    return(z);
}
運行結果為:
343 -45 4389 4235 1 -534 988 555 789↙
The Max Number is4389

【例】(*((void (*)())0))() 表示什么意思?
void (*)()   
聲明函數指針
        
讓我們來分析一下,左邊圓括弧中的星號是函數指針聲明的關鍵。另外兩個元素是函數的返回類型(void)和右邊圓括弧中的入口參數(本例中參數是空)。注意本例中還沒有創建指針變量-只是聲明了變量類型。
(void (*)())0  
0強制轉換成函數指針
(*((void (*)())0))()  
調用

所以(*((void (*)())0))()的意思是:調用地址為0處的程序。


【指針函數】

一個函數不僅可以帶回一個整型數據的值,字符類型值和實型類型的值,還可以帶回指針類型的數據,使其指向某個地址單元。
        返回指針的函數,一般定義格式為:
        類型標識符    *函數名(參數表)
int *f(xy);
其中xy是形式參數,f是函數名,調用后返回一個指向整型數據的地址指針。f(xy)是函數,其值是指針。
如:char *ch();表示的就是一個返回字符型指針的函數,請看下面的例題:
【例】將字符串1(str1)復制到字符串2(str2),并輸出字符串2.
#include 'stdio.h'
main()
{
    char *ch(char *char*);
    char str1[]='I amglad to meet you!';
    char str2[]='Welcomto study C!';
    printf('%s'ch(str1str2));
}
char *ch(char *str1char*str2)
{
    int i;
    char *p;
    p=str2
   
     if(*str2==NULL) exit(-1);

    do
    {
        *str2=*str1;
        str1++;
        str2++;
   }while(*str1!=NULL);
    return(p);
}

通過分析可得
函數指針是一個指向函數的指針,而指針函數只是說明他是一個返回值為指針的函數,
函數指針可以用來指向一個函數。



三極管的主要特點是具有電流放大功能,以共發射極接法為例(信號從基極輸入,從集電極輸出,發射極接地),當基極電壓UB有一個微小的變化時,基極電流IB也會隨之有一小的變化,受基極電流IB的控制,集電極電流IC會有一個很大的變化,基極電流IB越大,集電極電流IC也越大,反之,基極電流越小,集電極電流也越小,即基極電流控制集電極電流的變化。但是集電極電流的變化比基極電流的變化大得多,這就是三極管的放大作用。IC 的變化量與IB變化量之比叫做三極管的放大倍數β(β=ΔIC/ΔIB, Δ表示變化量。),三極管的放大倍數β一般在幾十到幾百倍。



幾乎在所有的電子電路中,都要用到半導體二極管,它在許多的電路中起著重要的作用,它是誕生最早的半導體器件之一,其應用也非常廣泛。

二極管的工作原理

晶體二極管為一個由p型半導體和n型半導體形成的p-n結,在其界面處兩側形成空間電荷層,并建有自建電場。當不存在外加電壓時,由于p-n 結兩邊載流子濃度差引起的擴散電流和自建電場引起的漂移電流相等而處于電平衡狀態。

當外界有正向電壓偏置時,外界電場和自建電場的互相抑消作用使載流子的擴散電流增加引起了正向電流。

當外界有反向電壓偏置時,外界電場和自建電場進一步加強,形成在一定反向電壓范圍內與反向偏置電壓值無關的反向飽和電流I0。

當外加的反向電壓高到一定程度時,p-n結空間電荷層中的電場強度達到臨界值產生載流子的倍增過程,產生大量電子空穴對,產生了數值很大的反向擊穿電流,稱為二極管的擊穿現象。

二極管的類型

二極管種類有很多,按照所用的半導體材料,可分為鍺二極管(Ge管)和硅二極管(Si管)。根據其不同用途,可分為檢波二極管、整流二極管、穩壓二極管、開關二極管等。按照管芯結構,又可分為點接觸型二極管、面接觸型二極管及平面型二極管。點接觸型二極管是用一根很細的金屬絲壓在光潔的半導體晶片表面,通以脈沖電流,使觸絲一端與晶片牢固地燒結在一起,形成一個“PN結”。由于是點接觸,只允許通過較小的電流(不超過幾十毫安),適用于高頻小電流電路,如收音機的檢波等。

面接觸型二極管的“PN結”面積較大,允許通過較大的電流(幾安到幾十安),主要用于把交流電變換成直流電的“整流”電路中。

平面型二極管是一種特制的硅二極管,它不僅能通過較大的電流,而且性能穩定可靠,多用于開關、脈沖及高頻電路中。

二極管的導電特性

二極管最重要的特性就是單方向導電性。在電路中,電流只能從二極管的正極流入,負極流出。下面通過簡單的實驗說明二極管的正向特性和反向特性。

正向特性
在電子電路中,將二極管的正極接在高電位端,負極接在低電位端,二極管就會導通,這種連接方式,稱為正向偏置。必須說明,當加在二極管兩端的正向電壓很小時,二極管仍然不能導通,流過二極管的正向電流十分微弱。只有當正向電壓達到某一數值(這一數值稱為“門檻電壓”,鍺管約為0.2V,硅管約為0.6V)以后,二極管才能直正導通。導通后二極管兩端的電壓基本上保持不變(鍺管約為0.3V,硅管約為0.7V),稱為二極管的“正向壓降”。

2、反向特性

在電子電路中,二極管的正極接在低電位端,負極接在高電位端,此時二極管中幾乎沒有電流流過,此時二極管處于截止狀態,這種連接方式,稱為反向偏置。二極管處于反向偏置時,仍然會有微弱的反向電流流過二極管,稱為漏電流。當二極管兩端的反向電壓增大到某一數值,反向電流會急劇增大,二極管將失去單方向導電特性,這種狀態稱為二極管的擊穿。

二極管的主要參數

用來表示二極管的性能好壞和適用范圍的技術指標,稱為二極管的參數。不同類型的二極管有不同的特性參數。對初學者而言,必須了解以下幾個主要參數:

1、額定正向工作電流

是指二極管長期連續工作時允許通過的最大正向電流值。因為電流通過管子時會使管芯發熱,溫度上升,溫度超過容許限度(硅管為140左右,鍺管為90左右)時,就會使管芯過熱而損壞。所以,二極管使用中不要超過二極管額定正向工作電流值。例如,常用的IN4001-4007型鍺二極管的額定正向工作電流為1A。

2、最高反向工作電壓

加在二極管兩端的反向電壓高到一定值時,會將管子擊穿,失去單向導電能力。為了保證使用安全,規定了最高反向工作電壓值。例如,IN4001二極管反向耐壓為50V,IN4007反向耐壓為1000V。

3、反向電流

反向電流是指二極管在規定的溫度和最高反向電壓作用下,流過二極管的反向電流。反向電流越小,管子的單方向導電性能越好。值得注意的是反向電流與溫度有著密切的關系,大約溫度每升高10,反向電流增大一倍。例如2AP1型鍺二極管,在25時反向電流若為250uA,溫度升高到35,反向電流將上升到500uA,依此類推,在75時,它的反向電流已達8mA,不僅失去了單方向導電特性,還會使管子過熱而損壞。又如,2CP10型硅二極管,25時反向電流僅為5uA,溫度升高到75時,反向電流也不過160uA。故硅二極管比鍺二極管在高溫下具有較好的穩定性。

測試二極管的好壞

初學者在業余條件下可以使用萬用表測試二極管性能的好壞。測試前先把萬用表的轉換開關撥到歐姆檔的RX1K檔位(注意不要使用RX1檔,以免電流過大燒壞二極管),再將紅、黑兩根表筆短路,進行歐姆調零。

1、正向特性測試

把萬用表的黑表筆(表內正極)搭觸二極管的正極,,紅表筆(表內負極)搭觸二極管的負極。若表針不擺到0值而是停在標度盤的中間,這時的阻值就是二極管的正向電阻,一般正向電阻越小越好。若正向電阻為0值,說明管芯短路損壞,若正向電阻接近無窮大值,說明管芯斷路。短路和斷路的管子都不能使用。

2、反向特性測試

把萬且表的紅表筆搭觸二極管的正極,黑表筆搭觸二極管的負極,若表針指在無窮大值或接近無窮大值,管子就是合格的。

二極管的應用

1、整流二極管

利用二極管單向導電性,可以把方向交替變化的交流電變換成單一方向的脈動直流電。

2、開關元件

二極管在正向電壓作用下電阻很小,處于導通狀態,相當于一只接通的開關;在反向電壓作用下,電阻很大,處于截止狀態,如同一只斷開的開關。利用二極管的開關特性,可以組成各種邏輯電路。

3、限幅元件

二極管正向導通后,它的正向壓降基本保持不變(硅管為0.7V,鍺管為0.3V)。利用這一特性,在電路中作為限幅元件,可以把信號幅度限制在一定范圍內。

4、繼流二極管

在開關電源的電感中和繼電器等感性負載中起繼流作用。

5、檢波二極管

在收音機中起檢波作用。

6、變容二極管

使用于電視機的高頻頭中。





經驗

浮點轉十六進制:
/*作用:浮點數---轉---十六進制 */
union fnum
{
long int m;
float f;
};
然后需要在引用的函數內聲明共用體比如:
union fnum num;
用法:共用體是將 多個成員變量共用一個地址,并且同一時刻只允許1個成員變量被賦值,當某個成員變量修改后,其他的成員立刻改變,
比如:num.f=6.91;那么num.m=0x40DD1EB8;
當num.f=6.0時,另一個成員變量也改變num.m=40C00000
因為,單片機的十進制和十六進制都可以進行直接計算,所以用以上辦法就可以實現浮點數轉十六進制.
通俗的講:共用體就像一個容器,成員變量就是不同形狀的容器出口,當我們把1個圓形的物體放進去,如果這時我們像要一個方形的物體,那么就從方形的出口將物體取出,就得到方形了,
同理,我們要浮點轉十六進制,就把浮點放進共用體(num.f=6.91),然后從整形取出( Rec=num.m )
細節問題:
因為浮點數轉成十六進制后,通常都是32位數據,所以我們在取出整形數的時候要 用一個32位的變量(long int,或者u32 ) 去存.
2. 共用體和結構體的區別  共用體和結構體有下列區別:
  1. 共用體和結構體都是由多個不同的數據類型成員組成,
  但在任何同一時刻, 共用體只存放了一個被選中的成員, 而結構體的所有成員都存在。
  2. 對于共用體的不同成員賦值, 將會對其它成員重寫, 原來成員的值就不存在了,
  而對于結構體的不同成員賦值是互不影響的。 另外要注意的是,



計算串口接收到的浮點數:
我們通常在接收到串口的數字時, 基本上都是文本類型的數字, 并且是一位一位的文本,
比如6.19就是 ‘6’, ’.’ , ’1’ , ’9’
我們將它重新變為6.19需要進行一下操作:
Arr[]={‘6’,’.’,’1’,’9’}
1.所有文本類型的數字只有 減零 之后才可以進行計算,否則是文本型.
  Arr[0]-‘0’;
2. 特別注意


sum_num= (float)(arr[6]-'0')+
(float)(arr[8]-'0')/10 +(float)(arr[9]-'0')/ 100;
在計算的時候,小數部分要轉換成 小數,然后進行相加,
注意的是 在(float) (arr[8]-'0')/10的時候, 前面要先強制裝換成(float)之后 才可以/10,這樣才是把 1變成0.1,
如果在/10之前 沒有(float)的話,意味著取10的倍數,
如果是 1/10,不加(float),那就等于0;最后相加就等于6.00000;
正確:

3. 注意細節:
成功將Arr[]={‘6’,’.’,’1’,’9’}
組合成sum_num =6.19之后, 在進行判斷sum_num時:
if(sum_num == 62.91f) { LED1=0; }
注意這里的62.91后面加f,如果不加會報警告:
:單精度操作數隱式轉換為雙精度
當if(sum_num == 62.91) { LED1=0; }
這里的sum_num是浮點型,而62.91默認是雙精度類型的;
當2個不同類型的變量 相加減時,會將二者都轉換成較大一方的類型,
所以 浮點數 和 雙精度進行判斷時:浮點數會被轉換成雙精度.所以會報警告,告訴你這里進行了這樣的操作.
當if(sum_num == 62.91f) { LED1=0; }這里的62.91f
是將62.91轉換成浮點數
浮點數 和 浮點數進行判斷 或者 計算,并不會轉換成雙精度,警告自然沒了



原創:http://www.raoushi.com/bbs/dpj-128076-1.html





歡迎光臨 (http://www.raoushi.com/bbs/) Powered by Discuz! X3.1