專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

80C51串行口通信

作者:佚名   來(lái)源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年04月19日   【字體:

80C51串行口的結(jié)構(gòu)



TXD  是80C51單片機(jī)的P3.1口

RXD  是80C51單片機(jī)的P3.0口

T1 溢出率 是定時(shí)器1 的溢出率  SMOD  是發(fā)送速率倍頻的   16分頻  T1每溢出一次發(fā)送一位,里面復(fù)雜咱們不管,每次發(fā)送完后TI 申請(qǐng)中斷,就是串口每次發(fā)送完一個(gè)字節(jié)去申請(qǐng)一個(gè)中斷,每接受完一個(gè)字節(jié)它也要申請(qǐng)一次中斷。接受完了通過(guò)移位寄存器  SBUF 取走。發(fā)送也用SBUF .

 

單片機(jī)上有兩個(gè)物理上獨(dú)立的接受,發(fā)送緩沖器SBUF,它們占用同一地址99H;接受器是雙緩沖結(jié)構(gòu);發(fā)送緩沖器,因?yàn)榘l(fā)送時(shí)CPU是主動(dòng)的,不會(huì)產(chǎn)生重疊錯(cuò)誤。

解釋下這句話意思:物理上獨(dú)立的但是地址相同,但是具體內(nèi)部構(gòu)造咱們不去了解它。2個(gè)寄存器一個(gè)負(fù)責(zé)發(fā)一個(gè)負(fù)責(zé)收,接受是雙緩沖的結(jié)構(gòu)。如果去取數(shù)據(jù)  A=SBUF   ; 發(fā)送數(shù)據(jù)  SBUF =A;   就是說(shuō)SBUF =A 就把A 發(fā)出去了。  A= SBUF 就是 把 SBUF 的值給取出來(lái)給了A。單片機(jī)的串口就是這么簡(jiǎn)單。主要要搞好中斷和比特率。

80C51串行口的控制寄存器

   SCON 是一個(gè)特殊功能寄存器,用以設(shè)定串行口的工作方式、接受/發(fā)送控制以及設(shè)置狀態(tài)標(biāo)志;


有此圖課看出地址誒98H 能對(duì)8整除 所以可以進(jìn)行位操作。
●SMO 和SM1為工作方式選擇位,可選擇四種工作方式:如下圖



串行口有4種工作方式。 0 、1、2、3。  f方式0 可以看出  是移位寄存器就是一位一位移位了,波特率是固定的晶振除以12    Fosc(oscillator 振蕩器),方式1 是10位異步收發(fā)器(8位數(shù)據(jù)),波特率可變。一下 2、3 類同。我們主要掌握方式1就OK。用的最多的也是方式1。波特率用軟件控制,設(shè)置多少就多少。由于選擇方式1 所以SMO SM1 就是   。

●SM2,多機(jī)通信控制位,主要用于方式2和方式3。當(dāng)接收機(jī)的SM2=1時(shí)可以利用收到的RB8來(lái)控制是否激活RI(RB8=0時(shí)不激活RI,收到的信息丟棄;RB8=1時(shí)收到的數(shù)據(jù)進(jìn)入SBUF,并激活RI,進(jìn)而在中斷服務(wù)中將數(shù)據(jù)從SBUF讀走)。當(dāng)SM2=0時(shí),不論收到的RB8為0和1,均可以使收到的數(shù)據(jù)進(jìn)入SBUF,并激活RI(即此時(shí)RB8不具有控制RI激活的功能)。通過(guò)控制SM2,可以實(shí)現(xiàn)多機(jī)通信。

在方式0時(shí),SM2必須是0。在方式1時(shí),若SM2=1,則只有接收到有效停止位時(shí),RI才置1。
      因?yàn)槲覀兙褪?個(gè)單片機(jī)所以SM2就是0了。有效停止位用到RB8  有用到校驗(yàn)的時(shí)候

●REN,允許串行接收位。由軟件置REN=1,則啟動(dòng)串行口接收數(shù)據(jù);若軟件置REN=0,則禁止接收。

    所以我們需要設(shè)置為1,就能接受數(shù)據(jù)了。 REN=1;

 


