實驗室考覈複習(一)----51單片機(基礎模塊)

0x00 前言

  6月份實驗室考覈,考覈的內容我也不知道(估計是 51,c,加點電分,或者數據結構?不知道),雖然是一些入門的東西,不過爲了萬無一失(誰也不敢說會不會出一些犄角旮旯的東西),還是從頭捋一遍。(菜雞瑟瑟發抖),先51看一下吧。我就拿

普中-51-A3的舉例了

本文全當博主的複習,主要是結合 小蜜蜂51普中51

0x01 最小系統板:

1.電源電路 2.復位電路 3.時鐘電路 4.下載電路

MCU

 

4個廣角,P0 P1 P2 P3 對應就行。

復位

RST 網絡標號  跟上述單片機的9腳相連,

1)當按鍵按下後,電源會經過按鍵,接入RST引腳進行復位(51單片機是進行高電頻復位)

2)不按的化,通過R與電容組成的RC充放電電路,進行復位

晶振電路

 

可以看出來是採用12兆晶振,兩邊c12 c13電容,接在單片機的18 19 腳。

電源電路 && 下載電路

通過下面的usb接口,接入電源,經過濾波電容進行濾波(圖中紅框處),緊接這連接D5V的開關,送到VCC,之後各部分纔有電,當沒有按下開關時,這個DIN5VS(5伏)只是和 CH340 這個芯片來識別串口,並沒有供電

P5短接板

CH340用的也是12兆晶振

下載時就利用RTS 和DTR高低電頻的變化,進行下載復位(STM就需要人爲了)

注意:CH340的位置一定要接地,不然會發燙。

0x02 LED

1.定義:LED,即發光二極管,是一種半導體固體發光器件。(寫上吧,萬一考呢)

2.LED的工作原理。           LED的符號爲:      LED的工作是有方向性的,只有當正級接到LED陽極,負極接到LED的陰極的時候才能工作,如果反接LED是不能正常工作的。

3.原理圖

正入負出,所以陽極都接到了VCC(高電平)上,陰極串聯一個電阻接到了P2口,所以點亮的話把對應的P2口拉低就行。

流水:

#include <REGX51.H>
#include <intrins.h>
typedef unsigned char u8;
typedef unsigned int u16;


void delay(u16 i)
{
	while(i--);//ͨ¹ýËÀÑ­»·Õ¼ÓÃcpuÔËËãʱ¼äÀ´ÑÓʱ
}
		
void LED_WATER()
{
	int i;
	
	for (i = 0 ; i < 7; i++)
	{
		P2 = ~(0x01 << i);
		delay(25000);
	}

	for (i = 0 ; i < 7; i++)
	{
		P2 = ~(0x80 >> i);
		delay(25000);
	}
}


void main()
{
	P2 = ~(0x01);
	delay(25000);
	while(1)
	{
		LED_WATER();
	}
}

(下面的代碼只寫關鍵部分)

0x03 蜂鳴器

有電路板的是無源蜂鳴器,沒有電路板的是有緣蜂鳴器(用黑膠封閉)

有源:在IO裏輸出一個電平就行         無源:電平 + 一定頻率脈衝

電磁式蜂鳴器由振盪器、電磁線圈、磁鐵、振動膜片及外殼等組成。     接通電源後,振盪器產生的音頻信號電流通過電磁線圈,使電磁線圈產生磁場,振動膜片在電磁線圈和磁鐵的相互作用下,週期性地振動發聲。

電磁式蜂鳴器由振盪器、電磁線圈、磁鐵、振動膜片及外殼等組成。     接通電源後,振盪器產生的音頻信號電流通過電磁線圈,使電磁線圈產生磁場,振動膜片在電磁線圈和磁鐵的相互作用下,週期性地振動發聲。

 壓電式蜂鳴器主要由多諧振盪器、壓電蜂鳴片、阻抗匹配器及共鳴箱、外殼等組成。     多諧振盪器由晶體管或集成電路構成,當接通電源後(1.5~15V直流工作電壓),多諧振盪器起振,輸出1.5~2.5kHZ的音頻信號,阻抗匹配器推動壓電蜂鳴片發聲。

 聲音

