购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.6.9 位操作(SPI口)

位操作用于设置或读取字节中某一位或几位,包括bitRead()、bitSet()、bitClear()等,具体定义及功能可以参考文件wiring.h。

#define lowbyte(w) ((uint8-t) ((w) & 0xff)) //低字节

#define lowbyte(w) ((uint8-t) ((w) >>8)) //高字节

//读bit位的值,即保留 bit位,其他位均清零

#define bitread(value,bit) (((value)>>(bit)) & 0x01)

//置bit位的值,即 bit位置1

#define bitset(value,bit) (((value) |= (1UL<<(bit))

//清除bit位,即bit位置0

#define bitclear(value,bit) (((value) &=-(1UL<<(bit)))

//写bit位的值,1或者0

#define bitwrite(value,bit,bitvalue)(bitvalue?bitset(value,bit):bitclear(value,bit))

1.概述

SPI(Serial Peripheral Interface)是由摩托罗拉公司提出的一种同步串行外设接口总线,它可以使MCU与各种外围设备以串行方式进行通信及交换信息,总线采用3根或4根数据线进行数据传输,常用的是4根线,即两条控制线(芯片CS和时钟SCLK),以及两条数据信号线SDI和SDO。

SPI是一种高速、全双工、同步的通信总线。在摩托罗位公司的SPI技术规范中,数据信号线 SDI 称为 MISO(Master-In-Slave-Out),主入从出,数据信号线 SDO 称为 MOSI(Master-Out-Slave-In,主出从入),控制信号线 CS 称为 SS(Slave-Select,从属选择),将SCLK称为SCK(Serial-Clock,串行时钟)。在SPI通信中,数据是同步进行发送和接收的。数据传输的时钟基于来自主处理器产生的时钟脉冲,摩托罗拉公司没有定义任何通用的SPI时钟规范。

2.SPI口数据传输

SPI是以主从方式工作的,其允许一个主设备和从设备进行通信,主设备通过不同的SS信号线选择不同的从设备进行通信。其典型应用示意图如图1-49所示。

图1-49 SPI总线应用示意图

当主设备选中某一个从设备后,MISO和MOSI用于串行数据的接收和发送,SCK 提供串行通信时钟,上升沿发送,下降沿接收。在实际应用中,未选中的从设备的MOSI信号线需处于高阻状态,否则会影响主设备与选中从设备间的正常通信。

3.SPI类函数

Arduino中的SPI通信是通过SPIClass类来实现的,使用SPIClass类能够方便地将Arduino作为主设备与其他从设备进行通信。SPIClass类提供了6个成员函数供使用者调用,如下:

begin()

setBitOrder()

setClockDivider()

setDataMode()

transfer()

end()

begin函数用于初始化SPI总线,函数原型如下:

void spicLASS::begin()

{

//Set direction register for SCK and MOST pin.

//MISO pin automatically overrides to INPUT.

//When the ss pin ios set as OUTPUT,it can be used as

//a poeneral purpuse output port(it doesn’t influence

//SPIoperations).

pinmode(SCK,OUTPUT);

pinmode(MOSI,OUTPUT);

pinmode(SS,OUTPUT);

digitalWrite(SCK,LOW);

digitalWrite(MOSI,LOW);

digitalWrite(SS,HIGH);

//warnig:if the ss pin ever becomes a LOW INPUT then SPI

//automatically switches to Slave,so the data direction of

//the ss pin NUST be kept as OUTPUT.

SPCR|=-BV(MSTR);

SPCR|=-BV(SPE);

}

setBitOrder 的作用是设置串行数据传输时是先传输低位还是先传输高位,函数有一个type类型的参数bitOrder,有LSBFIRST(最低位在前)和MSBFIRST(最高位在前)两种类型可选。函数无返回值,原型如下:

void SPICLass::setBitOrder(uint8-t bit order)

{

if(bit order==KSVFURST)

{

SPCR|=BC(DORD);

}

else

{

SPCR &=-(-BV(DORD));

}

}

setClockDivder函数的作用是设置SPI串行通信的时钟,通信时钟是由系统时钟分频得到的,分频值可选2、4、8、16、32、64及128,有一个type类型的参数rate,有7种类型,对应7个分频值,分别为 SPI-CLOCK-DIV2、SPI-CLOCK-DIV4、SPI-CLOCK-DIV8、SPI-CLOCK-DVI16、SPI-CLOCK-DIV32、SPI-CLOCKL-DVI64和 ASPI-CLOCK-DVI128。函数默认参数设置是SPI-CLOCK-DVI4,设置SPI串行通信时钟为系统时钟的1/4。函数原型如下:

void spiclass::setclockdivider(uint8-t rate)

{

SPCR=(SPCR& -SPI-CLOCK-MASK)|(rate & SPI-CLOCK-MASK);

SPCR=(SPCR& -SPI-2xCLOCK-MASK)|(rate & SPI-2xCLOCK-MASK);

}

setDataMode函数的作用是设置SPI的数据模式,由于在SPI通信中没有定义任何通用的时钟规范,所以在具体应用中有的在上升沿采样,有的在下降沿采样,由此SPI存在4种数据模式,见表1-9。

表1-9 SPI通信数据模式

setDataMode 函数 type 类型的参数 mode 有4种类型可选,分别是 SPI-MODE0、SPI-MODE1、SPI-MODE2和SPI-MODE3。函数原型如下:

viod spiclass::setdatamode(uint8-t mode)

{

SPCR=(SPCR & -SPI-MODE-MASK)|mode;

}

eranfer函数用来传输一个数据,由于SPI是一种全双工、同步的通信总线,所以传输一个数据实际上会发送一个数据,同时接收一个数据。函数的参数为发送的数据值,返回的参数为接收的数据值。函数原型如下:

byte spiclass::transfer(bytre-data)

{

SPDR= -data;

while(1(SPSR & -BV(SPIF)));

return SPDR;

}

end函数停止SPI总线的使用,函数原型如下:

void SPIClass::end()

{

SPCR &=-BV(SPE));

} r0R/VvYRIQltvYJRSze2tkeUTXg9v5j07ewNvCPM0MNcyfaSAl523+bVbHm//SL4

点击中间区域
呼出菜单
上一章
目录
下一章
×