●TB8,在方式2或方式3中,是發(fā)送數(shù)據(jù)的第九位,可以用軟件規(guī)定其作用。可以用作數(shù)據(jù)的奇偶校驗(yàn)位,或在多機(jī)通信中,作為地址幀/數(shù)據(jù)幀的標(biāo)志位。
在方式0和方式1中,該位未用。

  而我們用方式1 所以不設(shè)置也可以,給0也沒(méi)問(wèn)題,因?yàn)檫@個(gè)寄存器上電時(shí)候全都是0.


●RB8,在方式2或方式3中,是接收到數(shù)據(jù)的第九位,作為奇偶校驗(yàn)位或地址幀/數(shù)據(jù)幀的標(biāo)志位。在方式1時(shí),若SM2=0,則RB8是接收到的停止位。

   因?yàn)槲覀兪欠绞?所以不用管它了。SM2=0 所以這里接到是停止位。因?yàn)槲覀儾挥眯r?yàn)位 TB8  RB8 都設(shè)置0就行了。

 

 

 

●TI,發(fā)送中斷標(biāo)志位。在方式0時(shí),當(dāng)串行發(fā)送第8位數(shù)據(jù)結(jié)束時(shí),或在其它方式,串行發(fā)送停止位的開(kāi)始時(shí),由內(nèi)部硬件使TI置1,向CPU發(fā)中斷申請(qǐng)。在中斷服務(wù)程序中,必須用軟件將其清0,取消此中斷申請(qǐng)。

●RI,接收中斷標(biāo)志位。在方式0時(shí),當(dāng)串行接收第8位數(shù)據(jù)結(jié)束時(shí),或在其它方式,串行接收停止位的中間時(shí),由內(nèi)部硬件使RI置1,向CPU發(fā)中斷申請(qǐng)。也必須在中斷服務(wù)程序中,用軟件將其清0,取消此中斷申請(qǐng)。

TI  RI 這兩位比較重要  TI 是發(fā)送停止位 硬件置1,  申請(qǐng)中斷,響應(yīng)中端時(shí)候必須清0,這個(gè)中斷就退出了,不然就會(huì)又進(jìn)入中斷了。RI 類似。所剛開(kāi)始的時(shí)候是硬件置1 所以不用管 。  給0 0 就行了。

PCON 寄存器中有一位SMOD與串行口工作有關(guān):



PCON寄存器是單片機(jī)的跟電源有關(guān)系的。  比如讓單片機(jī)進(jìn)入、休眠、掉電、低功耗狀態(tài)等。其他幾位可以去找找看資料。

     SMOD(PCON.7)  波特率倍增位。在串行口方式1、方式2、方式3時(shí),波特率與SMOD有關(guān),當(dāng)SMOD=1時(shí),波特率提高一倍。復(fù)位時(shí),SMOD=0。

就是工作的時(shí)候你想讓波特率加倍就把SMOD =1就行了。咱們不用設(shè)置它

 

80C51串行口的工作方式

一、方式0
   方式0時(shí),串行口為同步移位寄存器的輸入輸出方式。主要用于擴(kuò)展并行輸入或輸出口。數(shù)據(jù)由RXD(P3.0)引腳輸入或輸出,同步移位脈沖由TXD(P3.1)引腳輸出。發(fā)送和接收均為8位數(shù)據(jù),低位在先,高位在后。波特率固定為fosc/12。  
   1、方式0輸出



方式0咱們就不用看了

 二、方式1
    方式1是10位數(shù)據(jù)的異步通信口。TXD為數(shù)據(jù)發(fā)送引腳,RXD為數(shù)據(jù)接收引腳,傳送一幀數(shù)據(jù)的格式如圖所示。其中1位起始位,8位數(shù)據(jù)位,1位停止位。 

 

 寫入SBUF  就是SBUF = 0X01 這就寫入了、停一下 TXD 就發(fā)起始  數(shù)據(jù)  停止   停止開(kāi)始的時(shí)候TI就置1.說(shuō)明數(shù)據(jù)就發(fā)完了。

2、方式1輸入


方式1的輸入就是接受端


    用軟件置REN為1時(shí),接收器以所選擇波特率的16倍速率采樣RXD引腳電平,檢測(cè)到RXD引腳輸入電平發(fā)生負(fù)跳變時(shí),則說(shuō)明起始位有效,將其移入輸入移位寄存器,并開(kāi)始接收這一幀信息的其余位。接收過(guò)程中,數(shù)據(jù)從輸入移位寄存器右邊移入,起始位移至輸入移位寄存器最左邊時(shí),控制電路進(jìn)行最后一次移位。當(dāng)RI=0,且SM2=0(或接收到的停止位為1)時(shí),將接收到的9位數(shù)據(jù)的前8位數(shù)據(jù)裝入接收SBUF,第9位(停止位)進(jìn)入RB8,并置RI=1,向CPU請(qǐng)求中斷。

 

