简体   繁体   English

SocketCAN连续读写

[英]SocketCAN continuous reading and writing

I'm writing a program that continuously sends "Hello" to a CAN-bus and reads data from the bus via SocketCAN. 我正在编写一个程序,不断向CAN总线发送“Hello”,并通过SocketCAN从总线读取数据。 I want those two steps to be independent. 我希望这两个步骤是独立的。 That means even if there is no data on the bus, the program will still send "Hello". 这意味着即使总线上没有数据,程序仍会发送“Hello”。 But with usual CAN reading it is impossible, because this function stops program run and waits for data. 但是通常的CAN读取是不可能的,因为这个功能会停止程序运行并等待数据。

Is there a way how to make it non-blocking or waiting for data only for a few milliseconds? 有没有办法使它无阻塞或仅等待几毫秒的数据?

Another way I found - threads. 我发现的另一种方式 - 线程。 Just make CAN reading work in thread and it won't stop main cycle. 只需让CAN读取工作在线程中,它就不会停止主循环。 For Linux systems it looks like this: 对于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;
    }

You can use following constellation (this is not the complete solution, but just algorithm): 您可以使用以下星座(这不是完整的解决方案,只是算法):

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
    }
}

See man select for more information and how to handle return value. 有关更多信息以及如何处理返回值,请参见man select

Be careful with this solution: 小心这个解决方案:

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

because if read() starts returning an error without block, and this is out in the field and there's nobody to look at the results of printf(), you're going into a busy loop. 因为如果read()开始返回没有阻塞的错误,并且该错误已出现在字段中,并且没有人可以查看printf()的结果,那么您将陷入忙碌的循环。

I solved it by add the following code on initialization 我通过在初始化时添加以下代码来解决它

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

and add the loop read in another thread. 并在另一个线程中添加循环read

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM