3

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

有没有办法让它非阻塞或只等待几毫秒的数据?

4

4 回答 4

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;
    }
于 2014-01-16T10:47:41.507 回答
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 。

于 2014-01-16T08:28:11.490 回答
2

小心这个解决方案:

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

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

于 2016-07-12T23:16:40.000 回答
1

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

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

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

于 2019-04-19T07:45:23.127 回答