這樣理解 是收到起始位  就收 數(shù)據(jù) 從低位 開(kāi)始收 收到 停止位中間 RI 置1

三、方式2和方式3(我這里提供點(diǎn)資料,用的幾率不大)

   方式2或方式3時(shí)偉11位數(shù)據(jù)的異步通信口。TXD位數(shù)據(jù)發(fā)送引腳,RXD 為數(shù)據(jù)的接受引腳。




    方式2和方式3時(shí)起始位1位,數(shù)據(jù)9位(含1位附加的第9位,發(fā)送時(shí)為SCON中的TB8,接收時(shí)為RB8),停止位1位,一幀數(shù)據(jù)為11位。方式2的波特率固定為晶振頻率的1/64或1/32,方式3的波特率由定時(shí)器T1的溢出率決定。
1、方式2和方式3輸出

 
     發(fā)送開(kāi)始時(shí),先把起始位0輸出到TXD引腳,然后發(fā)送移位寄存器的輸出位(D0)到TXD引腳。每一個(gè)移位脈沖都使輸出移位寄存器的各位右移一位,并由TXD引腳輸出。
     第一次移位時(shí),停止位“1”移入輸出移位寄存器的第9位上,以后每次移位,左邊都移入0。當(dāng)停止位移至輸出位時(shí),左邊其余位全為0,檢測(cè)電路檢測(cè)到這一條件時(shí),使控制電路進(jìn)行最后一次移位,并置TI=1,向CPU請(qǐng)求中斷。

2、方式2和方式3輸入

 

 

 


    接收時(shí),數(shù)據(jù)從右邊移入輸入移位寄存器,在起始位0移到最左邊時(shí),控制電路進(jìn)行最后一次移位。當(dāng)RI=0,且SM2=0(或接收到的第9位數(shù)據(jù)為1)時(shí),接收到的數(shù)據(jù)裝入接收緩沖器SBUF和RB8(接收數(shù)據(jù)的第9位),置RI=1,向CPU請(qǐng)求中斷。如果條件不滿足,則數(shù)據(jù)丟失,且不置位RI,繼續(xù)搜索RXD引腳的負(fù)跳變。

 

 


四、波特率的計(jì)算   這個(gè)重點(diǎn)一定要掌握
    在串行通信中,收發(fā)雙方對(duì)發(fā)送或接收數(shù)據(jù)的速率要有約定。通過(guò)軟件可對(duì)單片機(jī)串行口編程為四種工作方式,其中方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可變的,由定時(shí)器T1的溢出率來(lái)決定。
    串行口的四種工作方式對(duì)應(yīng)三種波特率。由于輸入的移位時(shí)鐘的來(lái)源不同,所以,各種方式的波特率計(jì)算公式也不相同。
方式0的波特率 =  fosc/12
方式2的波特率 =(2SMOD/64)· fosc        smod 要么0 要么1  32分子1  和64分子1 晶振頻率
方式1的波特率 =(2SMOD/32)·(T1溢出率)
方式3的波特率 =(2SMOD/32)·(T1溢出率)

這就是公式不要問(wèn)為什么了,T1的溢出率怎么計(jì)算呢?看下面

 

      當(dāng)T1作為波特率發(fā)生器時(shí),最典型的用法是使T1工作在自動(dòng)再裝入的8位定時(shí)器方式(即方式2,且TCON的TR1=1,以啟動(dòng)定時(shí)器)。這時(shí)溢出率取決于TH1中的計(jì)數(shù)值。

定時(shí)器作為波特率發(fā)生器時(shí),就是定時(shí)器工作在方式2 自動(dòng)重裝
         T1 溢出率 = fosc /{12×[256 -(TH1)]}

T1 溢出率就是1秒鐘溢出多少次。如果你裝滿  就255 256-255=1  12*1 =12  12M晶振 除以12 =1 所以就是1秒溢出一次。依次類推你算下。
     在單片機(jī)的應(yīng)用中,常用的晶振頻率為:12MHz和11.0592MHz。所以,選用的波特率也相對(duì)固定。常用的串行口波特率以及各參數(shù)的關(guān)系如表所示。



