
用C语言单开电脑的串口的核心步骤包括:打开串口、配置串口参数、读写数据、关闭串口。在C语言中,涉及系统调用和文件操作函数的使用。下面我们详细介绍其中一个关键步骤:配置串口参数。配置串口参数包括设置波特率、数据位、停止位和校验位,这些参数决定了通信的质量和可靠性。
一、串口基础知识
串口(Serial Port)是计算机与外部设备进行串行通信的接口。它通过串行方式逐位传输数据,常用于与外部设备如传感器、调制解调器等进行数据交换。串口通信的核心参数包括波特率、数据位、停止位和校验位。
1、波特率
波特率决定了数据传输速度,单位是bps(比特每秒)。常见的波特率有9600、19200、38400、57600、115200等。
2、数据位
数据位表示每个字符数据的位数,常见的有7位和8位。
3、停止位
停止位用于表示数据包结束,常见的有1位和2位。
4、校验位
校验位用于检测数据传输过程中的错误,常见的有无校验(None)、奇校验(Odd)、偶校验(Even)。
二、用C语言打开串口
在C语言中,串口通常作为文件来处理。可以使用open()函数来打开串口设备文件。例如,Linux系统中的串口设备文件通常是/dev/ttyS0、/dev/ttyUSB0等。打开串口后,需要配置其参数以确保正确的通信。
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
int open_serial_port(const char *device) {
int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("open_serial_port: Unable to open port");
} else {
fcntl(fd, F_SETFL, 0); // 设置串口为阻塞模式
}
return fd;
}
三、配置串口参数
1、获取和设置串口属性
在C语言中,可以使用termios结构体来配置串口参数。tcgetattr()函数用于获取当前的串口属性,tcsetattr()函数用于设置新的串口属性。
int configure_serial_port(int fd, int baud_rate) {
struct termios options;
// 获取当前的串口属性
if (tcgetattr(fd, &options) != 0) {
perror("configure_serial_port: Unable to get port attributes");
return -1;
}
// 设置波特率
cfsetispeed(&options, baud_rate);
cfsetospeed(&options, baud_rate);
// 设置数据位、停止位和校验位
options.c_cflag &= ~CSIZE; // 清除数据位掩码
options.c_cflag |= CS8; // 设置为8位数据位
options.c_cflag &= ~PARENB; // 无校验
options.c_cflag &= ~CSTOPB; // 1位停止位
// 设置新的串口属性
if (tcsetattr(fd, TCSANOW, &options) != 0) {
perror("configure_serial_port: Unable to set port attributes");
return -1;
}
return 0;
}
2、详细解释波特率设置
波特率的设置对串口通信非常关键,它决定了数据传输的速度。可以使用cfsetispeed()和cfsetospeed()函数来设置输入和输出的波特率。常见的波特率值在系统头文件中定义,例如B9600、B19200、B38400等。
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
四、读写数据
1、读取数据
可以使用read()函数从串口读取数据。读取的数据会存储在一个缓冲区中。
ssize_t read_serial_port(int fd, void *buffer, size_t size) {
return read(fd, buffer, size);
}
2、写入数据
可以使用write()函数向串口写入数据。
ssize_t write_serial_port(int fd, const void *buffer, size_t size) {
return write(fd, buffer, size);
}
五、关闭串口
使用close()函数可以关闭串口。
void close_serial_port(int fd) {
close(fd);
}
六、完整示例代码
以下是一个完整的示例代码,用于打开、配置、读写和关闭串口。
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
int open_serial_port(const char *device) {
int fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror("open_serial_port: Unable to open port");
} else {
fcntl(fd, F_SETFL, 0); // 设置串口为阻塞模式
}
return fd;
}
int configure_serial_port(int fd, int baud_rate) {
struct termios options;
// 获取当前的串口属性
if (tcgetattr(fd, &options) != 0) {
perror("configure_serial_port: Unable to get port attributes");
return -1;
}
// 设置波特率
cfsetispeed(&options, baud_rate);
cfsetospeed(&options, baud_rate);
// 设置数据位、停止位和校验位
options.c_cflag &= ~CSIZE; // 清除数据位掩码
options.c_cflag |= CS8; // 设置为8位数据位
options.c_cflag &= ~PARENB; // 无校验
options.c_cflag &= ~CSTOPB; // 1位停止位
// 设置新的串口属性
if (tcsetattr(fd, TCSANOW, &options) != 0) {
perror("configure_serial_port: Unable to set port attributes");
return -1;
}
return 0;
}
ssize_t read_serial_port(int fd, void *buffer, size_t size) {
return read(fd, buffer, size);
}
ssize_t write_serial_port(int fd, const void *buffer, size_t size) {
return write(fd, buffer, size);
}
void close_serial_port(int fd) {
close(fd);
}
int main() {
const char *device = "/dev/ttyS0";
int fd = open_serial_port(device);
if (fd == -1) {
return -1;
}
if (configure_serial_port(fd, B9600) == -1) {
close_serial_port(fd);
return -1;
}
const char *data = "Hello, Serial Port!";
if (write_serial_port(fd, data, strlen(data)) == -1) {
perror("main: Unable to write to port");
}
char buffer[100];
ssize_t bytes_read = read_serial_port(fd, buffer, sizeof(buffer) - 1);
if (bytes_read == -1) {
perror("main: Unable to read from port");
} else {
buffer[bytes_read] = '