两个Arduino之间进行SPI通信
原文地址:http://www.gammon.com.au/forum/?id=10892最近需要研究一下两台Arduino之间使用SPI通信的例子,搜了一下,只有国外大神们做过这种通讯,我们的坛子上找不到相关的资料,于是我结合自己的研究把这一通讯方式记录下来,给需要的同学们作参考:
使用两块Arduino UNO,一主一从。
Arduino UNO A: SPI 主机
Arduino UNO B: SPI 从机
连线方式:
A--------------------B
(10) SS---------->(10) SS
(11) MOSI------->(11) MOSI
(12) MISO<-------(12) MISO
(13) SCLK------->(13) SCLK
主机从机分别写入如下代码:
从机:
#include <SPI.h>
void setup (void)
{
Serial.begin(9600); // 开始串口通讯
digitalWrite(SS, HIGH);
SPI.begin (); // PI通讯开始
//SPI.setClockDivider(SPI_CLOCK_DIV8); //??
}
void loop (void)
{
char c;
// 片选为从机
digitalWrite(SS, LOW); // SS - pin 10
// 发送字串
for (const char * p = "Hello, world!\n" ; c = *p; p++) {
SPI.transfer (c);
Serial.print(c);
}
// 取消从机
digitalWrite(SS, HIGH);
delay (1000);
}
主机:
#include <SPI.h>
char buf ;
volatile byte pos;
volatile boolean process_it;
void setup (void)
{
Serial.begin (9600);
// have to send on master in, *slave out*
pinMode(MISO, OUTPUT);
// 设置为接收状态
SPCR |= _BV(SPE);
// 准备接受中断
pos = 0; // 清空缓冲区
process_it = false;
// 开启中断
SPI.attachInterrupt();
}
// SPI 中断程序
ISR (SPI_STC_vect)
{
byte c = SPDR;// 从 SPI 数据寄存器获取数据
if (pos < sizeof(buf))
{
buf = c;
if (c == '\n')
process_it = true;
}
}
void loop (void)
{
if (process_it)
{
buf = 0;
Serial.println (buf);
pos = 0;
process_it = false;
}
}
写入后打开各自的串口监视器,就能看到两个Arduino进行字串通信了。 LZ 的"从机:/ 主机:" 代码 与 原文地址 (http://www.gammon.com.au/forum/?id=10892) 的相反 !! hmjack2008 发表于 2013-5-30 18:10 static/image/common/back.gif
LZ 的"从机:/ 主机:" 代码 与 原文地址 (http://www.gammon.com.au/forum/?id=10892) 的相反 !!
好吧,反正能通信就是了~~~ 共地。。。。。一定要共地。。。。 friskit 发表于 2013-6-1 09:35 static/image/common/back.gif
共地。。。。。一定要共地。。。。
不用啊,有SCK就不用共地了,这个我试验过 哈哈,不供地貌似不能形成回路,难道其他的接口有?
哈哈顺 发表于 2013-12-17 22:27 static/image/common/back.gif
哈哈,不供地貌似不能形成回路,难道其他的接口有?
哦~~~我是接到一台电脑上了~~~ http://avrbeginners.net/architecture/img/spi_fig1_a.gif
http://www.gammon.com.au/forum/?id=10892
one example : slave send data back to master
slave code:
// Written by Nick Gammon
// April 2011
#include "pins_arduino.h"
// what to do with incoming data
byte command = 0;
// start of transaction, no command yet
void ss_falling ()
{
command = 0;
}// end of interrupt service routine (ISR) ss_falling
void setup (void)
{
// have to send on master in, *slave out*
pinMode(MISO, OUTPUT);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// turn on interrupts
SPCR |= _BV(SPIE);
// interrupt for SS falling edge
attachInterrupt (0, ss_falling, FALLING);
}// end of setup
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;
switch (command)
{
// no command? then this is the command
case 0:
command = c;
SPDR = 0;
break;
// add to incoming byte, return result
case 'a':
SPDR = c + 15;// add 15
break;
// subtract from incoming byte, return result
case 's':
SPDR = c - 8;// subtract 8
break;
} // end of switch
}// end of interrupt service routine (ISR) SPI_STC_vect
void loop (void)
{
// all done with interrupts
}// end of loop
//////////////////////////////////////////////////////////////////////////////////////////////
Master (example)
// Written by Nick Gammon
// April 2011
#include <SPI.h>
#include "pins_arduino.h"
void setup (void)
{
Serial.begin (115200);
Serial.println ();
digitalWrite(SS, HIGH);// ensure SS stays high for now
// Put SCK, MOSI, SS pins into output mode
// also put SCK, MOSI into LOW state, and SS into HIGH state.
// Then put SPI hardware into Master mode and turn SPI on
SPI.begin ();
// Slow down the master a bit
SPI.setClockDivider(SPI_CLOCK_DIV8);
}// end of setup
byte transferAndWait (const byte what)
{
byte a = SPI.transfer (what);
delayMicroseconds (20);
return a;
} // end of transferAndWait
void loop (void)
{
byte a, b, c, d;
// enable Slave Select
digitalWrite(SS, LOW);
transferAndWait ('a');// add command
transferAndWait (10);
a = transferAndWait (17);
b = transferAndWait (33);
c = transferAndWait (42);
d = transferAndWait (0);
// disable Slave Select
digitalWrite(SS, HIGH);
Serial.println ("Adding results:");
Serial.println (a, DEC);
Serial.println (b, DEC);
Serial.println (c, DEC);
Serial.println (d, DEC);
// enable Slave Select
digitalWrite(SS, LOW);
transferAndWait ('s');// subtract command
transferAndWait (10);
a = transferAndWait (17);
b = transferAndWait (33);
c = transferAndWait (42);
d = transferAndWait (0);
// disable Slave Select
digitalWrite(SS, HIGH);
Serial.println ("Subtracting results:");
Serial.println (a, DEC);
Serial.println (b, DEC);
Serial.println (c, DEC);
Serial.println (d, DEC);
delay (1000);// 1 second delay
}// end of loop
SPI.setClockDivider(SPI_CLOCK_DIV8);
=設置SPI串列通信的時鐘。
通信時鐘是由系統時鐘分頻而得到,分頻值有2,4,8,16,32,64或128。
預設設置是SPI_CLOCK_DIV4,設置SPI串列通信時鐘系統時鐘的四分之一。
語法
SPI.setClockDivider(divider)
參數
divider:
SPI_CLOCK_DIV2
SPI_CLOCK_DIV4
SPI_CLOCK_DIV8
SPI_CLOCK_DIV16
SPI_CLOCK_DIV32
SPI_CLOCK_DIV64
SPI_CLOCK_DIV128 kwleung 发表于 2013-12-29 23:47 static/image/common/back.gif
slave code:
// Written by Nick Gammon
Thanks for your share hi55234 发表于 2013-12-30 10:54 static/image/common/back.gif
SPI.setClockDivider(SPI_CLOCK_DIV8);
=設置SPI串列通信的時鐘。
通信時鐘是由系統時鐘分頻而得到,分頻 ...
学习一下,多谢!! 不知道为什么要将3.3V的电压接口连接在一起?
另外,传输过程中有单个字符的丢包现象。 本帖最后由 shihaipeng04 于 2014-3-24 23:42 编辑
我开始没有共地,误码奇高。可能之前是因为公用同一电脑勉强还可以传输,所以乱码了还能坚持。偶尔会死机。 现在共地了完全没有误码了,也不死机了。
哈哈,刚才又测试了一下 共usb hub,误码率也降低了不少,但是依然有误码。 可见一个短小精炼的共地回路是多么的重要啊。
就按我这个水平,别说是飞机会跑偏,就是个玩具车都能开失联了。。。
问题解决鸟~~
//_________________happyend______________