改變單片機引腳輸出波形的頻率,就可以調整控制蜂鳴器音調,產生各種不同音色、音調的聲音。

大小

改變輸出電平的高低電平佔空比,則可以控制蜂鳴器的聲音大小。、

原理圖

 

可以看到蜂鳴器BEEP接到了ULN2003D上,對應的是P2^5

ULN2003

放大電路,放大驅動電流

(下面是套話)

ULN2003 是高耐壓、大電流達林頓陳列,由七個硅NPN 達林頓管組成。 ULN2003是大電流驅動陣列,多用於單片機、智能儀表、PLC、數字量輸出卡等控制電路中。可直接驅動蜂鳴器、繼電器等負載 。

代碼

sbit bee = P2 ^ 5;  //因爲是無源,所以要  脈衝+電平

void main()
{
    bee = ~bee;  //產生脈衝
    delay(10);
}

 

0x04 數碼管

(因爲是複習,就不分靜態和動態了)

顯示器&&接口

LED顯示器有兩種:段顯示(7段,米字型等)和點陣顯示

LED數碼管根據LED的不同接法可分爲2類:共陰和共陽。

(A3裏沒有單個的,這是別人的圖)

共陰就是陰極接地,所以要是亮就得輸入高電平

共陽就是陽極接vcc,所以要是亮就得輸入低電平

共陽極數碼管編碼表:
unsigned char table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
共陰極數碼管編碼表:
unsigned char table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

原理圖:

引腳對應着 P0,看一眼P0口:

共陽,低電平有效

注意:P0口是露底開路的,如果不加上拉電阻(VCC)的話,對P0無法進行輸入輸出的控制。

使能

鎖存器:74HC245 (一般是74HC573,這個普中A3的板子有點神奇)

簡單地說鎖存器就是一個緩存器,它能保存上一次的狀態,自帶使能端口,清零端口。當使能端有效時,則左右兩端導通,否則斷開。

74HC245:

 

 

 

7HC573 :通常配合或非門(74HC02)使用

138譯碼器

74HC138 簡單地說138譯碼器將一個特殊的編碼翻譯成一個狀態。

代碼:(因爲普中這個板子,138譯碼器,接的是P2^2,P2^3,P2^4,有些麻煩,爲了直觀代碼如下)

sbit lsa=P2^2;
sbit lsb=P2^3;
sbit lsc=P2^4;

void wei_poc(u8 poc)
{
    switch(poc)
		{
			case 0:
				lsa=1;lsb=1;lsc=1;break;
                        case 1:
				lsa=0;lsb=1;lsc=1;break;
			case 2:
				lsa=1;lsb=0;lsc=1;break;
                        case 3:
				lsa=0;lsb=0;lsc=1;break;
                        case 4:
				lsa=1;lsb=1;lsc=0;break;
                        case 5:
				lsa=0;lsb=1;lsc=0;break;
			case 6:
				lsa=1;lsb=0;lsc=0;break;
			case 7:
				lsa=0;lsb=0;lsc=0;break;
		}

}

在藍橋杯裏有方便的寫法。

 

動態數碼管

動態顯示的特點是將所有數碼管的段選線並聯在一起,由位選線控制是哪一位數碼管有效。選亮數碼管採用動態掃描顯示。所謂動態掃描顯示即輪流向各位數碼管送出字形碼和相應的位選,利用發光管的餘輝和人眼視覺暫留作用,使人的感覺好像各位數碼管同時都在顯示。動態顯示的亮度比靜態顯示要差一些,所以在選擇限流電阻時應略小於靜態顯示電路中的。

說白了就是利用視覺殘留,讓多個靜態數碼管循環亮起。

代碼

