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); 
}

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