串口通信


1、 串口基礎知識html

  串口是串行接口(serial port)的簡稱,也稱爲串行通訊接口或COM接口。編程

  串口通訊是指採用串行通訊協議(serial communication)在一條信號線上將數據一個比特一個比特意逐位進行傳輸的通訊模式。網絡

  串口按電氣標準及協議來劃分,包括RS-232-C、RS-42二、RS485等。異步

 1. 串行通信方式async

  爲了更好的理解串口通訊,咱們還須要瞭解幾個串口通訊當中的基本概念。函數

  (1)發送時鐘:發送數據時,首先將要發送的數據送入移位寄存器,而後在發送時鐘的控制下,將該並行數據逐位移位輸出。工具

  (2)接收時鐘:在接收串行數據時,接收時鐘的上升沿對接收數據採樣,進行數據位檢測,並將其移入接收器的移位寄存器中,最後組成並行數據輸出。測試

  (3)波特率:波特率就是每秒鐘傳輸的數據位數。波特率的單位是每秒比特數(bps),經常使用的單位還有:每秒千比特數Kbps,每秒兆比特數Mbps。串口典型的傳輸波特率600bps,1200bps,2400bps,4800bps,9600bps,19200bps,38400bps。ui

  (4)波特率因子:波特率因子是指發送或接收1個數據位所須要的時鐘脈衝個數。編碼

  在串行通訊中,數據在1位寬的單條線路上進行傳輸,一個字節的數據要分爲8次,由低位到高位按順序一位一位的進行傳送。

  串行通訊的數據是逐位傳輸的,發送方發送的每一位都具備固定的時間間隔,這就要求接收方也要按照發送方一樣的時間間隔來接收每一位。不只如此,接收方還必須可以肯定一個信息組的開始和結束。

  經常使用的兩種基本串行通訊方式包括同步通訊和異步通訊。

 1.1 串行同步通信    

  同步通訊(SYNC:synchronous data communication)是指在約定的通訊速率下,發送端和接收端的時鐘信號頻率和相位始終保持一致(同步),這樣就保證了通訊雙方在發送和接收數據時具備徹底一致的定時關係。

  同步通訊把許多字符組成一個信息組(信息幀),每幀的開始用同步字符來指示,一次通訊只傳送一幀信息。在傳輸數據的同時還須要傳輸時鐘信號,以便接收方能夠用時針信號來肯定每一個信息位。

  同步通訊的優勢是傳送信息的位數幾乎不受限制,一次通訊傳輸的數據有幾十到幾千個字節,通訊效率較高。同步通訊的缺點是要求在通訊中始終保持精確的同步時鐘,即發送時鐘和接收時鐘要嚴格的同步(經常使用的作法是兩個設備使用同一個時鐘源)。

  在後續的串口通訊與編程中將只討論異步通訊方式,因此在這裏就不對同步通訊作過多的贅述了。

 1.2 串行異步通訊

  異步通訊(ASYNC:asynchronous data communication),又稱爲起止式異步通訊,是以字符爲單位進行傳輸的,字符之間沒有固定的時間間隔要求,而每一個字符中的各位則以固定的時間傳送。

  在異步通訊中,收發雙方取得同步是經過在字符格式中設置起始位和中止位的方法來實現的。具體來講就是,在一個有效字符正式發送以前,發送器先發送一個起始位,而後發送有效字符位,在字符結束時再發送一箇中止位,起始位至中止位構成一幀。中止位至下一個起始位之間是不定長的空閒位,而且規定起始位爲低電平(邏輯值爲0),中止位和空閒位都是高電平(邏輯值爲1),這樣就保證了起始位開始處必定會有一個下跳沿,由此就能夠標誌一個字符傳輸的起始。而根據起始位和中止位也就很容易的實現了字符的界定和同步。

  顯然,採用異步通訊時,發送端和接收端能夠由各自的時鐘來控制數據的發送和接收,這兩個時鐘源彼此獨立,能夠互不一樣步。

  下面簡單的說說異步通訊的數據發送和接收過程。

 1.2.1 異步通訊的數據格式

   在介紹異步通訊的數據發送和接收過程以前,有必要先弄清楚異步通訊的數據格式。

異步通訊規定傳輸的數據格式由起始位(start bit)、數據位(data bit)、奇偶校驗位(parity bit)和中止位(stop bit)組成,如圖1-1所示(該圖中未畫出奇偶校驗位,由於奇偶檢驗位不是必須有的,若是有奇偶檢驗位,則奇偶檢驗位應該在數據位以後,中止位以前)。