現(xiàn)在算一個(gè)波特率

如11.0592的晶振


我們直接設(shè)置 SMOD =0  那么2的0次方 等于1
因?yàn)?nbsp; 11059200 除以 9600 = 1152    、



為什么選用11.0592的晶振就是波特率好算  上面 是一個(gè)整數(shù)1152 所以波特率容易算。  如果用12MHZ 結(jié)果會(huì)有小數(shù)。就會(huì)有誤差不精確。如果串口通訊就會(huì)出錯(cuò),因?yàn)榫д癫蓸勇什慑e(cuò)位置了。

 

得到TH1 = 253  換成16進(jìn)制=FD 查上表  一致,F(xiàn)在很多人圖方便直接用軟件來(lái)計(jì)算了。但是這個(gè)過(guò)程還是必須的要了解的。 還有一點(diǎn)是就是SMOD 這一位是設(shè)置倍頻的。

       串行口工作之前,應(yīng)對(duì)其進(jìn)行初始化,主要是設(shè)置產(chǎn)生波特率的定時(shí)器1、串行口控制和中斷控制。具體步驟如下:

  • 確定T1的工作方式(編程TMOD寄存器);
  • 計(jì)算T1的初值、裝載TH1/TL1;
  • 啟動(dòng)T1(變成TCON中的TR1位)
  • 確定串行口控制(編程SCON寄存器);

   串行口在中斷方式工作時(shí),要進(jìn)行中斷設(shè)置(編程IE、IP寄存器)。(就是如果用中斷還得配置 串行口優(yōu)先級(jí)IP 寄存器  IE寄存器)

  • 單片機(jī)串行口應(yīng)用舉例

           在計(jì)算機(jī)組成的測(cè)控系統(tǒng)中,經(jīng)常要利用串行通信方式進(jìn)行數(shù)據(jù)傳輸。80C51單片機(jī)的串行口為計(jì)算機(jī)間的通信提供了極為便利的條件。利用單片機(jī)的串行口還可以方便地?cái)U(kuò)展鍵盤和顯示器,對(duì)于簡(jiǎn)單的應(yīng)用非常便利。這里僅介紹單片機(jī)串行口在通信方面的應(yīng)用。

一、單片機(jī)與單片機(jī)的通信。

(一)、點(diǎn)對(duì)點(diǎn)的通信 
1、硬件連接

 

(二)、多機(jī)通信

個(gè)人理解:這個(gè)串口多機(jī)通信其實(shí)跟I2C 同步通信協(xié)議差不多。區(qū)別是串口是異步的。而I2C是同步通信的。是在時(shí)鐘沿的跳變期間發(fā)生變化作為開(kāi)始。(之前本人學(xué)過(guò)ARM I2C總線協(xié)議,大概還記得點(diǎn))。

  1、硬件連接
   單片機(jī)構(gòu)成的多機(jī)系統(tǒng)常采用總線型主從式結(jié)構(gòu)。所謂主從式,即在數(shù)個(gè)單片機(jī)中,有一個(gè)是主機(jī),其余的是從機(jī),從機(jī)要服從主機(jī)的調(diào)度、支配。80C51單片機(jī)的串行口方式2和方式3適于這種主從式的通信結(jié)構(gòu)。當(dāng)然采用不同的通信標(biāo)準(zhǔn)時(shí),還需進(jìn)行相應(yīng)的電平轉(zhuǎn)換,有時(shí)還要對(duì)信號(hào)進(jìn)行光電隔離。在實(shí)際的多機(jī)應(yīng)用系統(tǒng)中,常采用RS-485串行標(biāo)準(zhǔn)總線進(jìn)行數(shù)據(jù)傳輸。



