下面我们还是用两块arduino来实践一下如何利用i2c协议来传输数据。如图连接好两块arduino:
一台我们作为主设备(master),烧录以下代码:
#include void setup() { serial.begin(9600); /* begin serial comm. */ wire.begin(); /* join i2c bus as master */ serial.println(i am i2c master);}void loop() { wire.begintransmission(8); /* begin with device address 8 */ wire.write(hello slave); /* sends hello string */ wire.endtransmission(); /* stop transmitting */ wire.requestfrom(8, 9); /* request & read data of size 9 from slave */ while(wire.available()){ char c = wire.read();/* read data received from slave */ serial.print(c); } serial.println(); delay(1000);}另一块作为从设备(slave),烧录以下代码:
#include void setup() { wire.begin(8); /* join i2c bus with address 8 */ wire.onreceive(receiveevent); /* register receive event */ wire.onrequest(requestevent); /* register request event */ serial.begin(9600); /* start serial comm. */ serial.println(i am i2c slave);}void loop() { delay(100);}// function that executes whenever data is received from mastervoid receiveevent(int howmany) { while (0
从机arduino的串口输出:
i2c虽然只需要两根线,就能支持多主机多从机的数据传输,但由于只有一根用于数据传输,它通过在“接收”和“传输”两种状态之间但切换实现了双向传输,但牺牲了不少传输速率。i2c还有典型的开漏问题,总线需要加上拉电阻。
spi协议
最后,我们来看一下spi协议。spi全称serial peripheral interface(串行外设接口),由摩托罗拉公司提出的一种同步串行数据传输协议。spi类似i2c也是同步通信的协议,但是全双工,支持数据的同时输出和输入。这两个特征使spi的传输速率比uart和i2c都高,这对于像sd卡、或者屏幕等数据型模块来说,是非常具有优势的。
spi支持一主多从的模式,但spi也是三种协议中需要线最多的协议,一共需要4条信号线:
但arduino uno默认的spi引脚分别为d13(sck), d12(miso), d11(mosi), d10(ss),其中ss是从机选择引脚,没有强制要求,你也可以选其他的引脚。
同样,我们来实践一下用spi实现数据传输。
如图连接好两块arduino uno。还是一块作为主机(master), 另一块作为从机(slave)。arduino对spi协议也做了类封装:
https://www.arduino.cc/en/reference/spi主机烧录以下代码:
#include void setup (void){ serial.begin(115200); digitalwrite(ss, high); spi.begin (); spi.setclockdivider(spi_clock_div8);}void loop (void){ char c; // enable slave select digitalwrite(ss, low); // ss is pin 10 // send test string for (const char * p = hello, world!\\n ; c = *p; p++) { spi.transfer (c); serial.print(c); } // disable slave select digitalwrite(ss, high); delay (1000);}从机烧录:
#include char buf [100];volatile byte pos;volatile boolean process_it;void setup (void){ serial.begin (115200); // debugging // turn on spi in slave mode spcr |= bit (spe); // have to send on master in, *slave out* pinmode(miso, output); // get ready for an interrupt pos = 0; // buffer empty process_it = false; // now turn on interrupts spi.attachinterrupt();} // end of setup// spi interrupt routineisr (spi_stc_vect){ byte c = spdr; // grab byte from spi data register // add to buffer if room if (pos < sizeof buf) { buf [pos++] = c; // example: newline means time to process buffer if (c == '\\n') process_it = true; } // end of room available} // end of interrupt routine spi_stc_vect// main loop - wait for flag set in interrupt routinevoid loop (void){ if (process_it) { buf [pos] = 0; serial.println(buf); pos = 0; process_it = false; } // end of flag set} // end of loop这样从机就能接受到主机发过来的消息了。
总结
今天,我们粗略地介绍了一下arduino数据通信中最常用的三种协议:uart、i2c和spi。
| **协议
** | **通信方式
** | **通信方向
** | **信号线
** | **传输速率
** | **主从模式
**
uart
异步
全双工 2线rx、tx 最低
一对一
i2c
同步
半双工
2线sda、scl,以地址选择从机 低
多主机多从机
spi
同步
全双工 4线mosi、miso、sclk、cs(或ss),以cs选择从机 高
一主多从
它们各自都有自己的优缺点和适用的场景,并没有绝对的好坏,这也是这三种协议经久不衰的原因。只有了解并掌握它们,我们才能在具体的应用场景里选择最合适的协议。当然在嵌入式世界里,还有其他很多协议,小编以后再介绍吧。如果对这三种协议的底层感兴趣的朋友,也可以自己再去深入了解。
「工业树莓派」raspi-config 常用配置介绍
2030年全球驱动电机市场规模年均增速将在18%-20%
宽带固定增益放大器THS4302的工作原理和应用电路分析
刷脸支付在商业投资推动下,发起了新的变革
单张消费级显卡微调多模态大模型
Arduino常用的三种通信协议 2
智能电网发展正当时
一文了解PLC的结构
Maxim Integrated发布业界噪声最低的D/G类放大器,用于行业标准的常开扬声器设计,仅消耗1/5静态功耗
控制面板优化的五大方向
VICOR电源FARM™滤波器特点及优点
ST EVL400W-EUPL7评估板可实现较高的平均能效和典型能效
电阻器的选用要点
开关电源之EMI噪声产生、抑制及滤波的分析
新能源汽车下乡成为车企、电池企业寻找销量增长的新突破口
Type-C数据线质量的好坏对数据传输有何影响
一个汽车电瓶可以用多久?
数读:工信部最新发布电子信息制造业年度数据
移动互联网时代,为什么还存在着固定电话
国民技术MCU正式入驻21ic中国电子技术论坛