下面我們還是用兩塊Arduino來實(shí)踐一下如何利用I2C協(xié)議來傳輸數(shù)據(jù)。如圖連接好兩塊Arduino:
一臺我們作為主設(shè)備(Master),燒錄以下代碼:
#include
void setup() {
Serial.begin(9600); /* begin serial comm. */
Wire.begin(); /* join i2c bus as master */
Serial.println("I am I2C Master");
}
void loop() {
Wire.beginTransmission(8); /* begin with device address 8 */
Wire.write("Hello Slave"); /* sends hello string */
Wire.endTransmission(); /* stop transmitting */
Wire.requestFrom(8, 9); /* request & read data of size 9 from slave */
while(Wire.available()){
char c = Wire.read();/* read data received from slave */
Serial.print(c);
}
Serial.println();
delay(1000);
}
另一塊作為從設(shè)備(Slave),燒錄以下代碼:
#include
void setup() {
Wire.begin(8); /* join i2c bus with address 8 */
Wire.onReceive(receiveEvent); /* register receive event */
Wire.onRequest(requestEvent); /* register request event */
Serial.begin(9600); /* start serial comm. */
Serial.println("I am I2C Slave");
}
void loop() {
delay(100);
}
// function that executes whenever data is received from master
void receiveEvent(int howMany) {
while (0 char c = Wire.read(); /* receive byte as a character */
Serial.print(c); /* print the character */
}
Serial.println(); /* to newline */
}
// function that executes whenever data is requested from master
void requestEvent() {
Wire.write("Hi Master"); /*send string on request */
}
這樣,我們就實(shí)現(xiàn)了主從設(shè)備的雙向傳輸。打開主機(jī)Arduino的串口監(jiān)視器我們可以看見如下的輸出:
從機(jī)Arduino的串口輸出:
I2C雖然只需要兩根線,就能支持多主機(jī)多從機(jī)的數(shù)據(jù)傳輸,但由于只有一根用于數(shù)據(jù)傳輸,它通過在“接收”和“傳輸”兩種狀態(tài)之間但切換實(shí)現(xiàn)了雙向傳輸,但犧牲了不少傳輸速率。I2C還有典型的開漏問題,總線需要加上拉電阻。
SPI協(xié)議
最后,我們來看一下SPI協(xié)議。SPI全稱Serial Peripheral Interface(串行外設(shè)接口),由摩托羅拉公司提出的一種同步串行數(shù)據(jù)傳輸協(xié)議。SPI類似I2C也是同步通信的協(xié)議,但是全雙工,支持?jǐn)?shù)據(jù)的同時(shí)輸出和輸入。這兩個(gè)特征使SPI的傳輸速率比UART和I2C都高,這對于像SD卡、或者屏幕等數(shù)據(jù)型模塊來說,是非常具有優(yōu)勢的。
SPI支持一主多從的模式,但SPI也是三種協(xié)議中需要線最多的協(xié)議,一共需要4條信號線:
但Arduino UNO默認(rèn)的SPI引腳分別為D13(SCK), D12(MISO), D11(MOSI), D10(SS),其中SS是從機(jī)選擇引腳,沒有強(qiáng)制要求,你也可以選其他的引腳。
同樣,我們來實(shí)踐一下用SPI實(shí)現(xiàn)數(shù)據(jù)傳輸。
如圖連接好兩塊Arduino UNO。還是一塊作為主機(jī)(Master), 另一塊作為從機(jī)(Slave)。Arduino對SPI協(xié)議也做了類封裝:
https://www.arduino.cc/en/reference/SPI
主機(jī)燒錄以下代碼:
#include
void setup (void)
{
Serial.begin(115200);
digitalWrite(SS, HIGH);
SPI.begin ();
SPI.setClockDivider(SPI_CLOCK_DIV8);
}
void loop (void)
{
char c;
// enable Slave Select
digitalWrite(SS, LOW); // SS is pin 10
// send test string
for (const char * p = "Hello, world!\\n" ; c = *p; p++) {
SPI.transfer (c);
Serial.print(c);
}
// disable Slave Select
digitalWrite(SS, HIGH);
delay (1000);
}
從機(jī)燒錄:
#include
char buf [100];
volatile byte pos;
volatile boolean process_it;
void setup (void)
{
Serial.begin (115200); // debugging
// turn on SPI in slave mode
SPCR |= bit (SPE);
// have to send on master in, *slave out*
pinMode(MISO, OUTPUT);
// get ready for an interrupt
pos = 0; // buffer empty
process_it = false;
// now turn on interrupts
SPI.attachInterrupt();
} // end of setup
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR; // grab byte from SPI Data Register
// add to buffer if room
if (pos < sizeof buf)
{
buf [pos++] = c;
// example: newline means time to process buffer
if (c == '\\n')
process_it = true;
} // end of room available
} // end of interrupt routine SPI_STC_vect
// main loop - wait for flag set in interrupt routine
void loop (void)
{
if (process_it)
{
buf [pos] = 0;
Serial.println(buf);
pos = 0;
process_it = false;
} // end of flag set
} // end of loop
這樣從機(jī)就能接受到主機(jī)發(fā)過來的消息了。
總結(jié)
今天,我們粗略地介紹了一下Arduino數(shù)據(jù)通信中最常用的三種協(xié)議:UART、I2C和SPI。
| **協(xié)議
** | **通信方式
** | **通信方向
** | **信號線
** | **傳輸速率
** | **主從模式
** | |||||
---|---|---|---|---|---|
UART | |||||
異步 | |||||
全雙工 | 2線RX、TX | 最低 | |||
一對一 | |||||
I2C | |||||
同步 | |||||
半雙工 | |||||
2線SDA、SCL,以地址選擇從機(jī) | 低 | ||||
多主機(jī)多從機(jī) | |||||
SPI | |||||
同步 | |||||
全雙工 | 4線MOSI、MISO、SCLK、CS(或SS),以CS選擇從機(jī) | 高 | |||
一主多從 | |||||
它們各自都有自己的優(yōu)缺點(diǎn)和適用的場景,并沒有絕對的好壞,這也是這三種協(xié)議經(jīng)久不衰的原因。只有了解并掌握它們,我們才能在具體的應(yīng)用場景里選擇最合適的協(xié)議。當(dāng)然在嵌入式世界里,還有其他很多協(xié)議,小編以后再介紹吧。如果對這三種協(xié)議的底層感興趣的朋友,也可以自己再去深入了解。
-
SPI
+關(guān)注
關(guān)注
17文章
1707瀏覽量
91627 -
I2C
+關(guān)注
關(guān)注
28文章
1488瀏覽量
123831 -
uart
+關(guān)注
關(guān)注
22文章
1237瀏覽量
101426
發(fā)布評論請先 登錄
相關(guān)推薦
評論