圖1-1 異步通訊數據格式

  (1)起始位:起始位必須是持續一個比特時間的邏輯0電平,標誌傳輸一個字符的開始,接收方可用起始位使本身的接收時鐘與發送方的數據同步。

  (2)數據位:數據位緊跟在起始位以後,是通訊中的真正有效信息。數據位的位數能夠由通訊雙方共同約定,通常能夠是5位、7位或8位,標準的ASCII碼是0~127(7位),擴展的ASCII碼是0~255(8位)。傳輸數據時先傳送字符的低位,後傳送字符的高位。

  (3)奇偶校驗位:奇偶校驗位僅佔一位,用於進行奇校驗或偶校驗,奇偶檢驗位不是必須有的。若是是奇校驗,須要保證傳輸的數據總共有奇數個邏輯高位;若是是偶校驗,須要保證傳輸的數據總共有偶數個邏輯高位。

舉例來講,假設傳輸的數據位爲01001100,若是是奇校驗,則奇校驗位爲0(要確保總共有奇數個1),若是是偶校驗,則偶校驗位爲1(要確保總共有偶數個1)。

因而可知,奇偶校驗位僅是對數據進行簡單的置邏輯高位或邏輯低位,不會對數據進行實質的判斷,這樣作的好處是接收設備可以知道一個位的狀態,有可能判斷是否有噪聲干擾了通訊以及傳輸的數據是否同步。

  (4)中止位:中止位能夠是是1位、1.5位或2位,能夠由軟件設定。它必定是邏輯1電平,標誌着傳輸一個字符的結束。

  (5)空閒位:空閒位是指從一個字符的中止位結束到下一個字符的起始位開始,表示線路處於空閒狀態,必須由高電平來填充。

 1.2.2 異步通訊數據發送過程

  清楚了異步通訊的數據格式以後,就能夠按照指定的數據格式發送數據了,發送數據的具體步驟以下:

  (1)初始化後或者沒有數據須要發送時,發送端輸出邏輯1,能夠有任意數量的空閒位。

  (2)當須要發送數據時,發送端首先輸出邏輯0,做爲起始位。

  (3)接着就能夠開始輸出數據位了,發送端首先輸出數據的最低位D0,而後是D1,最後是數據的最高位。

  (4)若是設有奇偶檢驗位,發送端輸出檢驗位。

  (5)最後,發送端輸出中止位(邏輯1)。

  (6)若是沒有信息須要發送,發送端輸出邏輯1(空閒位),若是有信息須要發送,則轉入步驟(2)。

 1.2.3 異步通訊數據接收過程

  在異步通訊中,接收端以接收時鐘和波特率因子決定每一位的時間長度。下面以波特率因子等於16(接收時鐘每16個時鐘週期使接收移位寄存器移位一次)爲例來講明。

  (1)開始通訊,信號線爲空閒(邏輯1),當檢測到由1到0的跳變時,開始對接收時鐘計數。

  (2)當計到8個時鐘的時候,對輸入信號進行檢測,若仍然爲低電平,則確認這是起始位,而不是干擾信號。

  (3)接收端檢測到起始位後,隔16個接收時鐘對輸入信號檢測一次,把對應的值做爲D0位數據。

  (4)再隔16個接收時鐘,對輸入信號檢測一次,把對應的值做爲D1位數據,直到所有數據位都輸入。

  (5)檢驗奇偶檢驗位。

  (6)接收到規定的數據位個數和校驗位以後,通訊接口電路但願收到中止位(邏輯1),若此時未收到邏輯1,說明出現了錯誤,在狀態寄存器中置「幀錯誤」標誌;若沒有錯誤,對所有數據位進行奇偶校驗,無校驗錯時,把數據位從移位寄存器中取出送至數據輸入寄存器,若校驗錯,在狀態寄存器中置「奇偶錯」標誌。

  (7)本幀信息所有接收完,把線路上出現的高電平做爲空閒位。

  (8)當信號再次變爲低時,開始進入下一幀的檢測。

  以上就是異步通訊中數據發送和接收的全過程了。

 