2、通信協(xié)議
所有從機(jī)的SM2位置1,處于接收地址幀狀態(tài)。
主機(jī)發(fā)送一地址幀,其中8位是地址,第9位為地址/數(shù)據(jù)的區(qū)分標(biāo)志,該位置1表示該幀為地址幀。  
所有從機(jī)收到地址幀后,都將接收的地址與本機(jī)的地址比較。對(duì)于地址相符的從機(jī),使自己的SM2位置0(以接收主機(jī)隨后發(fā)來(lái)的數(shù)據(jù)幀),并把本站地址發(fā)回主機(jī)作為應(yīng)答;對(duì)于地址不符的從機(jī),仍保持SM2=1,對(duì)主機(jī)隨后發(fā)來(lái)的數(shù)據(jù)幀不予理睬。
從機(jī)發(fā)送數(shù)據(jù)結(jié)束后,要發(fā)送一幀校驗(yàn)和,并置第9位(TB8)為1,作為從機(jī)數(shù)據(jù)傳送結(jié)束的標(biāo)志。

 主機(jī)接收數(shù)據(jù)時(shí)先判斷數(shù)據(jù)接收標(biāo)志(RB8),若RB8=1,表示數(shù)據(jù)傳送結(jié)束,并比較此幀校驗(yàn)和,若正確則回送正確信號(hào)00H,此信號(hào)命令該從機(jī)復(fù)位(即重新等待地址幀);若校驗(yàn)和出錯(cuò),則發(fā)送0FFH,命令該從機(jī)重發(fā)數(shù)據(jù)。若接收幀的RB8=0,則存數(shù)據(jù)到緩沖區(qū),并準(zhǔn)備接收下幀信息。
主機(jī)收到從機(jī)應(yīng)答地址后,確認(rèn)地址是否相符,如果地址不符,發(fā)復(fù)位信號(hào)(數(shù)據(jù)幀中TB8=1);如果地址相符,則清TB8,開(kāi)始發(fā)送數(shù)據(jù)。
從機(jī)收到復(fù)位命令后回到監(jiān)聽(tīng)地址狀態(tài)(SM2=1)。否則開(kāi)始接收數(shù)據(jù)和命令。

 

 3、應(yīng)用程序
主機(jī)發(fā)送的地址聯(lián)絡(luò)信號(hào)為:00H,01H,02H ,… …(即從機(jī)設(shè)備地址),地址FFH為命令各從機(jī)復(fù)位,即恢復(fù)SM2=1。
主機(jī)命令編碼為:01H,主機(jī)命令從機(jī)接收數(shù)據(jù);02H,主機(jī)命令從機(jī)發(fā)送數(shù)據(jù)。其它都按02H對(duì)待。

 

 
RRDY=1:表示從機(jī)準(zhǔn)備好接收。
TRDY=1:表示從機(jī)準(zhǔn)備好發(fā)送。
ERR=1: 表示從機(jī)接收的命令是非法的。
     程序分為主機(jī)程序和從機(jī)程序。約定一次傳遞數(shù)據(jù)為16個(gè)字節(jié),以01H地址的從機(jī)為例。

我們重點(diǎn)是要會(huì)程序去控制單片機(jī)和計(jì)算機(jī)來(lái)傳輸數(shù)據(jù)。
 -------------------------------------------------------------------------------------

寫一個(gè)程序:

思路:首先得讓單片機(jī)能收到數(shù)據(jù),這數(shù)據(jù)怎么給單片機(jī)呢?我們用計(jì)算機(jī)來(lái)發(fā),用串口調(diào)試助手,記住不能和下載程序工具STC-ISP用同一個(gè)串口,不然會(huì)沖突,到時(shí)候軟件會(huì)提示串口不存在等信息。如果是同一個(gè)串口那么你可以先把串口調(diào)試助手關(guān)閉串口然后再下載程序。



我們寫一個(gè)程序需求:

上位機(jī)通過(guò)串口調(diào)試助手,隨便發(fā)送一個(gè)數(shù),如果單片機(jī)收到這個(gè)數(shù),就讓單片機(jī)點(diǎn)亮一個(gè)發(fā)光二極管。調(diào)試程序就這樣,先看它能不能收到數(shù)然后再判斷是什么數(shù),做什么樣的動(dòng)作。我們先收到這個(gè)數(shù)就把發(fā)光二極管點(diǎn)亮,收不到就不亮。

#include

 

