SocketCAN连续读写

问题描述 投票:2回答:4

我正在编写一个程序,不断向CAN总线发送“Hello”,并通过SocketCAN从总线读取数据。我希望这两个步骤是独立的。这意味着即使总线上没有数据,程序仍会发送“Hello”。但是通常的CAN读取是不可能的,因为这个功能会停止程序运行并等待数据。

有没有办法如何使其无阻塞或仅等待几毫秒的数据?

c embedded nonblocking can-bus socketcan
4个回答
2
投票

您可以使用以下星座(这不是完整的解决方案,只是算法):

while(1) {
    FD_ZERO(&rdfs);
    FD_SET(s, &rdfs);

    tv.tv_sec = 0;
    tv.tv_usec = 10000; // microseconds

    rc = select(s + 1, &rdfs, NULL, NULL, &tv);

    // rc == 0 - timeout
    if (!rc) {
         // write your CAN frame
    }

    if (FD_ISSET(s, &rdfs)) {
         // read CAN frames
    }
}

有关更多信息以及如何处理返回值,请参阅man select


3
投票

我发现的另一种方式 - 线程。只需让CAN读取工作在线程中,它就不会停止主循环。对于Linux系统,它看起来像这样:

 #include <pthread.h>

    void *thread(int cansock) {
       struct can_frame rxmsg;      
       while (1) {   
            read(cansock, &rxmsg, sizeof(rxmsg));
            printf("message received\n");                     
        }
    }

    int main(){
// initialize CAN socket and message to send
    pthread_t pth;
    pthread_create(&pth, NULL, thread, cansock);
    while(1){
      write(cansock, &txmsg, sizeof(txmsg));
      printf("message sent\n");
      }
    return 0;
    }

1
投票

小心这个解决方案:

void *thread(int cansock) {
       struct can_frame rxmsg;      
       while (1) {   
            read(cansock, &rxmsg, sizeof(rxmsg));
            printf("message received\n");                     
        }
    }

因为如果read()开始返回一个没有阻塞的错误,并且这已经在现场,并且没有人可以查看printf()的结果,那么你将进入一个繁忙的循环。


1
投票

我通过在初始化时添加以下代码来解决它

timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 10000;
setsockopt(skt_, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

并在另一个线程中添加循环read

© www.soinside.com 2019 - 2024. All rights reserved.