2、 串口接頭簡介

  經常使用的串口接頭有兩種,一種是9針串口(簡稱DB-9),一種是25針串口(簡稱DB-25)。每種接頭都有公頭和母頭之分,其中帶針狀的接頭是公頭,而帶孔狀的接頭是母頭。9針串口的外觀如圖2所示。

 

圖2-1 DB-9 外觀圖

  由圖2-1能夠看出,在9針串口接頭中,公頭和母頭的管腳定義順序是不同,這一點須要特別注意。那麼,這些管腳都有什麼做用呢?9針串口和25針串口經常使用管腳的功能說明如圖2-2所示。

圖2-2 9針串口和25針串口經常使用管腳功能說明

 

3、 串口通訊接口標準

  基本概念:

  (1)單工模式:(Simplex Communication)的數據傳輸是單向的。通訊雙方中,一方固定爲發送端,一方則固定爲接收端。信息只能沿一個方向傳輸,使用一根傳輸線。

  (2)半雙工模式:(Half Duplex)通訊使用同一根傳輸線,既能夠發送數據又能夠接收數據,但不能同時進行發送和接收。數據傳輸容許數據在兩個方向上傳輸,可是,在任什麼時候刻只能由其中的一方發送數據,另外一方接收數據。所以半雙工模式既可使用一條數據線,也可使用兩條數據線。半雙工通訊中每端需有一個收發切換電子開關,經過切換來決定數據向哪一個方向傳輸。由於有切換,因此會產生時間延遲,信息傳輸效率低些。

  (3)全雙工模式:(Full Duplex)通訊容許數據同時在兩個方向上傳輸。所以,全雙工通訊是兩個單工通訊方式的結合,它要求發送設備和接收設備都有獨立的接收和發送能力。在全雙工模式中,每一端都有發送器和接收器,有兩條傳輸線,信息傳輸效率高。

  顯然,在其它參數都同樣的狀況下,全雙工比半雙工傳輸速度要快,效率要高。

 1. RS-232標準

   RS232是計算機與通訊工業應用中最普遍一種串行接口。它以全雙工方式工做,須要地線、發送線和接收線三條線。RS232只能實現點對點的通訊方式。

 1.1 RS232串口缺點

    ●接口信號電平值較高,接口電路芯片容易損壞。
    ●傳輸速率低,最高波特率19200bps。
    ●抗干擾能力較差。
    ●傳輸距離有限,通常在15m之內。
    ●只能實現點對點的通信方式。

 1.2 RS232串口接口定義:

  RXD:接收數據,TXD:發送數據,GND/SG:信號地。

 

 2. RS-485標準

 2.1 RS-485串口特色

    ●RS485採用平衡發送和差分接收,具備良好的抗干擾能力,信號能傳輸上公里。
    ●RS485有兩線制和四線制兩種接線。採用四線制時,只能實現點對多的通信(即只能有一個主設備,其他爲從設備)。四線制如今不多采用,如今多采用兩線制接線方式。
    ●兩線制RS485只能以半雙式方式工做,收發不能同時進行。
    ●RS485在同一總線上最多能夠接32個結點,可實現真正的多點通信,但通常採用的是主從通訊方式,即一個主機帶多個從機。
    ●因RS485接口具備良好的抗干擾能力,長的傳輸距離和多站能力等優勢使其成爲首選的串行接口。

 2.2 RS-485抑制共模干擾

   

 2.3 RS-485串口接口定義

  A 或 Data+(D+) 或 +:信號正;
  B 或 Data-(D-) 或 -:信號負

 2.4 計算機與RS485儀表通信

  計算機自帶的串口只有RS232,沒有RS485,若是計算機要與RS485串口的儀表進行通信,必須使用串口轉換器或裝上RS485串口轉換卡後才能進行通信。
  2.4.1 RS485串口的終端電阻
    ●通常狀況下不須要增長終端電阻,只有在RS485通訊距離超過100米的狀況下,要在RS485通信的開始端和結束端增長終端電阻,RS485典型終端電阻是120歐。
    ●終端電阻是爲了消除在通訊電纜中的信號反射在通訊過程當中,有兩種信號因致使信號反射:阻抗不連續和阻抗不匹配。

    阻抗不連續,信號在傳輸線末端忽然遇到電纜阻抗很小甚至沒有,信號在這個地方就會引發反射。消除這種反射的方法,就必須在電纜的末端跨接一個與電纜的特性阻抗一樣大小的終端電阻,使電纜的阻抗連續。因爲信號在電纜上的傳輸是雙向的,所以,在通信電纜的另外一端可跨接一個一樣大小的終端電阻。
    引發信號反射的另外一緣由是數據收發器與傳輸電纜之間的阻抗不匹配。這種緣由引發的反射,主要表如今通信線路處在空閒方式時,整個網絡數據混亂。要減弱反射信號對通信線路的影響,一般採用噪聲抑制和加偏置電阻的方法。在實際應用中,對於比較小的反射信號,爲簡單方便,常常採用加偏置電阻的方法。

 