void main(){

//進(jìn)了主函數(shù)就不停的檢測(cè)收到的數(shù)據(jù),那就大循環(huán)

      //我們?cè)O(shè)成了8位異步收發(fā)器了。方式1

 TR1 =1; //啟動(dòng)定時(shí)器1 TCON 控制寄存器中   打開(kāi)定時(shí)器。

     //TCON 低四位用于控制外部中斷,高四 位 用于控制定時(shí)、計(jì)數(shù)的啟動(dòng)好申請(qǐng)中斷。

    //TF1   TF0  他倆硬件自動(dòng)置1 置0  可以用作查詢測(cè)試

     // TR1  TR0 是T1 的運(yùn)行控制位   是由軟件控制

 TMOD = 0x20;    //1   是2  是2 0   設(shè)置定時(shí)器1 為工作方式2.

   //TMOD 高4位控制 T1 定時(shí)器  T0 控制T0 定時(shí)器

TH1 = 0XFD;//算的 9600  

TL1 = 0xFD;//也就是TL1 裝滿了 TH1 自動(dòng)裝 TL1 這就是方式2

REN =1;// 把SCON 寄存器的REN 位 置 1  表示 接受。

  SM0= 0;

  SM1=1;//如果不設(shè)置這2位 就默認(rèn) 0 當(dāng)移位寄存器用了。所以必須設(shè)置

 

 

 

  while(1){

              

      //2種方法  :1 查詢RI是否置位 如果置位了,說(shuō)明收到了數(shù)據(jù)。

      //2.如果置位了 會(huì)想單片機(jī)申請(qǐng)中斷,那么我們就寫一個(gè)中斷函數(shù),因?yàn)橹袛嗍亲詣?dòng)進(jìn)入的,已有中

//斷就自動(dòng)進(jìn)入。第一個(gè)叫查詢法 第二種叫中斷法 。我們先寫查詢法。

    if (1== RI )//是0 的為真 一直循環(huán)在這里,若果收到一幀數(shù)據(jù) 硬件自動(dòng)置1  為假  跳出來(lái)執(zhí)行下面

   {

    RI= 0;//先把RI 清0  這樣就保證還能進(jìn)行下一幀數(shù)據(jù)

    //P1 = 0XFE;

    P1 = SBUF ; // 這樣你發(fā)的數(shù)據(jù)就放在SBUF 里了 然后把SBUF 再賦值給P1 ;

 

    }

    //1?、為什么會(huì)復(fù)位也亮呢?原因是 沒(méi)有設(shè)定模式 SM0 SM1;   解決就不亮了

 

    //2?、還是發(fā)送  不亮  為什么呢?收不到數(shù)據(jù)?說(shuō)明沒(méi)有設(shè)置波特率 無(wú)法檢測(cè)這個(gè)數(shù) ,

      //只有把定時(shí)器設(shè)置成方式2.因?yàn)槎〞r(shí)器方式2是8位重裝的。所以可以用在溢出的話就能算波特率了。

 

//設(shè)置比特率之前需設(shè)置TMOD

    //以上2 ?注意啊。 就OK了

 }

 

}

 

----------------------------------------

//到這里你發(fā) 55  aa   就能讓燈  亮  0101 0101   1010  1010  呵呵

//正好8位一個(gè)字節(jié)發(fā)過(guò)去 賦值給P1 口上去了。  改成4800  就不對(duì)了 因?yàn)椴蓸勇什粚?duì)了,就不準(zhǔn)了

//上面是查詢法,if  不能用while () 判斷

//在工程中  呢 就是前幾個(gè)字節(jié)表示什么 ,后面幾個(gè)東西表示什么用程序?qū)崿F(xiàn)。

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

用中斷法實(shí)現(xiàn)下

#include

 

 

void main(){

//開(kāi)定時(shí)總開(kāi)關(guān)

EA =1 ;

ES =1 ;//使能串口中斷

TMOD =0X20;//定時(shí)器方式2

TR1=1;//運(yùn)行定時(shí)器

 

TH1= 0XFD;/裝值

TL1= 0XFD;

REN =1;//串口使能接受

SM0D0 = 0;//串口工作模式  8位異步模式

SMOD1 = 1;

 

  while(1){

     

      

 

    }

 

}

