UART、I2C和SPI是嵌入式世界里最常見的三種通信協(xié)議。在閱讀教程,或者購(gòu)買模塊時(shí)常常看見“這個(gè)模塊是用I2C協(xié)議驅(qū)動(dòng)的”, “兩個(gè)設(shè)備之間數(shù)據(jù)走SPI”諸如此類的描述,很多新手覺得是什么高階的知識(shí)就一知半解得略過去略了。今天小編簡(jiǎn)略地為大家介紹一下這三種協(xié)議,以及它們各自的優(yōu)缺點(diǎn)。
什么是通信協(xié)議
白話點(diǎn)說,通信協(xié)議就是通信時(shí)候雙方約定的規(guī)則。打個(gè)類比,就像你跟另外一個(gè)人交流,你們之間需要一種交流的約定,就是語言。要么都說中文,要么都說英文。通信協(xié)議就類似于硬件之間交流的語言。
串行通信和并行通信
在硬件通信里,一般有兩種通信方式:串行通信(Serial Communication)和并行通信(Parallel Communication)。這兩種通信方式的區(qū)別從字面理解也很簡(jiǎn)單:串行就是數(shù)據(jù)一個(gè)接一個(gè)的發(fā)送;并行就是所有數(shù)據(jù)都同時(shí)發(fā)出。
但由于并行通信在線路成本和同步困難方面的問題使其在實(shí)際應(yīng)用上面遠(yuǎn)不如串口通信來得廣泛。本文介紹的UART, I2C和SPI三種通信協(xié)議都屬于串口通信。
單工,半雙工,雙工
根據(jù)串行數(shù)據(jù)的傳輸方向,我們可以將通信分為單工,半雙工,雙工。
-
單工:
是指數(shù)據(jù)傳輸僅能沿一個(gè)方向,不能實(shí)現(xiàn)反向傳輸。
-
半雙工:
是指數(shù)據(jù)傳輸可以沿兩個(gè)方向,但不能同時(shí)進(jìn)行傳輸。
-
全雙工:
是指數(shù)據(jù)可以同時(shí)進(jìn)行雙向傳輸。
同步通信和異步通信
根據(jù)串行數(shù)據(jù)傳輸方式,我們又可以分為:同步通信和異步通信。
同步通信是指發(fā)送端和接收端必須使用同一時(shí)鐘,是一種連續(xù)傳送數(shù)據(jù)的通信方式。由于發(fā)送和接收的雙方都采用同一時(shí)鐘,這樣接收方就可以通過時(shí)鐘信號(hào)來確定每個(gè)信息位。
異步通信不需要雙方使用同一時(shí)鐘,并且它是一種不連續(xù)的傳輸通信方式,一次通信只能傳輸一個(gè)字符數(shù)據(jù)(字符幀)。而字符幀之間的間隙可以是任意的。但由于不知道對(duì)方什么時(shí)候發(fā)送數(shù)據(jù),所以發(fā)送方要在數(shù)據(jù)的開始后結(jié)束都要加一些輔助的信息,比如開始要有起始位,結(jié)束要有結(jié)束位等。
同步通信的通信效率比異步通信高,可以傳輸較大的數(shù)據(jù)量但對(duì)于時(shí)鐘同步要求比較高,而異步通信不需要同步時(shí)鐘,通信實(shí)現(xiàn)簡(jiǎn)單,設(shè)備相對(duì)簡(jiǎn)單,但是傳輸速率不高,某些通訊中還需要雙方約定數(shù)據(jù)的傳輸速率,以便更好地同步。
了解了上面的幾個(gè)基本概念,我們?cè)賮戆磦€(gè)看一看UART、I2C和SPI三種協(xié)議。
UART協(xié)議
UART的全稱叫 Universal Asynchronous Reception and Transmission通用異步收發(fā)。從名字我們就可以知道,UART是異步串行通信的。利用UART協(xié)議傳輸數(shù)據(jù)時(shí),需要兩個(gè)數(shù)據(jù)引腳,一個(gè)用于傳輸數(shù)據(jù)的TX,另一個(gè)用于接收的RX。
Arduino板上默認(rèn)的RX和TX引腳分別是Pin0和Pin1。UART硬件層和軟件層的功能都是Arduino集成的,一般我們不需要從底層操作數(shù)據(jù)。一個(gè)UART口(一組RX和TX)只能連接一個(gè)UART設(shè)備進(jìn)行通信,我們需要這樣就接線:
注意,一個(gè)設(shè)備的TX接的是另一設(shè)備的RX,反之RX接TX,最后需要將兩個(gè)設(shè)備共地,共地是讓它們的參考電壓一致。
下面,我們用兩塊Arduino實(shí)際實(shí)踐一下。如圖連接兩個(gè)Arduino:
我們?cè)贏rduino A里燒錄以下代碼:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
char s[]="I am Arduino A";//每隔1s發(fā)送一次字符數(shù)組s
Serial.print(s);
delay(1000);
}
再在Arduino B里燒錄以下代碼:
String a=""; //定義字符串,接收數(shù)據(jù)
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
while(Serial.available())//當(dāng)發(fā)現(xiàn)緩存中有數(shù)據(jù)時(shí),將數(shù)據(jù)送至字符數(shù)組a中
{
a+=char(Serial.read());
delay(3);
}
if (a.length() > 0){
Serial.println(a)
a = ""
}
}
這樣就A就通過UART向B發(fā)送了“I am Arduino A”消息,B接收到以后輸出。當(dāng)然你可以修改A的代碼實(shí)現(xiàn)雙向數(shù)據(jù)傳輸,這里我們就點(diǎn)到即止了。
UART是最常見的通信協(xié)議之一,它可以實(shí)現(xiàn)全雙工傳輸,但它的傳輸速度比較慢,而且只能支持一對(duì)一的設(shè)備。
I2C協(xié)議
I2C是Philips公司在1980年代發(fā)明的一種協(xié)議,全稱是Inter-Integrated Circuit。I2C最常被應(yīng)用于模塊或者傳感器之間的通信,因?yàn)镮2C基于二根傳輸線,同步通信的半雙工協(xié)議,而且協(xié)議也非常簡(jiǎn)單可靠。I2C使用兩根傳輸線實(shí)現(xiàn)一個(gè)主設(shè)備與多個(gè)從設(shè)備,甚至是多個(gè)主設(shè)備與對(duì)應(yīng)從設(shè)備之間的通信。 這兩根通訊線一根為控制時(shí)鐘線,稱之為SCL,用于同步設(shè)備間的數(shù)據(jù)傳輸時(shí)鐘; 另一根為數(shù)據(jù)線,稱之為SDA,用于攜帶數(shù)據(jù)。理論上,一條I2C總線上能支持掛載128臺(tái)設(shè)備。
Arduino UNO的I2C引腳是A4(SDA), A5(SDL)。Arduino對(duì)I2C協(xié)議也進(jìn)行了庫(kù)封裝:
https://www.arduino.cc/en/Reference/Wire
-
SPI
+關(guān)注
關(guān)注
17文章
1688瀏覽量
91215 -
I2C
+關(guān)注
關(guān)注
28文章
1477瀏覽量
123059 -
uart
+關(guān)注
關(guān)注
22文章
1219瀏覽量
101120
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論