4、串口通信硬件常見的注意事項

    ●通信電纜端子必定接牢,不可有任何鬆動,不然,可能會燒壞儀表或上位機的通信板。
    ●不可帶電拔插通信端子,不然,可能會燒壞儀表或上位機的通信板,必定要關閉儀表電源後才能去拔插通信端子或接通信線。
    ●通信用的屏蔽電纜最好選用雙層隔離型屏蔽電纜,其次選用單層屏蔽電纜,最好不要選用無屏蔽層的電纜,且電纜屏蔽層必定要能徹底屏蔽,有些質量差的電纜,屏蔽層很鬆散,根本起不到屏蔽的做用。單層屏蔽的電纜屏蔽層應一端接地,雙層屏蔽的電纜屏蔽層其外層(含鎧裝)應兩端接地,內層屏蔽則應一端接地。
    ●儀表使用RS232通信時,通信電纜長度不得超過15米。
    ●通常RS485協議的接頭沒有固定的標準,可能根據廠家的不一樣引腳順序和管腳功能可能不盡相同,用戶能夠查閱相關產品RS485的引腳圖。
    ●RS485通信電纜最好選用阻阬匹配、低衰減的RS485專用通信電纜(雙絞線),不要使用普通的雙絞電纜或質量較差的通信電纜。由於普通電纜或質量差的通信電纜,可能阻抗不匹配、衰減大、絞合度不夠、屏蔽層太鬆散,這樣會致使干擾將很是大,會形成通信不順暢,甚至通信不上。
    ●儀表使用RS485通信時,每臺儀表必須手牽手地串下去,不能夠有星型鏈接或者分叉,若是有星型鏈接或者分叉,干擾將很是大,會形成通信不順暢,甚至通信不上。

    

    ●485總線結構理論上傳輸距離達到1200米,通常是指通信線材優質達標,波特率9600,只有一臺485設備才能使得通信距離達到1200米,並且能通信並不表明每次通信都正常,因此一般485總線實際的穩定通信距離遠遠達不到1200米。負載485設備多,線材阻抗不一樣時,通信距離更短。
    ●儀表使用RS485通信時,必要時,請接入終端電阻,以加強系統的抗干擾性,典型的終端電阻阻值是120歐。

 

5、串口通信軟件設置要點

 1. 通信的一些基本概念
    ●主機與從機:在通信系統中起主要做用、發佈主要命令的稱爲主機,接收命令的稱爲從機。
    ●連續方式:指主機不須要發佈命令,從機就能自動地向主機發送數據。
    ●指令方式:指主機向從機發布命令,從機根據指令執行動做,並將結果「應答」給主機的模式。
    ●輸出數據類型:指在連續方式通信時,從機輸出給主機的數據類型。
    ●通信協議:指主機與從機通信時,按哪種編碼規則來通信。
    ●波特率:主從機之間通信的速度。
    ●數據位:每次傳輸數據時,數據由幾位組成。
    ●校驗位:數據傳輸錯誤檢測,能夠是奇校驗、偶校驗或無校驗。
    ●地址:每一臺從機的編號。

 2. 主從機之間通信設置要點
    ●要點一:主/從RS232/485硬件有無設置正確,通信線有無接對。有些通信板卡是RS422與RS485共用的,依靠板上跳線來實現的,有些儀表RS232/485也須要通信跳線來實現。
    ●要點二:主機上的通信端口有無設置正確;超時(通常設置爲2s)、通信延時(通常設置爲5~20ms)、ACK信號延時(通常設置爲0ms)有無設置正確。
    ●要點三:主/從機通信協議有無選擇正確。
    ●要點四:主/從機波特率有無選擇正確。
    ●要點五:主/從機數據位有無選擇正確。數據位能夠選擇7位,8位。
    ●要點六:主/從機校驗位有無選擇正確。校驗位通常可選擇偶校驗、奇校驗、無校驗。
    ●要點七:主/從機中止位有無選擇正確。中止位能夠選擇1位、1.5位仍是2位。
    ●要點八:從機地址有無選擇正確。
    ●要點九:主/從機的通信方式有無選擇正確。

 

