Monday, March 26, 2007

CAN application using block device drivers

This simple application uses 2 threads to interact with a remote node on a Controller Area Network (CAN).

The remote node induces a 32-bit saw-tooth signal in a message with ID 0x1235, the thread called "thread3" in the TinKer program picks up the induced data (the red graph). It then subtracts 500 from each sample and returns the data to the network with a changed header (ID 0x1236) to distinguish the original signal from the echoed one (blue graph).

Additionally the root-thread induces a sinus wave (green graph).


The complete program with two threads...



The results viewed with the CANalyser tool from Vector

The code for the application:

/*
This example show how to use CAN block-device driver.

To enable this example, please modify the make.files file and re-run
make config
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/times.h>
#include <time.h>
#include <fcntl.h>
#include <pthread.h>
#include <assert.h>
#include <math.h>

#define PI 3.1415

typedef struct {
__uint32_t id;
__uint8_t data[8];
}CANmsg_t;


void *thread3(void *inpar );

void *thread3(void *inpar){
int psz,dlc,i,j,CAN, sawdata;
CANmsg_t CANmsg;

CAN=open("/dev/can0",O_RDWR);

for ( i=0;i<50000;i++){
assure( psz=read( CAN, &CANmsg, sizeof(CANmsg)));
dlc=psz-sizeof(__uint32_t);
if(CANmsg.id==0x1235){
CANmsg.id=0x1236;
sawdata=((__int32_t*)CANmsg.data)[0];
sawdata-=500;
((__int32_t*)CANmsg.data)[0]=sawdata;
assure( write( CAN, &CANmsg, sizeof(CANmsg)) == 0);
}
}
return 0x192837;
}


int main(int argc, char **argv){
pthread_t T3;
int i,CAN,Sini;
double angle,Sin;
CANmsg_t canM;

assert (pthread_create(&T3, NULL, thread3, 3) == 0);
CAN=open("/dev/can0",O_WRONLY);

for ( i=0;i<50000;i++){
msleep(10);
angle=angle+(2*PI)/360;
if (angle>(2*PI))
angle=0;
Sin=sin(angle);
Sini=1000000*Sin;
canM.id=0x1234;
memcpy(&canM.data,&Sini,sizeof(Sini));
assure(write(CAN,&canM,sizeof(canM)) ==0);
}
printf("program finished successfully...\n");
}