引言

串口通信是一种基本的计算机通信方式,广泛应用于嵌入式系统、工业控制等领域。C语言由于其高效性和灵活性,成为实现串口通信的常用编程语言。本文将详细介绍C语言串口通信的原理、配置方法以及实战解析,帮助读者轻松上手。

1. 串口通信基础

1.1 串口概述

串口(Serial Port)是一种串行通信接口,用于实现计算机与外部设备之间的数据传输。它通过串行传输数据,即每次只传输一位数据。

1.2 串口标准

常见的串口标准包括RS-232、RS-485、RS-422等。其中,RS-232是最常用的串口标准,广泛应用于计算机与外部设备之间的通信。

1.3 串口参数

串口通信的主要参数包括波特率、数据位、停止位、校验位等。

  • 波特率:表示每秒传输的位数,单位为bps(比特/秒)。
  • 数据位:表示每次传输的数据位数,常见值为8位。
  • 停止位:表示每次传输结束后,停止位的位数,常见值为1位。
  • 校验位:用于校验数据传输的正确性,常见值为无校验、奇校验、偶校验。

2. C语言串口编程基础

2.1 串口编程环境

在进行C语言串口编程之前,需要安装串口编程所需的库和驱动程序。常见的库包括Windows平台下的Win32 API、Linux平台下的termios等。

2.2 串口编程步骤

  1. 打开串口:使用open()函数打开串口设备文件。
  2. 设置串口参数:使用setsockopt()函数设置串口参数,如波特率、数据位、停止位、校验位等。
  3. 读写数据:使用read()和write()函数进行数据的读写操作。
  4. 关闭串口:使用close()函数关闭串口。

3. 串口通信实战解析

3.1 Windows平台下的串口编程

以下是一个简单的Windows平台下使用Win32 API进行串口通信的示例代码:

#include <windows.h>

int main() {
    HANDLE hSerial;
    DCB dcbSerialParams = {0};

    // 打开串口
    hSerial = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hSerial == INVALID_HANDLE_VALUE) {
        return 1;
    }

    // 设置串口参数
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        return 1;
    }

    dcbSerialParams.BaudRate = CBR_9600;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;

    if (!SetCommState(hSerial, &dcbSerialParams)) {
        return 1;
    }

    // 读写数据
    char data[] = "Hello, Serial Port!";
    DWORD bytes_written;
    if (!WriteFile(hSerial, data, strlen(data), &bytes_written, NULL)) {
        return 1;
    }

    char read_data[1024];
    DWORD bytes_read;
    if (!ReadFile(hSerial, read_data, sizeof(read_data), &bytes_read, NULL)) {
        return 1;
    }

    // 关闭串口
    CloseHandle(hSerial);

    return 0;
}

3.2 Linux平台下的串口编程

以下是一个简单的Linux平台下使用termios进行串口通信的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>

int main() {
    int fd;
    struct termios tty;

    // 打开串口
    fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd < 0) {
        perror("open_port: Unable to open serial port");
        exit(1);
    }

    // 设置串口参数
    if(tcgetattr(fd, &tty) != 0) {
        perror("tcgetattr");
        exit(1);
    }

    tty.c_cflag &= ~PARENB; // Clear parity bit, disabling parity (most common)
    tty.c_cflag &= ~CSTOPB; // Clear stop field, only one stop bit used in communication (most common)
    tty.c_cflag &= ~CSIZE; // Clear all the size bits, then use one of the statements below
    tty.c_cflag |= CS8; // 8 bits per byte (most common)
    tty.c_cflag &= ~CRTSCTS; // Disable RTS/CTS hardware flow control (most common)
    tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines (CLOCAL = 1)

    tty.c_lflag &= ~ICANON; // Disable canonical mode
    tty.c_lflag &= ~ECHO; // Disable echo
    tty.c_lflag &= ~ECHOE; // Disable erasure
    tty.c_lflag &= ~ECHONL; // Disable new-line echo
    tty.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP

    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
    tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes

    tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
    tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed

    tty.c_cc[VTIME] = 10;    // Wait for up to 1s (10 deciseconds), returning as soon as any data is received.
    tty.c_cc[VMIN] = 0;

    if (tcsetattr(fd,TCSANOW,&tty) != 0) {
        perror("tcsetattr");
        exit(1);
    }

    // 读写数据
    char data[] = "Hello, Serial Port!";
    write(fd, data, strlen(data));

    char read_data[1024];
    read(fd, read_data, sizeof(read_data));

    // 关闭串口
    close(fd);

    return 0;
}

4. 总结

本文介绍了C语言串口通信的基础知识、编程步骤以及实战解析。通过本文的学习,读者可以轻松上手C语言串口通信编程,并能够根据实际需求进行应用。在实际开发过程中,可以根据不同的平台和需求选择合适的串口编程方法,实现高效、稳定的串口通信。