Arduino(3) Mega2560和外部設備SPI通信

前言

這篇文章主要講Arduino串行通信裏的SPI通信。SPI(Serial Peripheral Interface,串行外設接口)高速通信接口一般用在於對於數據量要求比較大的設備或者場景裏,例如SD卡,網絡芯片,而Arduino支持SPI總線,從而可以和一些使用SPI總線的設備通信,一根SPI總線上可以連接多個SPI從設備。

SPI設置

  • 在一個SPI設備中,通常會有4個引腳。SPI總線有主從機之分,主機負責輸出時鐘信號及選擇通信的從設備。時鐘信號會通過主機的SCK引腳輸出,提供給通信從機使用。而從機的選擇由從機CS引腳來決定,CS引腳爲低電平時,該從機被選中,CS引腳拉高,該從機被斷開。數據的收發則通過MISO和MOSI引腳進行。Arduino Mega2560開發板上引腳位置分別爲:MOSI–51腳,MISO–50腳,SCK–52腳,SS–53腳。或者利用6針的ICSP引腳來使用SPI總線。
    MISO(Master In Slave Out):主機數據輸入,從機數據輸出
    MOSI(Master Out Slave In):主機數據輸出,從機數據輸入
    SCK(Serial Clock):用於通信同步的時鐘信號,由主機產生
    SS(Slave Select)或CS(Chip Select):從機使能信號,由主機控制

SPI類庫成員函數

1. SPI.begin()

初始化SPI通信,調用該函數後,SCK/MOSI/SS引腳將被設置爲輸出模式,且SCK/MOSI引腳拉低,SS引腳拉高。

2. SPI.end()

關閉SPI總線通信

3. SPI.setBitOrder(order)

設置傳輸順序。order:傳輸順序,LSBFIRST,低位在前;MSBFIRST,高位在前

4. SPI.setClockDivider(divider)

設置通信時鐘,由主機產生,從機不用配置。divider:SPI通信的系統時鐘分頻得到,可選配置有SPI_CLOCK_DIV2、SPI_CLOCK_DIV4(默認配置)等,最大可達128分頻

5. SPI.setDataMode(mode)

設置數據模式。mode:可配置的模式,可選項有SPI_MODE0、SPI_MODE1、SPI_MODE2、SPI_MODE3

6. SPI.transfer(val)

傳輸1Byte的數據,SPI是全雙工通信,所以發送1B的數據,也會接收到1B的數據。val:要發送的字節數據。

SPI通信示例

  • 下面這個例子是我用Arduino通過SPI通信控制下變頻模塊產生兩級變頻。這裏有兩個SPI從設備PLL1和PLL2,所以這裏我需要重新定義SPI從設備的使能引腳,如下圖代碼中所示,PLL1定義爲47腳,PLL2定義爲48腳;SCK腳則使用Mega2560默認的52引腳;因爲我這裏只需要從Arduino發送數據到從設備,並不需要從設備裏讀取數據,所以我只使用到了MOSI 51引腳,MISO引腳就不需要使用。剩下的就是將各個引腳和從設備上對應的引腳相連就行了。如果只有一個從設備的話,可以直接使用Mega2560上默認的SPI引腳。
#include <SPI.h>                 //引入SPI類庫
const int PLL1 = 47;             //定義SPI從設備的使能引腳
const int PLL2 = 48;

//因爲篇幅原因,這裏PLL寄存器的數據接收做了簡化處理,兩個從設備都只發送了一組數據,
//實際上這裏需要發送多組寄存器數據才能使從設備工作,這也是根據不同的外部設備的規格定義去修改的。
//這裏每組4個字節數據
unsigned char PLL1_Reg_buf0[4] = {0x00,0x30,0x1B,0x30};
unsigned char PLL2_Reg_buf0[4] = {0x00,0xBE,0x00,0x00};

void setup() 
{ 
	Serial.begin(9600);
	pinMode(PLL1,OUTPUT);
	pinMode(PLL2,OUTPUT);          //管腳設置爲輸出模式
	digitalWrite(PLL1,HIGH);       //拉高SPI從設備引腳
	digitalWrite(PLL2,HIGH);
	delay(50);
	SPI.setBitOrder(MSBFIRST);     // 最高有效位
	SPI.setDataMode(SPI_MODE0);    // SCK上升沿輸入,下降沿輸出;SCK低電平空閒
	SPI.begin();                   // SCK MOSI SS設爲輸出模式,SCK MOSI拉低,SS拉高
	set_frq(); 
	delay(1000);
}

void loop() 
{ 
}

void WriteToADF4350(unsigned char PLL,unsigned char count, unsigned char *buf)
{
	if(PLL == 1)  digitalWrite(PLL1,LOW);    //拉低電平,選擇對應SPI從設備
	if(PLL == 2)  digitalWrite(PLL2,LOW);
	delay(50);
	unsigned char ValueToWrite = 0;
	unsigned char i = 0;
	for(i=0;i<count;i++)
	{
    	ValueToWrite = *(buf + i);
    	SPI.transfer(ValueToWrite);           // 發送數據到SPI從設備
    }
 	if(PLL == 1)  digitalWrite(PLL1,HIGH);    //拉高電平,釋放對應SPI從設備
 	if(PLL == 2)  digitalWrite(PLL2,HIGH);
  	delay(50);
}

void set_frq(void)
{
	WriteToADF4350(1,4,PLL1_Reg_buf0);
	delay(500);
	WriteToADF4350(2,4,PLL2_Reg_buf0);
	delay(500); 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章