void serial() interrupt 4 {

 RI=0;

 P1 = SBUF;

 

 

//串口和定時(shí)器很像  哦! 串口收到數(shù)通知單片機(jī),讓單片機(jī)處理這個(gè)數(shù),

//定時(shí)器溢出 通知單片機(jī)讓單片機(jī)重新裝置。

//剛下載有數(shù)據(jù)收到 當(dāng)有燈亮 所復(fù)位下就OK了

 ---------------------------------------------------------------------------

接下來(lái)我們讓單片機(jī)收到什么東西再發(fā)回來(lái)。就是發(fā)送這一塊。

#include

 

usning char  flag, a;

void main(){

EA =1;

ES =1;

TMOD =0X20;

TR1 =1;

TH1 = 0XFD;

TL1 =0XFD ;//9600 波特率

SMOD0=0;//設(shè)置串口工作模式

SMOD1 =1;

REN =1; //讓串口能夠接受

   while(1){

      if (1==flag){

         flag =0 

      

         SBUF = a;//同一個(gè)地址但是是兩個(gè)SBUF 當(dāng)這樣賦值時(shí)候就是賦值給發(fā)送的SBUF

      }

 

   }

}

 

void serial() interrupt 4

{

   RI=0;

   P1 = SBUF ;  //表示接受緩沖區(qū) 就是等號(hào)左右的區(qū)別決定 是接受 發(fā)送SBUF

   a= SBUF;

   flag =1;

 

}

-----------------------------------

//上面程序有個(gè)問(wèn)題是已下載程序  復(fù)位就一直收到FF  原因:

//因?yàn)?nbsp;單片機(jī)上電會(huì)判斷有沒(méi)有上位機(jī)下載程序,而我們下載程序了已經(jīng)有中斷  把  flag 賦值了 

// SBUF =a 發(fā)完了 TI 置1  又進(jìn)入中斷4   也就是 RI TI 都進(jìn)入 interrupt 4  So 循環(huán)發(fā)送。死循環(huán)

//一直發(fā)數(shù)據(jù)   發(fā)了數(shù)據(jù)就置1   置1 就中斷循環(huán)

======================================

解決方法如下

 

#include

 

usning char  flag, a;

void main(){

EA =1;

ES =1;

TMOD =0X20;

TR1 =1;

TH1 = 0XFD;

TL1 =0XFD ;//9600 波特率

SMOD0=0;//設(shè)置串口工作模式

SMOD1 =1;

REN =1; //讓串口能夠接受

   while(1){

      if (1==flag){

         flag =0 

         ES =0;//串口中斷關(guān)掉了 //再發(fā)就不會(huì) 進(jìn)中斷

         SBUF = a;//同一個(gè)地址但是是兩個(gè)SBUF 當(dāng)這樣賦值時(shí)候就是賦值給發(fā)送的SBUF

        //也可以是字符 SBUF = ‘b’ 也行  如果你寫SBUF =128  那么他是16進(jìn)制顯示 80 

    //其實(shí)可以128分開(kāi) ‘ 1’ ‘ 2’  ‘ 8’ 發(fā)3次  多數(shù)可以寫個(gè)for 循環(huán)分離開(kāi) 循環(huán)發(fā)出來(lái)。

         //檢測(cè)是否發(fā)完了

         while (!TI);//發(fā)完了 置1  取非    我覺(jué)得應(yīng)該取反  而不是邏輯非   沒(méi)發(fā)完等在這里

             TI =0;//清 0  手動(dòng)清0  到這里不會(huì)產(chǎn)生中斷因?yàn)樯厦嬷袛嚓P(guān)了 呵呵

             ES =1;//打開(kāi)串口中斷 

       

      }

    }

}

 void serial() interrupt 4

{

   RI=0;

   P1 = SBUF ;  //表示接受緩沖區(qū) 就是等號(hào)左右的區(qū)別決定 是接受 發(fā)送SBUF

   a= SBUF;

   flag =1;

 

}

------------------------------

注意:如果發(fā)的不是十六進(jìn)制  比如發(fā)1  收到是31 ASCII碼的對(duì)應(yīng)關(guān)系。C語(yǔ)言書后面有。1 對(duì)應(yīng)31   

如果發(fā)  hello everyone!  返回來(lái)hello everyone! 對(duì)應(yīng)ASCII碼有  如果十六進(jìn)制發(fā)55a 收到55 因?yàn)槟惆l(fā)的不夠 16進(jìn)制數(shù) a 就給你去掉了

//自己認(rèn)為單片機(jī)只有REN  控制單片機(jī)允許接收,為什么沒(méi)有TEN 控制單片機(jī)允許發(fā)送的位呢

//還有 TI RI  位都是單片機(jī)內(nèi)部硬件  發(fā)送 接收完一幀 數(shù)據(jù)自動(dòng)置1   需程序員 清 0

//使用中斷法 控制串口需要注意: 

//用串口記得設(shè)置定時(shí)器 裝初值 、串口模式  接收允許 開(kāi)中斷 (總中斷和串口中斷)

關(guān)閉窗口

相關(guān)文章