云海游戏(中国区)有限公司官网



  • Multi threading in CANlib

    samples\example\c\thread.c

    /*
    ** This software is furnished as Redistributable under the 云海游戏 Software Licence
    ** https://www.kvaser.com/canlib-webhelp/page_license_and_copyright.html
    ** Description:
    ** This is a multithreaded program that uses CANLIB.
    */
    #include <stdlib.h>
    #include <stdio.h>
    #include <memory.h>
    #include <windows.h>
    #include <conio.h>
    #include <canlib.h>
    #ifdef __BORLANDC__
    #pragma argsused
    #endif
    void Usage(int argc, char* argv[])
    {
    printf("\nCANLIB Thread Test 4\n");
    printf("\n");
    printf("\nUsage: thread [flags]\n");
    printf(" -aX Use channel number X as source\n");
    printf(" -bY Use channel number Y as destination\n");
    printf(" (note: X must be different from Y. Default X=0, Y=1)\n");
    printf(" -B<value> Set the bitrate. Value is any of 1000,500,250,125.\n");
    printf(" Default bitrate is 125 kbit/s.\n");
    printf(" -v Be verbose.\n");
    printf(" -Lnnn Run nnn \"loops\". Default is 500.\n");
    exit(1);
    }
    //
    // Global variables for the command-line options.
    //
    int Bitrate = canBITRATE_125K; //
    int Verbose = 0;
    int MaxLoops = 500;
    //
    // Check a status code and issue an error message if the code
    // isn't canOK.
    //
    void Check(char* id, canStatus stat)
    {
    if (stat != canOK) {
    char buf[50];
    buf[0] = '\0';
    canGetErrorText(stat, buf, sizeof(buf));
    printf("%s: failed, stat=%d (%s)\n", id, (int)stat, buf);
    }
    }
    //
    // Setup a CAN controller.
    //
    canHandle InitCtrl(int ctrl)
    {
    canStatus stat;
    canHandle hnd;
    hnd = canOpenChannel(ctrl, 0x0020);
    if (hnd < 0) {
    printf("canOpenChannel failed, stat=%d, ctrl=%d\n", hnd, ctrl);
    exit(0);
    }
    //
    // Using our new shiny handle, we specify the baud rate
    // using one of the convenient canBITRATE_xxx constants.
    //
    // The bit layout is in depth discussed in most CAN
    // controller data sheets, and on the web at
    // http://www.kvaser.se.
    //
    stat = canSetBusParams(hnd, Bitrate, 0, 0, 0, 0, 0);
    if (stat < 0) {
    printf("canSetBusParams failed, stat=%d\n", stat);
    }
    //
    // Then we start the ball rolling.
    //
    stat = canBusOn(hnd);
    if (stat < 0) {
    printf("canBusOn failed, stat=%d\n", stat);
    }
    // Return the handle; our caller will need it for
    // further exercising the CAN controller.
    return hnd;
    }
    CRITICAL_SECTION cs;
    static long TimeToLeave;
    static long TotalSent[4];
    static long TotalReceived[4];
    #define NR_MSGS 3
    #define SRC_ID 300
    #define P_NAP 50
    #define C_NAP 0
    HANDLE events[4];
    int channels[4];
    DWORD WINAPI SendAndReceive(PVOID p)
    {
    canHandle hnd;
    long id_read;
    canStatus stat;
    BYTE msg[8];
    int i, count;
    ULONG idx;
    idx = PtrToUlong(p);
    hnd = InitCtrl(channels[idx]);
    TotalSent[idx] = 0;
    count = 0;
    WaitForSingleObject(events[idx], INFINITE);
    while (TRUE) {
    long id;
    id = SRC_ID + idx;
    for (i=0; i<NR_MSGS; i++) {
    unsigned int dlc, flags;
    // Send one..
    //memcpy(msg, &i, sizeof(i));
    memcpy(msg, &count, sizeof(count));
    count++;
    stat = canWrite(hnd, id, msg, 8, 0);
    Check("canWrite A", stat);
    TotalSent[idx]++;
    // And receive all that is pending..
    do {
    stat = canRead(hnd, &id_read, NULL, &dlc, &flags, NULL);
    if (stat == canOK) {
    if (Verbose > 1) printf("R");
    TotalReceived[idx]++;
    // if (id_read != SRC_ID) printf("Id=%d dlc=%d flags=0x%x\n", id_read, dlc, flags);
    if (flags & canMSG_ERROR_FRAME) printf("x");
    }
    } while (stat == canOK);
    }
    stat = canWriteSync(hnd, 1000);
    Check("canWriteSync A", stat);
    Sleep(P_NAP);
    if (TimeToLeave) break;
    }
    return 0;
    }
    DWORD WINAPI ReadOne(PVOID p)
    {
    canHandle hnd;
    canStatus stat;
    ULONG idx;
    idx = PtrToUlong(p);
    hnd = InitCtrl(channels[idx]);
    TotalReceived[idx] = 0;
    WaitForSingleObject(events[idx], INFINITE);
    while (TRUE) {
    //
    // Call canReadSyncSpecific to wait for the message(s) that the other threads
    // are sending back and forth, then call canRead to consume the messages.
    //
    do {
    stat = canReadSyncSpecific(hnd, SRC_ID, 500);
    if (stat == canOK) {
    if (Verbose > 1) printf("r");
    } else {
    if (Verbose > 1) printf("T");
    }
    while (canRead(hnd, NULL, NULL, NULL, NULL, NULL) == canOK) {
    TotalReceived[idx]++;
    }
    } while (stat == canOK);
    //
    // Call canReadSyncSpecific again to wait for a non-existent id - this time
    // we expect a timeout.
    //
    do {
    stat = canReadSyncSpecific(hnd, SRC_ID+5, 50);
    if (stat == canOK) {
    printf("Whoops, canReadSyncSpecific failed");
    }
    } while (stat == canOK);
    if (TimeToLeave) break;
    Sleep(C_NAP);
    }
    return 0;
    }
    //
    // Just consume all messages on the bus.
    //
    DWORD WINAPI Sink(PVOID p)
    {
    canHandle hnd;
    ULONG idx;
    idx = PtrToUlong(p);
    hnd = InitCtrl(channels[idx]);
    TotalReceived[idx] = 0;
    WaitForSingleObject(events[idx], INFINITE);
    while (TRUE) {
    while (canRead(hnd, NULL, NULL, NULL, NULL, NULL) == canOK) {
    if (Verbose > 1) printf("x");
    TotalReceived[idx]++;
    }
    if (TimeToLeave) break;
    Sleep(C_NAP);
    }
    return 0;
    }
    //
    //
    void main(int argc, char* argv[])
    {
    int i;
    DWORD tid;
    HANDLE t1, t2, t3, t4;
    for (i=0; i<4; i++) channels[i] = i;
    //
    // First, parse the command-line arguments.
    //
    for (i=1; i<argc; i++) {
    int tmp;
    char c;
    if (sscanf(argv[i], "-a%d%c", &tmp, &c) == 1) {
    channels[0] = tmp;
    } else if (sscanf(argv[i], "-b%d%c", &tmp, &c) == 1) {
    channels[1] = tmp;
    } else if (sscanf(argv[i], "-c%d%c", &tmp, &c) == 1) {
    channels[2] = tmp;
    } else if (sscanf(argv[i], "-d%d%c", &tmp, &c) == 1) {
    channels[3] = tmp;
    } else if (sscanf(argv[i], "-B%d%c", &tmp, &c) == 1) {
    switch (tmp) {
    case 1000 : Bitrate = canBITRATE_1M; break;
    case 500 : Bitrate = canBITRATE_500K; break;
    case 250 : Bitrate = canBITRATE_250K; break;
    case 125 : Bitrate = canBITRATE_125K; break;
    default : Usage(argc, argv);
    }
    } else if (strcmp(argv[i], "-v") == 0) {
    Verbose++;
    } else if (sscanf(argv[i], "-L%d%c", &tmp, &c) == 1) {
    MaxLoops = tmp;
    } else {
    Usage(argc, argv);
    }
    }
    printf("\nCANLIB Thread Test 4\n");
    memset(TotalSent, 0, sizeof(TotalSent));
    memset(TotalReceived, 0, sizeof(TotalReceived));
    InitializeCriticalSection(&cs);
    TimeToLeave = FALSE;
    t1 = t2 = t3 = t4 = NULL;
    if (channels[0] != 99) t1 = CreateThread(NULL, 0, SendAndReceive, (LPVOID)0, CREATE_SUSPENDED, &tid);
    if (channels[1] != 99) t2 = CreateThread(NULL, 0, SendAndReceive, (LPVOID)1, CREATE_SUSPENDED, &tid);
    if (channels[2] != 99) t3 = CreateThread(NULL, 0, ReadOne, (LPVOID)2, CREATE_SUSPENDED, &tid);
    if (channels[3] != 99) t4 = CreateThread(NULL, 0, Sink, (LPVOID)3, CREATE_SUSPENDED, &tid);
    printf("\n");
    if (t1) printf("SendAndReceive on channel %d\n", channels[0]);
    if (t2) printf("SendAndReceive on channel %d\n", channels[1]);
    if (t3) printf("ReadOne on channel %d\n", channels[2]);
    if (t4) printf("Sink on channel %d\n", channels[3]);
    printf("\n");
    for (i=0; i<4; i++) events[i] = CreateEvent(0, FALSE, FALSE, 0);
    ResumeThread(t1);
    ResumeThread(t2);
    ResumeThread(t3);
    ResumeThread(t4);
    Sleep(100);
    for (i=0; i<4; i++) SetEvent(events[i]);
    while (TRUE) {
    Sleep(200);
    if (_kbhit()) {
    _getch();
    break;
    }
    if (--MaxLoops == 0) break;
    }
    TimeToLeave = TRUE;
    WaitForSingleObject(t1, 2000);
    WaitForSingleObject(t2, 2000);
    WaitForSingleObject(t3, 2000);
    WaitForSingleObject(t4, 2000);
    printf("\nChannel Sent Received\n");
    for (i=0; i<4; i++) {
    printf("%7d%10ld%13ld\n", channels[i], TotalSent[i], TotalReceived[i]);
    }
    }
    【网站地图】【sitemap】