剛學單片機沒多久,折騰數碼管走了很多彎路,記錄一下心得,電路圖有的手畫,方便點,單片機用的STC91C52RC。
1.先來講講單片機的構成,最小的可運行的單片機系統由復位電路,振盪電路等組成。如下圖,單片機引腳圖就不放了,藍色部分即復位電路,由單片機RST引腳引出,一路接上10μF電容至VCC(正極),另一路接10K電阻接地。紅色部分即振盪電路,由單片機的XTAL1和XTAL1引出,分別串一個20P左右電容,中間串上12MHZ晶振,匯流接地。至於中間的綠色電路,EA/VPP引腳直接接到VCC,目的是讀取內部ROM。串口通訊使用CH340芯片,連接方式根據購買指導連接即可。
2.基本電路明白了之后就可以焊接電路了,單片機建議使用插座,如下圖的綠色部分所示,為了方便可以將引腳引出來,利用插針(即紅色部分兩旁的東西)與引腳連在一起,需要用到引腳時用杜邦線接起來即可,方便拆卸,接線,如下圖1。
3.明白了最小電路之后,就需要四位數碼管了如下圖就是一個共陰極四位數碼管,共陰極的意思即內部的所有發光二極管都有一個公共端,需要將此公共端接地,數碼管才能發光。每個位都有一個公共端。拿到這個數碼管之后我們就需要測出每個引腳代表的段數,所謂的段數見圖,a~g即數碼管的段數,1~4就是公共端。我的是共陰極,用萬用表的二極管擋位,黑筆選一個腳位,紅筆去碰其他的引腳,如果段數逐一發亮,黑筆所碰的那個引腳就是公共端,記下來黑筆那個引腳位置以及編號,記下段數編號對應的引腳,繼續用黑筆去找出其他三個公共端即可。
4.了解了數碼管之后,可以試着將數碼管直接接到單片機上,我們這里可以使用P1作為段數的選擇,直接將a~g引腳依次接到P1口,可以像上圖從數碼管引出到插針,用杜邦線和P1口連接。1~4直接接地,將P0置1,(P0 = 0XFF) 即可點亮數碼管,但是亮度會很低,因為I/O口的輸出驅動所有數碼管很吃力,所以我們接下來要使用三極管放大電路增強驅動能力。
5.三極管使用的NPN型,我使用的是型號是S8050,如下圖,將三極管有字的那一面面向自己,從左到右分別是發射級,基極,集電極,原理這里就不贅述了。接下來講一下電路的連接。
6.電路的連接,如下圖所示。藍色框是段選電路的連接,這里注意一點,由於P0的特殊構造,輸出高電平需要加入上拉電阻,即那個330Ω的排阻,將排阻的公共端接到VCC,分出兩路連到P0.0~P0.7以及數碼管的a~f引腳。如圖,藍色就是排阻,兩邊右邊接排針連到P0,左邊接排針連到數碼管。接下來是圖5的綠色電路,B(基極)接到P2.0~P2.3,C(集電極)接到數碼管的公共端1~4,E(發射級)接地。
7.程序的編寫。當P0給出高電平時那一段的二極管亮,例如我們要讓它顯示數字0,我的數碼管對應的段位如下圖,除了g和dp是0其他都給1即可,即11111100,換成16進制0XFC,代碼就可以寫成P0 = 0XFC。代碼的解釋:我們利用內部T0計數器,這些中斷都是需要掌握的,推薦新概念單片機C語言入門這本書。計數20次為一秒,中斷20次后再利用一個變量計數60次,即一分鍾,讓分鍾數+1,分別判斷分鍾數是否60,小時數是否24,分別送入display十位數和個位數。程序以下給出參考:
#include<reg51.h> #include<intrins.h> #define uint unsigned int #define uchar unsigned char void delays(uint); uint i,j; uchar code table1[]={ 0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; //數碼顯示管0-9 uchar code table2[] = { 0x01,0x02,0x04,0x08}; //位選 uchar num,num1,num2,shi,ge,shi1,ge1,t; void display(uchar,uchar,uchar,uchar); void main() { TMOD = 0X01; //內部定時模式16bit TH0 = (65536-50000)/256; //設置初值 TL0 = (65536-50000)%256; //設置初值 EA = 1; //總中斷開 ET0 = 1; //內部定時開 TR0 = 1; //溢出位開 ge1 = 0; //設置時鍾的初值,一下同理 shi1 = 2; num1 = 25; ge = 5; shi = 2;
num2 = 20; while(1){ display(shi,ge,shi1,ge1); } } void display(uchar shi,uchar ge,uchar shi1,uchar ge1){ //ÏÔʾº¯Êý //if (num1 > 10) //{ P0 = 0; //消除顯示殘影 P2 = table2[1]; //位選 P0 = table1[ge]; //段選 delays(5); //延時 P0 = 0; P2 = table2[0]; P0 = table1[shi]; delays(5); P0 = 0; P2 = table2[3]; P0 = table1[ge1]; delays(5); P0 = 0; P2 = table2[2]; P0 = table1[shi1]; delays(5); } void T0_time() interrupt 1 //中斷函數 { TH0 = (65536-50000)/256; //設置初值 TL0 = (65536-50000)%256; //設置初值 num++; //計數變量 if(num == 20) //中斷20次為一秒 { num = 0; //20次后置0重新開始 t ++; //60次的一秒即一分鍾計數變量 if (t == 60){ //檢查是否到了60秒 t = 0; num1 ++; //分鍾數進1 if(num1 == 60){ //檢查分鍾數是否60· num1 = 0; //如果是置0 num2 ++; //小時數進1 if (num2 == 24){num2 = 0;} //檢查是否過了24小時,是的話置0 shi1 = num2/10; //小時的十位數 ge1 = num2 % 10; //小時的個位數 } shi = num1/10; //分鍾的十位數 ge = num1 % 10; //分鍾的個位數 } } } void delays(uint xms){ //ÑÓʱº¯Êý1ºÁÃëΪ»ùÖµ uint i,j; for (i = 0;i < xms;i++){ for (j = 83;j > 0;j--); } }