PS:進行通信測試的時候常常會進行線路測試,測試所用的串口線是否可用,方法有二以下:
  (1)  把串口線接到不一樣的串口,用串口調試工具從一個串口發數據,另外一個能正常收到說明串口線是OK的。
  (2)  把串口線的一端短接(用金屬把2,3號腳連通),用萬用表測另外一端的2,3號若是正常的話會有嘀嘀的短接報警聲。
 
 
參考來源:依舊淡然->串口通信與編程01:串口基礎知識  http://www.cnblogs.com/menlsh/archive/2013/01/28/2880580.html
 
 
 
 

附:模擬串口代碼

1. 模擬串口底層驅動:

/************************************************************** * 函數名:UART_Analog_Init * 描 述:模擬串口初始化函數 * 說 明:初始化I/O配置,包括TX,RX,RE(RS-485使能),初始化 定時器。 **************************************************************/
void UART_Analog_Init(void) {    }

 

/************************************************************** * 函數名:anal_WByte * 描 述:發送一個字節數據 * 輸 入:unsigned char Byt,須要發送的字節。 * 說 明:串口發送標誌位置一,初始化發送位計數,傳遞要發送的字節 重裝波特率,啓動定時器。 **************************************************************/
void anal_WByte(unsigned char Byt)            // 發送一個字節
{ f_Uart_TX = 1;                    // 發送標誌位置一
    bitcount = 10;                    // 發送位計數
    anal_Sent_Byte = Byt;        // 傳遞要發送的字節數據
 TIMER_STOP; TIMR_SETPERIOD = BAUD_RATE_4800;            // 重裝波特率時鐘
    TIMER_START;                    // 啓動定時器
}

 

/************************************************************** * 函數名:anal_Uart_Send_Data * 描 述:發送Len個字節數據 * 輸 入:unsigned char *buf,要發送的數據; unsigned char Len,要發送數據的個數。 * 說 明:字發送完成(字發送標誌位清零)後,裝載下一個字節數據, 當裝載字節數超過要發送數據的個數,則字符串發送完成, 字符串發送完成標誌位置一。 **************************************************************/
void anal_Uart_Send_Data(unsigned char *buf,unsigned char Len)            // 發送一串字符
{ static unsigned char b_anal_Send_Count = 0;            // 發送字節計數
    if(!f_Uart_Byte_W)            // 字發送完成標誌位
 { if(b_anal_Send_Count >= Len) { b_anal_Send_Count = 0; f_Uart_W = 1;            // 字符串發送完成標誌位
 } else { f_Uart_Byte_W = 1; anal_WByte(buf[b_anal_Send_Count]); b_anal_Send_Count++; } } }

 

/************************************************************** * 函數名:anal_RData * 描 述:啓動串口接收數據。 * 說 明:串口發送標誌位清零,字符串接收完成標誌位清零,打開 串口接收中斷。開始檢測接收數據。 **************************************************************/
void anal_RData(void) { f_Uart_TX = 0;            // 串口發送標誌位清零
    f_Uart_R = 0;                // 字符串接收完成標誌位清零
    EXTI_OPEN(UART_RX_PIN);            // 打開串口接收中斷
}

 

