Linuxでシリアルポート割り込みを使用してデータを受信する方法について

Linux上でシリアルポート割り込みでデータをレシーブするには次の手順で行います。

  1. シリアルポートデバイスを開く:たとえば/dev/ttyS0などのシリアルポートデバイスファイルをopen()関数で開く。
  2. シリアルポートパラメータを設定する: termios構造体を使用してシリアルポートのボーレート、データビット、ストップビット、パリティビットなどのパラメータを設定します。tcgetattr() 関数を使用して現在のシリアルポート設定を取得し、次に必要なパラメータを変更し、最後に tcsetattr() 関数を使用してパラメータをシリアルポートに適用できます。
  3. シリアルポート割り込みの設定: fcntl() 関数の F_SETOWN コマンドを使用して、現在のプロセスをシリアルポートの所有者に設定する。
  4. シリアルポート割り込みの有効化:シリアル通信ポートで非ブロッキングモードを有効にするfcntl()関数とF_SETFLコマンドを使用し、FASYNCフラグで非同期通知を有効にします。
  5. シグナル処理関数の設置:シリアルポートの割り込みシグナルの処理では、signal() 関数を使用してシグナル処理関数を設定する。
  6. シグナル処理関数でデータを読み取る: シリアルポートにデータを受信すると、シグナル処理関数が呼び出されます。シグナル処理関数内で read() 関数を使用して、受信したデータを読み取ることができます。

以下は、Linuxでシリアルポート割り込みによるデータ受信を実現する簡単なサンプルコードです。

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

volatile int stop = 0;

void signal_handler(int signum) {
    if (signum == SIGIO) {
        char buffer[255];
        int nbytes = read(STDIN_FILENO, buffer, sizeof(buffer));
        buffer[nbytes] = '\0';
        printf("Received: %s\n", buffer);
    }
}

int main() {
    int fd;
    struct termios tio;
    struct sigaction saio;

    // 打开串口设备
    fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd < 0) {
        perror("Failed to open serial port");
        return 1;
    }

    // 配置串口参数
    memset(&tio, 0, sizeof(tio));
    tio.c_iflag = 0;
    tio.c_oflag = 0;
    tio.c_cflag = CS8 | CREAD | CLOCAL;
    tio.c_lflag = 0;
    tio.c_cc[VMIN] = 1;
    tio.c_cc[VTIME] = 5;
    cfsetospeed(&tio, B9600);
    cfsetispeed(&tio, B9600);
    tcsetattr(fd, TCSANOW, &tio);

    // 设置串口中断
    fcntl(fd, F_SETOWN, getpid());

    // 启用串口中断
    fcntl(fd, F_SETFL, FASYNC);

    // 安装信号处理函数
    saio.sa_handler = signal_handler;
    sigemptyset(&saio.sa_mask);
    saio.sa_flags = 0;
    saio.sa_restorer = NULL;
    sigaction(SIGIO, &saio, NULL);

    printf("Waiting for data...\n");

    // 等待中断并处理数据
    while (!stop) {
        sleep(1);
    }

    // 关闭串口设备
    close(fd);

    return 0;
}

実際の状況に応じて調整と最適化が必要になる可能性があるので、このサンプルコードはあくまでデモの目的で使用されることに注意してください。

bannerAds