u8 code DUANXUAN[]={                       //標準字庫
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8.
void SMC_Bit(u8 dat, u8 poc)
{
    P0 = ~DUANXUAN[dat];//段
    wei_poc(poc);//位
}

void SMC_Display()
{
    SMC_Bit(1,0);
    delay(500);
    SMC_Bit(0,0);//消影
    
    SMC_Bit(2,1);
    delay(500);
    SMC_Bit(0,1);//消影
    
    SMC_Bit(3,2);
    delay(500);
    SMC_Bit(0,2);//消影
    
    SMC_Bit(4,3);
    delay(500);
    SMC_Bit(0,3);//消影
   
    SMC_Bit(5,4);
    delay(500);
    SMC_Bit(0,4);//消影
    
    SMC_Bit(6,5);
    delay(500);
    SMC_Bit(0,5);//消影
    
    SMC_Bit(7,6);
    delay(500);
    SMC_Bit(0,6);//消影
    
    SMC_Bit(8,7);
    delay(500);
    SMC_Bit(0,7);//消影
}

(代碼要結合前文,注意一下自己的是共陰還是共陽)

 

0x05 獨立按鍵

按鍵的兩個引腳,一端通過電阻上拉到高電平,另一端接地。

沒有按鍵按下時,輸入引腳爲高電平。

有按鍵按下時,輸入引腳爲低電平。

掃描:通過反覆讀取按鍵輸入引腳的信號,然後識別高低電平來判斷是否有按鍵觸發。

去抖動

(別人的圖)

首次檢測到輸入引腳有低電平後,稍做延時,再次讀取該引腳,如果確實是低電平,則觸發,否則就是干擾信號。

原理圖:

代碼:

-------------------------------------
按鍵按下,L1燈亮;
按鍵鬆開,L1燈滅;
-------------------------------------
sbit K1 P3^1;
sbit L1 P2^0;

void ScanKeys_Alone()
{
    if (K1 == 0)
    {
        delay(100);
        if(K1 == 0)
        {
            L1 = 0;          //按鍵按下,L1燈亮
            while(K1 == 0);  //分界線
            L1 = 1;          //按鍵鬆開,L1燈滅
        }
    }
}

要注意,按下和鬆開的位置。

 

0x06 矩陣按鍵

小蜜蜂老師這篇寫得很仔細:https://www.cnblogs.com/ALittleBee/p/8411771.html

下面是我摘抄的一些:

與獨立按鍵不同的是,按鍵的兩個引腳都分別連接的單片機的I/O端口,一個作爲行信號,另外一個作爲列信號。我們以4X4的矩陣鍵盤爲例,試着探討其工作方式和掃描思路。

 

在上面的矩陣鍵盤中,要識別出黃色按鍵的按下狀態,應該怎麼做呢?
    對與矩陣鍵盤,我們只能逐行掃描,然後讀取列的狀態信號。如果R3行輸出低電平,那麼黃色按鍵如果有按下動作的話,那讀取C2列信號也應該爲低電平,而該行上其他沒有按下動作的按鍵的列信號則爲高電平。因此,我們可以得到矩陣鍵盤的基本掃描步驟:
    <1> R1輸出點電平,R2、R3、R4輸出高電平,逐個讀取判斷列信號,如果都爲高電平則R1行上沒有按鍵按下。
    <2> R2輸出點電平,R1、R3、R4輸出高電平,逐個讀取判斷列信號。
    <3> R3輸出點電平,R1、R2、R4輸出高電平,發現C2列信號爲低電平,那麼可以判斷得R3行的C2列的按鍵有按下動作。
    <4> R4輸出點電平,R1、R3、R4輸出高電平,逐個讀取判斷列信號。
    如此循環往復,掃描的按鍵的狀態。
    我們知道有按鍵按下動作,那麼又怎麼知道是哪一個按鍵按下呢?這時,我們最好定義一個鍵值全局變量,給矩陣行列上的每一個的按鍵編一個唯一的號碼。當掃描的某一行某一列的按鍵動作後,把對應的編號複製給鍵值變量,這樣我們判斷這個鍵值,就知道是那個按鍵有觸發動作了。

代碼:

原理圖:

sbit R1 = P1^7;
sbit R2 = P1^6;
sbit R3 = P1^5;
sbit R4 = P1^4;

sbit C1 = P1^3;
sbit C2 = P1^2;
sbit C3 = P1^1;
sbit C4 = P1^0;

void ScanKeys()
{
        keyNum = 16;//黑屏
        R1 = 0;
        R2 = R3 = R4 = 1;
        C1 = C2 = C3 = C4 = 1;
        if(C1 == 0)
        {
                while(C1 == 0);
                keyNum = 0;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C2 == 0)
        {
                while(C2 == 0);
                keyNum = 1;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C3 == 0)
        {
                while(C3 == 0);
                keyNum = 2;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C4 == 0)
        {
                while(C4 == 0);
                keyNum = 3;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        
        R2 = 0;
        R1 = R3 = R4 = 1;
        C1 = C2 = C3 = C4 = 1;
        if(C1 == 0)
        {
                while(C1 == 0);
                keyNum = 4;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C2 == 0)
        {
                while(C2 == 0);
                keyNum = 5;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C3 == 0)
        {
                while(C3 == 0);
                keyNum = 6;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C4 == 0)
        {
                while(C4 == 0);
                keyNum = 7;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        
        R3 = 0;
        R2 = R1 = R4 = 1;
        C1 = C2 = C3 = C4 = 1;
        if(C1 == 0)
        {
                while(C1 == 0);
                keyNum = 8;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C2 == 0)
        {
                while(C2 == 0);
                keyNum = 9;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C3 == 0)
        {
                while(C3 == 0);
                keyNum = 10;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C4 == 0)
        {
                while(C4 == 0);
                keyNum = 11;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        
        R4 = 0;
        R2 = R3 = R1 = 1;
        C1 = C2 = C3 = C4 = 1;
        if(C1 == 0)
        {
                while(C1 == 0);
                keyNum = 12;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C2 == 0)
        {
                while(C2 == 0);
                keyNum = 13;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C3 == 0)
        {
                while(C3 == 0);
                keyNum = 14;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
        else if(C4 == 0)
        {
                while(C4 == 0);
                keyNum = 15;
                ShowKeyNum(SMG_NoDot[keyNum]);
        }
}

按鍵掃描有很多種寫法,這是一種好理解,引腳比較靈活,但是笨笨的寫法。

下面這種,需要引腳比較規則時比較方便:

void KeyDown()   
{
	io_Key=0x0f;      //行
	if(io_Key !=0x0f) //判斷是否按下
	{
		delay(1000);     //去抖動
		if(io_Key !=0x0f)
		{
			io_Key =0x0f; //行
			switch(io_Key)
			{
				case 0x07:
					KeyValue=0;break;
		                case 0x0b:
					KeyValue=1;break;
	                        case 0x0d:
					KeyValue=2;break;
		                case 0x0e:
					KeyValue=3;break;
			}
		        io_Key =0xf0; //列
			switch(io_Key)
			{
				case 0x70:
					KeyValue=KeyValue;break;
		                case 0xb0:
					KeyValue=KeyValue+4;break;
	                        case 0xd0:
					KeyValue=KeyValue+8;break;
		                case 0xe0:
					KeyValue=KeyValue+12;break;
			}
			while((a<50) && io_Key!=0xf0)
			{
				delay(1000);
				a++;
			}
		}
	}
}

0X07 中斷系統

參考文章https://bbs.21ic.com/icview-2477100-1-1.html(小蜜蜂老師賽高)

在執行cpu當前程序時,由於系統中出現了某種急需處理的情況,cpu暫停正在執行的程序,轉而去執行另外一段特殊的程序來處理出現的緊急事務,處理結束後,CPU自動返回到原來暫停的程序中去繼續執行。這種程序在執行過程中由於外界的原因而被中間打斷的情況,成爲中斷。

圖解:

引起CPU中斷的根源,稱爲中斷源。中斷源向CPU提出的中斷請求。CPU暫時中斷原來的事務A,轉去處理事件B。對事件B處理完畢後,再回到原來被中斷的地方(即斷點),稱爲中斷返回。實現上述中斷功能的部件稱爲中斷系統

中斷服務函數:內核響應中斷後執行的相應處理程序。
中短向量:中斷服務函數的入口地址。每個中斷源都對應一個固定的入口地址。當內核響應中斷請求時,就會暫停當前的程序執行,然後跳轉到該入口地址執行代碼。

注意:有中斷請求不一定能打斷主程序。

 

   隨着計算機技術的應用,人們發現中斷技術不僅解決了快速主機與慢速I/O設備的數據傳送問題,而且還具有如下優點: 分時操作。CPU可以分時爲多個I/O設備服務,提高了計算機的利用率;

實時響應。CPU能夠及時處理應用系統的隨機事件,系統的實時性大大增強;

可靠性高。CPU具有處理設備故障及掉電等突發性事件能力,從而使系統可靠性提高。

 (以上看一眼瞭解一下,萬一考呢,下面說正事)

中斷系統

 

一般來說,51單片機有5箇中斷源(忽略定時/計數器2),分2個優先級,這個5箇中斷源按照自然優先級從高到低依次爲:
    外部中斷0INT0
    定時/計數器0TF0
    外部中斷1INT1
    定時/計數器1TF1    
    串口中斷RI/TI

(圖一)

每個中斷源都對應着一個固定的入口地址,也就是中斷向量,它們依次是:
    0    0x0003:  INT0
    1    0x000B:  TF0
    2    0x0013:  INT1
    3    0x001B:  TF1
    4    0x0023:  RI/TI
    也就是說,不管主程序執行到什麼地方,只要外部中斷1產生請求,內核要響應該中斷,就會到0x0013這個地址去執行代碼。如果你是在使用彙編語言進行程序開發的時候,你需要記住每個中斷源對應的地址;如果你使用的是C語言,你只需要記住中斷源的順序就可以了,也就是最左邊的中斷號

寄存器

中斷相關的寄存器有4個,每個寄存器都是可以位尋址的,這該編程帶來了方便。    其中2個爲控制寄存器:IE寄存器IP寄存器

 

另外2個爲中斷請求標誌:TCON寄存器SCON寄存器

代碼

/////////////////////////////==中斷0==///////////////
void Init_INT0()//觸發方式
{
	IT0 = 1;//下降沿觸發
	EX0 = 1;//中斷使能打開
	EA = 1;//總中斷打開
}

void ServiceINT0() interrupt 0
{
	......//終端服務函數的編寫
}
///////////////////////////==中斷0_end==////////////

(Init_INT0()函數結合 圖一 去看)

0x08 定時/計數器

參考文章:https://bbs.21ic.com/icview-2477676-1-1.html

作爲定時器時,計數信號的來源選擇週期性的內部時鐘脈衝;用作計數器時,計數信號的來源選擇非週期性的外部輸入信號

本質上都是計數器

計算:

51單片機有兩個定時/計數器T0和T1,爲16位加法計數器,由低8位TLx和高8位THx兩個寄存器組成,最大計數值爲65535個計數脈衝

原理: 每接收到一個計數脈衝,計數器就會加1,當計數值累計至全爲1時(8位255,13位8191,16位65535),再輸入一個計數脈衝,計數器便會溢出回零,並且計數器的溢出是TCON寄存器的TF0或TF1位置1,同時向內核提出中斷請求。如果定時/計數器工作於定時模式,則表示間隔定時時間到,如果工作與計數模式,則表示計數值已滿。

     假設單片機的外部晶振爲12MHz,那麼,經過12分頻後輸入計數器的計數脈衝爲1MHz,即每個脈衝的週期爲1us。因此定時器T0的16位工作模式最大的定時時間爲65535us,65.5ms。如果要定時10ms的話,計數器就不能夠從0開始計數了,必須給它一個計數初值。怎麼計算這個初值呢?
    要定時10ms,則相當於計數10000個脈衝後計數器的值就到達65535了,那麼開始計數的這個地方就是計數初值。
    65535 - 10000 = 55535 = 0xd8ef
    把這個計算得到的初值寫入TH0和TL0寄存器即可:
    TH0 = 0xd8;或者 TH0 = (65535 - 10000) / 256;
    TL0 = 0xef; 或者  TL0 = (65535 - 10000) % 256;

當然明白了,上述文章中還有個例題,也是同樣的計算方法(具體見上述文章)。

寄存器

除了除了計數初值寄存器THxTLx之外,還有TMOD寄存器和TCON寄存器

(小蜜蜂的圖)

TCON:見上段落(中斷)所寫。

代碼:

void Init_T0()//需要配置TMOD THX TLX ET0 EA TR0
{
	//TMOD: GATE = 0; c/t = 0; M1,M0 = 0x01
	TMOD = 0X01;
	//初值5ms * 100 = 0.5s
	TH0 = (65535 - 50000) / 256;//高8位
	TL0 = (65535 - 50000) % 256;//低8位
	//打開使能
	ET0 = 1;
	//總中斷
	EA = 1;
	TR0 = 1;
}

void ServiceT0() interrupt 1
{
	//因爲沒有打開自動重裝載,所以要重新配置
	TH0 = (65535 - 50000) / 256;//高8位
	TL0 = (65535 - 50000) % 256;//低8位
        ......//編寫服務函數
}
	

(定時器通常與全局變量相結合來編寫)

 

0x09 串口通信

串口通信的概念有很多,這裏只講述博主認爲重要的(重要的意思就是感覺能考的(手動滑稽))

一些概念:

串行 && 並行:

串行通信:是將數據字節分成一位一位的形式在 一條傳輸線上逐個地傳送。

串行通信的特點:傳輸線少,長距離傳送時成本低,且可以利用電話網等現成的設備,但數據的傳送控制比並行通信複雜。  

 

並行通信:通常是將數據字節的各位用多條數據線同時進行傳送 。

並行通信的特點:並行通信控制簡單、傳輸速度快;由於傳輸線較多,長距離傳送時成本高且接收方的各位同時接收存在困難。

 

通信種類:

在51中一般是串行,在此不談並行,串行通信有SPI,IIC,UART,大多數,串行通信指的就是UART.

傳輸方向:

單工是指數據傳輸僅能沿一個方向,不能實現反向傳輸。

半雙工是指數據傳輸可以沿兩個方向,但需要分時進行。

全雙工是指數據可以同時進行雙向傳輸。

通信方式:

異步通信:通信中雙方的比特率要保持一致。以字符爲單位進行數據幀傳輸,一次一幀。

 

同步通信:需要同一個時鐘,以數據塊傳輸。

比特率:

串口每秒傳輸的位數。

在51中有4種模式:

模式1,3,由定時器1的溢出率決定,波特率可變

通常用模式2 因爲是由定時器1的8位自動重裝載產生,當TH1溢出時,自動裝到TL1去。

波特率怎麼算的就大致看一下把(瞭解爲主)主要是圖中後兩行話

串口通信有2個緩衝寄存器SBUF,一個發送,一個接收,物理上完全獨立,字節尋址(99h).

發送:自動發完之後,TI標誌位置1。

SBUF = 0x00; //發送

接收:自動接收之後,RI標誌位置1。

變量 = SBUF; //接收到一個變量裏

SCON

(小蜜蜂的圖)

記住SCON = 0x50,類似藍橋杯的板子還需要設置AUXR,普中A3就不用了。

代碼:

// sfr AUXR=0x8e;   //藍橋杯要用            
//--------------------------------------
unsigned char tmpRecv;
void Init_Uart()
{
    TMOD=0x20;       
    TH1=0xfd;        
    TL1=0xfd;       
            
    TR1=1;           
    SCON = 0x50;     
    ES=1;             
    EA=1;             
   // AUXR &= 0x40; //藍橋杯要用
}
/*==============發送一個字節===============*/
void SendByte(unsigned char dat)
{
    SBUF = dat;            
    while(TI == 0);       
    TI = 0;                
}
/*=============服務函數================*/
void Sevice_Uart() interrupt 4
{
    if(RI == 1)                
    {
        RI = 0;               
        tmpRecv = SBUF;//接收
        SendByte(tmpRecv + 1);//再發出去  (接收的值 + 1)
    }
}

當然這裏也給出穿字符串的寫法:

void Send_Byte(u8 dat)
{
	SBUF = dat;//發送
	while(TI == 0);
	TI = 0;
}

void Send_Str(u8* str)
{
	while(*str != '\0')
	{
		Send_Byte(*str++);
	}
}

 

0x0A 總結

因爲篇幅的原因,51單片機的外設芯片,pwm之類的放到下一章去寫,本文是博主的複習,借用了小蜜蜂和普中的一些素材。

因爲是複習,所以點了一些博主覺得會考的知識點,放了一些博主用慣了的代碼。如有不正確的地方,請路過的大佬斧正,希望可以幫助到各位看官,(下一篇是外設芯片篇)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章