Arduino 串行外設(shè)接口

2018-11-17 19:07 更新

串行外設(shè)接口(SPI)總線是用于串行通信的系統(tǒng),最多可使用四個導體,通常為三個。一個導體用于數(shù)據(jù)接收,一個導體用于數(shù)據(jù)發(fā)送,一個導體用于同步,另一個導體用于選擇與之通信的設(shè)備。它是一個全雙工連接,這意味著數(shù)據(jù)是同時發(fā)送和接收的。最大波特率高于I2C通信系統(tǒng)中的波特率。

板的SPI引腳

SPI使用以下四條線:

  • SCK - 這是由主機驅(qū)動的串行時鐘。

  • MOSI - 這是由主機驅(qū)動的主輸出/從輸入。

  • MISO - 這是由主機驅(qū)動的主輸入/從輸出。

  • SS - 這是從機選擇線。

使用以下函數(shù),必須包括SPI.h.

  • SPI.begin() - 通過將SCK,MOSI和SS設(shè)置為輸出來初始化SPI總線,將SCK和MOSI拉低,將SS拉高。

  • SPI.setClockDivider(分頻器) - 相對于系統(tǒng)時鐘設(shè)置SPI時鐘分頻器。在基于AVR的板上,可用的分頻器為2,4,8,16,32,64或128。默認設(shè)置為SPI_CLOCK_DIV4,它將SPI時鐘設(shè)置為系統(tǒng)時鐘的四分之一(對于20 MHz的電路板為5 Mhz)。

  • Divider - 它可以是(SPI_CLOCK_DIV2,SPI_CLOCK_DIV4,SPI_CLOCK_DIV8,SPI_CLOCK_DIV16,SPI_CLOCK_DIV32,SPI_CLOCK_DIV64,SPI_CLOCK_DIV128)。

  • SPI.transfer(val) - SPI傳輸基于同時發(fā)送和接收:接收的數(shù)據(jù)在receivedVal中返回。

  • SPI.beginTransaction(SPISettings(speedMaximum,dataOrder,dataMode)) - speedMaximum是時鐘,dataOrder(MSBFIRST或LSBFIRST),dataMode(SPI_MODE0,SPI_MODE1,SPI_MODE2或SPI_MODE3)。

SPI中有四種操作模式,如下所示:

  • 模式0(默認值) - 時鐘通常為低電平(CPOL = 0),數(shù)據(jù)在從低電平到高電平(前沿)(CPHA = 0)的轉(zhuǎn)換時采樣。

  • 模式1 - 時鐘通常為低電平(CPOL = 0),數(shù)據(jù)在從高電平到低電平(后沿)(CPHA = 1)的轉(zhuǎn)換時采樣。

  • 模式2 - 時鐘通常為高電平(CPOL = 1),數(shù)據(jù)在從高電平到低電平(前沿)(CPHA = 0)的轉(zhuǎn)換時采樣。

  • 模式3 - 時鐘通常為高電平(CPOL = 1),數(shù)據(jù)在從低電平到高電平(后沿)(CPHA = 1)的轉(zhuǎn)換時采樣。

  • SPI.attachInterrupt(handler) - 當從設(shè)備從主設(shè)備接收數(shù)據(jù)時調(diào)用的函數(shù)。

現(xiàn)在,我們將兩個Arduino UNO板連接在一起;一個作為主機,另一個作為從機。

  • (SS):引腳10
  • (MOSI):引腳11
  • (MISO):引腳12
  • (SCK):引腳13

接地是常見的。以下是兩個電路板之間的連接的圖示:


兩個電路板之間的連接

讓我們看看SPI作為主機和SPI作為從機的例子。

SPI為主機

例子

#include <SPI.h>

void setup (void) {
   Serial.begin(115200); //set baud rate to 115200 for usart
   digitalWrite(SS, HIGH); // disable Slave Select
   SPI.begin ();
   SPI.setClockDivider(SPI_CLOCK_DIV8);//divide the clock by 8
}

void loop (void) {
   char c;
   digitalWrite(SS, LOW); // enable Slave Select
   // send test string
   for (const char * p = "Hello, world!\r" ; c = *p; p++) {
      SPI.transfer (c);
      Serial.print(c);
   }
   digitalWrite(SS, HIGH); // disable Slave Select
   delay(2000);
}

SPI為從機

例子

#include <SPI.h>
char buff [50];
volatile byte indx;
volatile boolean process;

void setup (void) {
   Serial.begin (115200);
   pinMode(MISO, OUTPUT); // have to send on master in so it set as output
   SPCR |= _BV(SPE); // turn on SPI in slave mode
   indx = 0; // buffer empty
   process = false;
   SPI.attachInterrupt(); // turn on interrupt
}
ISR (SPI_STC_vect) // SPI interrupt routine { 
   byte c = SPDR; // read byte from SPI Data Register
   if (indx < sizeof buff) {
      buff [indx++] = c; // save data in the next index in the array buff
      if (c == '\r') //check for the end of the word
      process = true;
   }
}

void loop (void) {
   if (process) {
      process = false; //reset the process
      Serial.println (buff); //print the array on serial monitor
      indx= 0; //reset button to zero
   }
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號