串行通信协议比较
特性 | 串行(UART/USART) | I2C | SPI |
---|
线数 | 2 (TX, RX) | 2 (SDA, SCL) | 4 (MISO, MOSI, SCLK, SS/CS) |
数据率 | 低到中等 | 中等 | 高 |
主/从 | 可以是主或从 | 主/从 | 主/从 |
寻址 | 无寻址 | 7位或10位地址 | 通过片选线 (SS) 进行寻址 |
拓扑 | 点对点,点到多点 | 多主,多从 | 多主,多从 |
总线仲裁 | 无总线仲裁 | 通过冲突进行仲裁 | 无总线仲裁 |
错误处理 | 有限错误检测 | 基本的错误检查 | 有限错误检测 |
用途 | 一般通信 | 传感器,EEPROM,某些集成电路 | 闪存,传感器,外设 |
灵活性 | 由于固定大小较不灵活 | 由于寻址更灵活 | 通过各种模式更灵活 |
电缆长度 | 中等到长 | 短到中等 | 短到中等 |
常见电压电平 | TTL, RS-232(可能不同) | 通常为3.3V或5V | 通常为3.3V或5V |
双工模式 | 全双工或半双工 | 半双工 | 全双工 |
时钟信号 | 同步或异步 | 同步 | 同步 |
设备示例 | USB到串行适配器,微控制器 | 传感器,EEPROM,微控制器 | 闪存,传感器,微控制器 |
串行通信 (UART/USART) 特性详解
特性 | 描述 |
---|
定义 | 串行通信是一种逐位传输数据的通信方式。 |
线数 | 2 (TX, RX) - 分别用于发送和接收数据。 |
数据率 | 低到中等 - 支持不同速率,例如 9600、115200 bps。 |
工作模式 | 全双工或半双工 - 可同时发送和接收或只能执行其中一项。 |
电平标准 | TTL, RS-232(可能不同) - 标准电平可以是TTL或RS-232。 |
帧结构 | 起始位、数据位、校验位和停止位组成帧结构。 |
同步方式 | 可以是同步或异步 - 同步需要时钟信号,异步没有时钟信号。 |
寻址方式 | 无寻址 - 通常是点对点通信,不需要地址进行寻址。 |
错误检测 | 有限错误检测 - 常见的错误检测包括奇偶校验和校验和。 |
适用范围 | 一般通信 - 用于连接各种设备,例如传感器、微控制器等。 |
典型用途 | USB到串行适配器、微控制器通信等。 |
电缆长度 | 中等到长 - 随着电缆长度增加,需注意信号衰减。 |
优势 | 简单、成本低、易于实现。 |
劣势 | 电缆长度受限,对电缆质量和环境敏感。 |
注:TTL (Transistor-Transistor Logic) 是一种低电平逻辑电平标准,RS-232 是一种常见的串口电平标准。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
void error(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
int main() {
int serial_port = open("/dev/ttyUSB0", O_RDWR);
if (serial_port == -1) {
error("Error - Unable to open UART.");
}
struct termios options;
tcgetattr(serial_port, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_iflag &= ~(IXON | IXOFF | IXANY);
options.c_oflag &= ~OPOST;
tcsetattr(serial_port, TCSANOW, &options);
char tx_buffer[] = "Hello, Serial!";
if (write(serial_port, tx_buffer, strlen(tx_buffer)) < 0) {
error("Error - Unable to write to UART.");
}
char rx_buffer[256];
int bytes_read = read(serial_port, rx_buffer, sizeof(rx_buffer));
if (bytes_read < 0) {
error("Error - Unable to read from UART.");
}
printf("Received Data: %.*s\n", bytes_read, rx_buffer);
close(serial_port);
return 0;
}
I2C通信特性详解
特性 | 描述 |
---|
定义 | I2C (Inter-Integrated Circuit) 是一种串行通信协议。 |
线数 | 2 (SDA, SCL) - 数据线 (SDA) 和时钟线 (SCL)。 |
数据率 | 中等 - 数据传输速率通常在几百 kHz 到几兆 Hz 之间。 |
工作模式 | 主/从 - 设备可以是主设备(发起通信)或从设备(被动应答)。 |
寻址方式 | 7位或10位地址 - 设备通过地址进行唯一寻址。 |
拓扑 | 多主,多从 - 允许多个主设备和多个从设备存在在同一总线上。 |
总线仲裁 | 通过冲突进行仲裁 - 多主模式下可能发生仲裁冲突。 |
错误检查 | 基本的错误检查 - 可以通过 NACK 信号检测错误。 |
适用范围 | 传感器,EEPROM,某些集成电路等。 |
典型用途 | 用于连接多个设备,如传感器、EEPROM、实时时钟等。 |
电缆长度 | 短到中等 - 电缆长度受限,随着电缆长度增加需注意信号衰减。 |
常见电压电平 | 通常为3.3V或5V。 |
双工模式 | 半双工 - 数据在两个方向上传输,但不同时进行。 |
时钟信号 | 同步 - 时钟信号由主设备提供。 |
设备示例 | 传感器,EEPROM,微控制器等。 |
灵活性 | 由于寻址更灵活,支持多主模式。 |
优势 | 适用于连接多个设备,寻址灵活,支持多主模式。 |
劣势 | 电缆长度受限,错误检测有限。 |
注:I2C 是一种常见的串行通信协议,广泛用于连接各种集成电路和外设。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#define I2C_DEVICE "/dev/i2c-1"
void error(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
int main() {
int i2c_fd = open(I2C_DEVICE, O_RDWR);
if (i2c_fd == -1) {
error("Error - Unable to open I2C device.");
}
int slave_address = 0x48;
if (ioctl(i2c_fd, I2C_SLAVE, slave_address) < 0) {
error("Error - Unable to set I2C slave address.");
}
char tx_buffer[] = "Hello, I2C!";
if (write(i2c_fd, tx_buffer, sizeof(tx_buffer)) != sizeof(tx_buffer)) {
error("Error - Unable to write to I2C device.");
}
char rx_buffer[256];
if (read(i2c_fd, rx_buffer, sizeof(rx_buffer)) < 0) {
error("Error - Unable to read from I2C device.");
}
printf("Received Data: %s\n", rx_buffer);
close(i2c_fd);
return 0;
}
SPI通信特性详解
特性 | 描述 |
---|
定义 | SPI (Serial Peripheral Interface) 是一种全双工串行通信协议。 |
线数 | 4 (MISO, MOSI, SCLK, SS/CS) - MISO: 主设备到从设备数据线,MOSI: 从设备到主设备数据线,SCLK: 时钟线,SS/CS: 片选线。 |
数据率 | 高 - 支持高达几百 Mbps 到几 Gbps 的数据传输速率。 |
工作模式 | 主/从 - 主设备发起通信,从设备被动应答。 |
寻址方式 | 通过片选线 (SS/CS) 进行寻址 - 每个从设备连接到不同的片选线。 |
拓扑 | 多主,多从 - 允许多个主设备和多个从设备存在在同一总线上。 |
总线仲裁 | 无总线仲裁 - 没有多主模式下的总线仲裁。 |
错误检查 | 有限错误检测 - 可以通过校验和等手段进行错误检测。 |
适用范围 | 闪存,传感器,外设等。 |
典型用途 | 连接外设,如闪存、传感器、显示器等。 |
电缆长度 | 短到中等 - 电缆长度受限,随着电缆长度增加需注意信号衰减。 |
常见电压电平 | 通常为3.3V或5V。 |
双工模式 | 全双工 - 可同时进行数据发送和接收。 |
时钟信号 | 同步 - 时钟信号由主设备提供。 |
设备示例 | 闪存,传感器,微控制器等。 |
灵活性 | 通过各种模式更灵活 - 支持不同的时钟极性和相位配置。 |
优势 | 高速数据传输,支持全双工通信,灵活的时钟和模式配置。 |
劣势 | 对布线和电缆长度要求较高,相对复杂。 |
注:SPI是一种常用的串行通信协议,特别适用于高速数据传输和连接外围设备。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#define SPI_DEVICE "/dev/spidev0.0"
void error(const char *msg) {
perror(msg);
exit(EXIT_FAILURE);
}
int main() {
int spi_fd = open(SPI_DEVICE, O_RDWR);
if (spi_fd == -1) {
error("Error - Unable to open SPI device.");
}
uint8_t mode = SPI_MODE_0;
uint8_t bits = 8;
uint32_t speed = 1000000;
if (ioctl(spi_fd, SPI_IOC_WR_MODE, &mode) < 0 ||
ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0 ||
ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) {
error("Error - Unable to configure SPI device.");
}
uint8_t tx_buffer[] = {0x01, 0x02, 0x03};
uint8_t rx_buffer[sizeof(tx_buffer)] = {0};
struct spi_ioc_transfer transfer = {
.tx_buf = (unsigned long)tx_buffer,
.rx_buf = (unsigned long)rx_buffer,
.len = sizeof(tx_buffer),
.speed_hz = speed,
.bits_per_word = bits,
};
if (ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer) < 0) {
error("Error - Unable to perform SPI transaction.");
}
printf("Received Data:");
for (int i = 0; i < sizeof(rx_buffer); i++) {
printf(" %02x", rx_buffer[i]);
}
printf("\n");
close(spi_fd);
return 0;
}