C语言串口通信是嵌入式系统和硬件交互中常见的任务,它涉及多个关键步骤和概念,以下是关于C语言串口通信的详细教程:
1、基本概念
波特率:指每秒钟传输的比特数,常见值有9600、19200、38400等。
数据位:每个字符的数据位数,通常为8位。
停止位:用于标志一个字符的结束,可以是1位或2位。
校验位:用于错误检测,常见的校验方式有无校验、奇校验和偶校验。
2、应用场景
串口通信广泛应用于嵌入式系统、工业控制、传感器数据采集等领域。
1、Linux系统
使用termios结构体和tcsetattr函数来配置串口参数。
示例代码:
int configure_serial_port(int fd, int baud_rate) { struct termios tty; if (tcgetattr(fd, &tty) != 0) { perror("tcgetattr"); return -1; } cfsetospeed(&tty, baud_rate); cfsetispeed(&tty, baud_rate); tty.c_cflag &= ~PARENB; // 无校验位 tty.c_cflag &= ~CSTOPB; // 1个停止位 tty.c_cflag &= ~CSIZE; tty.c_cflag |= CS8; // 8个数据位 tty.c_cflag |= CREAD | CLOCAL; // 打开接收开关和本地模式 tty.c_lflag &= ~ICANON; tty.c_lflag &= ~ECHO; tty.c_lflag &= ~ECHOE; tty.c_lflag &= ~ISIG; tty.c_iflag &= ~(IXON | IXOFF | IXANY); tty.c_iflag &= ~(ICRNL | INLCR); tty.c_oflag &= ~OPOST; tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; if (tcsetattr(fd, TCSANOW, &tty) != 0) { perror("tcsetattr"); return -1; } return 0; }
2、Windows系统
Windows下串口编程与Linux有所不同,需要包含头文件<windows.h>
,并使用CreateFile
、BuildCommDCBA
、SetCommState
等API函数进行配置,具体步骤包括打开串口、获取串口属性、设置串口参数(如波特率、数据位、停止位、校验位等)以及配置超时等。
1、Linux系统
串口设备通常位于/dev/ttyS
或/dev/ttyUSB
。
使用open函数打开串口设备,示例代码:
int open_serial_port(const char *device) { int fd = open(device, O_RDWR | O_NOCTTY | O_SYNC); if (fd == -1) { perror("open"); return -1; } return fd; }
2、Windows系统
使用CreateFile
函数打开串口,示例代码:
HANDLE hSerial = CreateFile(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSerial == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { printf("串口不存在! "); } else { printf("打开串口失败! "); } return NULL; }
1、Linux系统
使用write函数将数据写入到串口,示例代码:
int send_data(int fd, const char *data, size_t length) { ssize_t bytes_written = write(fd, data, length); if (bytes_written == -1) { perror("write"); return -1; } return bytes_written; }
2、Windows系统
使用WriteFile
函数向串口写入数据,示例代码:
DWORD dwBytesWrite = 0; BOOL bWriteState = FALSE; bWriteState = WriteFile(hSerial, buffer, dwBytesToWrite, &dwBytesWrite, NULL); if (!bWriteState) { if (GetLastError() == ERROR_GEN_FAILURE) { printf("写入串口出错! "); } else { printf("写入串口时发生未知错误! "); } } else { printf("成功写入%d个字符。 ", dwBytesWrite); }
1、Linux系统
使用read函数从串口读取数据,示例代码:
int read_data(int fd, char *buffer, size_t length) { ssize_t bytes_read = read(fd, buffer, length); if (bytes_read == -1) { perror("read"); return -1; } return bytes_read; }
2、Windows系统
使用ReadFile
函数从串口读取数据,示例代码:
DWORD dwBytesRead = 0; BOOL bReadState = FALSE; bReadState = ReadFile(hSerial, buffer, dwBytesToRead, &dwBytesRead, NULL); if (!bReadState) { if (GetLastError() == ERROR_GEN_FAILURE) { printf("读取串口出错! "); } else { printf("读取串口时发生未知错误! "); } } else { printf("成功读取%d个字符。 ", dwBytesRead); }
以下是一个简单的C语言串口通信示例程序,用于向串口发送字符串"Hello, World!":
1、Linux系统
完整代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> int main() { int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { perror("open"); return -1; } configure_serial_port(fd, B9600); char *data = "Hello, World!"; send_data(fd, data, strlen(data)); close(fd); return 0; }
2、Windows系统
完整代码如下:
#include <windows.h> #include <stdio.h> int main() { HANDLE hSerial = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hSerial == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { printf("串口不存在! "); } else { printf("打开串口失败! "); } return 1; } DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) { printf("获取串口状态失败! "); return 1; } dcbSerialParams.BaudRate = CBR_9600; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(hSerial, &dcbSerialParams)) { printf("配置串口失败! "); return 1; } char buffer[] = "Hello, World!"; DWORD dwBytesWrite = 0; BOOL bWriteState = WriteFile(hSerial, buffer, strlen(buffer), &dwBytesWrite, NULL); if (!bWriteState) { if (GetLastError() == ERROR_GEN_FAILURE) { printf("写入串口出错! "); } else { printf("写入串口时发生未知错误! "); } } else { printf("成功写入%d个字符。 ", dwBytesWrite); } CloseHandle(hSerial); return 0; }
1、问:如何确定串口设备的文件路径?
答:在Linux系统中,串口设备通常位于/dev/ttyS
或/dev/ttyUSB
,可以通过查看/dev
目录下的设备文件来确定具体的串口设备,在Windows系统中,串口设备通常标识为COM1
、COM2
等,可以通过设备管理器来查看串口设备的详细信息。
2、问:为什么串口通信时需要配置波特率等参数?
答:波特率等参数是串口通信的重要参数,它们决定了数据传输的速度和格式,不同的设备可能使用不同的波特率和数据格式,因此在进行串口通信之前,需要配置正确的参数,以确保双方能够正确地进行数据传输。
八、小编有话说:通过本文的介绍,相信读者对C语言串口通信有了更深入的了解,无论是在Linux还是Windows系统下,掌握串口通信的方法对于嵌入式系统开发和硬件交互都具有重要意义,希望本文能够帮助读者更好地理解和应用C语言串口通信技术。