文章

RX Object Mode

Refer to NTCAN Application Developers Manual document charpter

  • 3.11 RX Object Mode
  • 4.1.1 canOpen, NTCAN_MODE_OBJECT
  • 4.3.1 canTake
  • 6.2.3 CMSG, len Bit 5 = No_Data (Object Mode)[Rx]

使用目的

If an application is only interested in the most recent data of a CAN message the handle can be initialized using the object mode instead of the default FIFO mode.

使用场景举例

假设在某个CAN总线中,有一个CAN装置专门收集户外温度,它每隔5分钟就会在总线上发送一次数据。数据是用固定的ID发送。总线上有一台主机执行的应用程序,已经配置好用Object mode receive方式读取此固定ID的数据。每当有新的数据发送过来,底层驱动都会为上层应用程序预备好最新的数据,供应用程序使用canTake()方式去读取。一旦有人要查询气温的时候,上层应用程序执行一次canTake(),就能把最新的数据展示给用户看。

Example code

  • objrx.c: 配置用Object Mode接收CAN ID为11-bit ID从0到4的5个CAN消息。每按一下空格键加回车键,就读取一次这5个ID的最新更新上来的数据。
  • 只能使用canTake()方式读取数据,不能使用canRead()方式读取数据。
  • canTake()方式读取数据,会马上返回,不会block程序执行。
  • Object mode receive只支持11-bit ID的CAN消息。
  • canTake()返回NTCAN_SUCCESS不代表有数据更新,需要去检查NTCAN_NO_DATA状态。Bit 5(NTCAN_NO_DATA) of CMSG.len为0说明有有效数据存在,如果为1说明No valid data存在。
uint32_t mode=NTCAN_MODE_OBJECT; /* mode bits for canOpen */
/* The rxqueuesize should be set to the maximum number of different
CAN messages (messages with different CAN-IDs) the application 
wants to receive. */
int32_t rxqueuesize=5; 
int32_t lenRcv=5;
CMSG cmsgObjRcv[5]; 

/* Initialize the id from 0 to 4 of the CMSG objects of interest. */ 
for (int i = 0; i < lenRcv; i++)
{
    cmsgObjRcv[i].id = i;
}
printf("press SPACE and then ENTER key to canTake() data once. \n");
while(1)
{
    // 0x20 is SPACE key number.
    if(getchar()==0x20)
    {
        retvalue = canTake(rxhandle, &cmsgObjRcv[0], &lenRcv);
        if(retvalue != NTCAN_SUCCESS)
        {
            printf("canTake() failed with error %d!\n", retvalue);
        }
        else
        { 
            for (int i = 0; i < lenRcv; i++)
            {
                /*check if Bit 5(NTCAN_NO_DATA) of CMSG.len is clear */
                if (!(cmsgObjRcv[i].len & 0x20))
                {
                    printf("Id: %d\n", cmsgObjRcv[i].id);
                    printf("Len: %d\n", (cmsgObjRcv[i].len & 0x0f));
                    for (int j=0;j<(cmsgObjRcv[i].len & 0x0f);j++)
                        printf("Byte %d: %#x\n", j, cmsgObjRcv[i].data[j]);
                    printf("\n");
                }
                else
                {
                    printf("Id %d: no valid data. \n\n", cmsgObjRcv[i].id);
                }
            }
            printf("================================\n");
        }
    }
}  

测试执行

  • 没有收到ID从0-4的CAN消息前,按空格加回车键读取一次所有5个ID的数据,都显示为no valid data。
bobtu@debian:~/ntcantest$ ./objrx
press SPACE and then ENTER key to canTake() data once.  
Id 0: no valid data. 
Id 1: no valid data. 
Id 2: no valid data. 
Id 3: no valid data. 
Id 4: no valid data. 
  • 向总线中发送如下CAN消息,按空格加回车键读取一次所有5个ID的数据,其中ID 0和1的数据更新了。

Id: 0
Len: 1
Byte 0: 0x23

Id: 1
Len: 2
Byte 0: 0x23
Byte 1: 0

Id 2: no valid data. 
Id 3: no valid data. 
Id 4: no valid data. 
  • 在总线中发送ID从0到4的任意数据,只有最新发送的数据才会被应用程序读取上来。