/************************************************************** * 函數名:anal_Uart_Receive_Data * 描 述:字符串接收校驗函數 * 輸 入:unsigned char b_Receive,接收到的字節。 * 說 明:接收一個字節數據,傳遞給串口接收寄存器,判斷數據正確 則下標加1,若是判斷錯誤(或字節接收超時錯誤,20ms)則 下標歸零,直到完成整個字符串的接收。進行數據和校驗檢測, 檢測經過則字符串接收完成標誌位置一。 **************************************************************/
void    anal_Uart_Receive_Data(unsigned char b_Receive) { unsigned char b_Sum,i; if(!b_Time_UART_Byte)            // 字節接收超時錯誤,20ms
 { b_anal_Recieve_Count = 0; } b_Time_UART_Byte = 20; b_anal_RecieveBuf[b_anal_Recieve_Count] = b_Receive; switch(b_anal_Recieve_Count) { case 0: if(b_anal_RecieveBuf[0] == 0xAA)            // 判斷幀頭:0xAA
 { b_anal_Recieve_Count ++; } else { b_anal_Recieve_Count = 0; } break; case 1: if(b_anal_RecieveBuf[1] == 0x11)            // 判斷標誌位:0x11
 { b_anal_Recieve_Count ++; } else { b_anal_Recieve_Count = 0; } break; case 2: if(b_anal_RecieveBuf[2] <= 24)            // 判斷數據長度
 { b_anal_Recieve_Count ++; } else { b_anal_Recieve_Count = 0; } break; default: if(b_anal_Recieve_Count < b_anal_RecieveBuf[2]) { if(++b_anal_Recieve_Count >= b_anal_RecieveBuf[2]) { b_Sum = 0; for(i=0; i < b_anal_RecieveBuf[2]-1; i++) { b_Sum += b_anal_RecieveBuf[i]; i=i; } if(b_anal_RecieveBuf[b_anal_RecieveBuf[2]-1] == b_Sum)        // 和校驗檢測
 { b_anal_Recieve_Count = 0; f_Uart_R = 1;                                // 字符串接收完成標誌位置一
                        TIMER_STOP;                                    // 關閉定時器
                        EXTI_CLOSE(UART_RX_PIN);        // 關閉串口中斷
 } else { b_anal_Recieve_Count = 0; } } } else { b_anal_Recieve_Count = 0; } break; } }

 

/************************************************************** * 函數名:UART_TIMER_Handler * 描 述:串口定時器中斷函數 * 說 明:發送一字節數據或接收一字節數據,詳見函數! **************************************************************/
void UART_TIMER_Handler(void) { uint32_t tmp; static unsigned char b_buf; TIMR_INTClr; // 清除中斷
    if(f_Uart_TX)                    // 發送一字節數據
 { bitcount--; if(bitcount == 9)                // 起始位(1)
 { UART_TX_0; } else if(bitcount>0) { if(anal_Sent_Byte&0x01)            // 數據位(8):低位在前,高位在後
 { UART_TX_1; } else { UART_TX_0; } anal_Sent_Byte=anal_Sent_Byte>>1; } else if(bitcount == 0)            // 中止位(1)
 { UART_TX_1; f_Uart_Byte_W = 0;                // 發送字節標誌位
            TIMER_STOP;                                // 關閉定時器
 } } else                // 接收一字節數據
 { bitcount--; if(bitcount == 9)            // 起始位(1):
 { TIMER_STOP; if(!Read_RX) { TIMR_SETPERIOD = UART_Analog_BAUD_RATE;            // 檢測起始位正確,重裝波特率
 TIMER_START; } } else if(bitcount>0)            // 數據位(8):低位在前,高位在後
 { b_buf >>=1; if(Read_RX) { b_buf |=0x80;                // 接收數據
 } } else if(bitcount==0)        // 中止位(1):
 { TIMER_STOP; // 關閉定時器
            EXTI_OPEN(UART_RX_PIN);                    // 打開接收中斷
            if(Read_RX) { anal_Uart_Receive_Data(b_buf); // 檢驗該字節數據
 } } } }

 

/************************************************************** * 函數名:GPIOE_Handler * 描 述:串口接收中斷函數 * 說 明:降低沿觸發中斷,濾波時間可修改。初始化接收位計數,重裝 半週期波特率,做起始位校驗。 **************************************************************/
void GPIOE_Handler(void) { if(EXTI_INTSTATUS(UART_RX_PIN))            // 判斷中斷位
 { EXTI_CLEAR(UART_RX_PIN); // 清中斷標誌位
        delay_us(10);            // 濾波:10us
        if(!Read_RX)            // 判斷起始位
 { bitcount=10;        //n初始化接收位計數
            TIMER_STOP;            // 關閉定時器
            TIMR_SETPERIOD = BAUD_RATE_4800/2;            // 重裝半個週期波特率,檢測起始位
            TIMER_START;                    // 啓動定時器
            EXTI_CLOSE(UART_RX_PIN);        // 關閉串口中斷 
 } } }

 

 2. 串通信:

/******************************************************************** * 函數名:Uart * 描 述:模擬串口收發控制函數 * 說 明:被動模式,接收正確數據後,返回數據。 控制流程:初始化->接收數據->數據解碼->發送數據打包->發送數據->初始化 c_Uart_Recieve_Init:模擬串口接收數據初始化,接收數據前準備。 c_Uart_anal_Recieve:模擬串口接收數據等待。接收超時錯誤判斷。 c_Uart_anal_Decode:模擬串口接收數據解碼。 c_Uart_anal_Load:模擬串口發送數據加載。 c_Uart_anal_Send:模擬串口發送數據。 c_Uart_anal_Send_Wait:模擬串口發送數據等待。 ********************************************************************/
void    Uart(void) { switch(b_Uart_Progress) { case c_Uart_Recieve_Init:            // 接收初始化
 { b_Uart_Progress = c_Uart_anal_Recieve; w_UART_Wait_Time = 100;                // 接收超時,時間:100ms
            REDE_CLR;            // 接收使能 
 anal_RData(); }break; case c_Uart_anal_Recieve:            // 接收數據
 { if(f_Uart_R)            // 接收數據完成
 { e_anal_Uart_Count = 0;        // 清接收超時錯誤計數
                e_anal_UART = 0;                    // 清接收超時錯誤標誌位
                b_Uart_Progress = c_Uart_anal_Decode; EXTI_CLOSE(UART_RX_PIN); // 接收成功轉發送,並關閉接收中斷
 } else if(!w_UART_Wait_Time)        // 接收超時
 { b_Uart_Progress = c_Uart_Recieve_Init; if(++e_anal_Uart_Count >= 5)        // 接收超時錯誤計數>=5次,判斷爲接收超時錯誤
 { e_anal_UART = 1;        // 接收超時錯誤
 } } }break; case c_Uart_anal_Decode:            // 接收數據解碼
 { anal_Uart_Decode(); // 解碼函數
            b_Uart_Progress = c_Uart_anal_Load; }break; case c_Uart_anal_Load:            // 發送數據加載
 { anal_Uart_Load_Data(); // 加載發送數據函數
            f_Uart_W = FALSE;                    // 清發送字符串完成標誌位
            REDE_SET;            // 發送使能
            b_Uart_Progress = c_Uart_anal_Send; }break; case c_Uart_anal_Send:            // 發送數據
 { anal_Uart_Send_Data(b_anal_SendBuf,20);            // 發送數據
            if(f_Uart_W) { b_Uart_Progress = c_Uart_anal_Send_Wait; w_UART_Wait_Time = 1; } }break; case c_Uart_anal_Send_Wait:            // 發送線控板數據等待
 { if(!w_UART_Wait_Time) { b_Uart_Progress = c_Uart_Recieve_Init; } }break; default: b_Uart_Progress = c_Uart_Recieve_Init; break; } }

 

/************************************************************** * 函數名:anal_Uart_Decode * 描 述:模擬串口接收數據解碼 * 說 明:模擬串口接收數據提取並賦值到相應寄存器。 **************************************************************/
void    anal_Uart_Decode(void)            // 解碼
{ /**** 控制標誌位清零 **** _System_Ctrl.byte = 0x00; f_Open_Air_Con = FALSE; // 空調開機 f_Open_Fan = FALSE; // 室外風機控制 f_Open_YJ = FALSE; // 室內機要求開壓縮機 **** 控制位賦值 **** f_System_Run = b_Recieve_Data[3] & 0x01; f_Manual_Heater = b_Recieve_Data[3]>>1 & 0x01; f_Sys_Calorifier = b_Recieve_Data[3]>>4 & 0x01; f_System_SFS = b_Recieve_Data[3]>>5 & 0x01; f_System_CSS = b_Recieve_Data[3]>>6 & 0x01; */ }

 

 

/************************************************************** * 函數名:anal_Uart_Load_Data * 描 述:模擬串口發送數據打包 * 說 明:模擬串口發送數據加載,包括校驗等。 **************************************************************/
void    anal_Uart_Load_Data(void)            // 裝載數據
{ unsigned char b_Sum,i; b_anal_SendBuf[0] = 0xAA;        // 幀頭
    b_anal_SendBuf[1] = 0x11;        // 識別碼 
    /* b_anal_SendBuf[2] = ; // 數據長度 b_anal_SendBuf[3] = ; // 數據 ··· */ b_Sum = 0; for(i=0;i <= (b_anal_SendBuf[2]-2);i++) { b_Sum += b_anal_SendBuf[i]; } b_anal_SendBuf[b_anal_SendBuf[2]-1] = b_Sum;            // 和校驗
}
相關文章
相關標籤/搜索