📄 documentation
字号:
Read baudrate (baudrate is calculated by driver): baudrate = ioctl(file, CANBUS4LINUX_GET_BAUDRATE, 0);Write baudrate (baudrate is calculated by driver): ioctl(file, CANBUS4LINUX_SET_BAUDRATE, <baudrate>);Read baudrate (baudrate is a constant): index = ioctl(file, CANBUS4LINUX_GET_BAUDRATE_BY_CONSTANT, 0);Write baudrate (baudrate is a constant): ioctl(file, CANBUS4LINUX_SET_BAUDRATE_BY_CONSTANT, <index of baudrates[] in property structure>);----------------------------------------------------------------------------Set CAN mode (2.0A or 2.0B)Set to CAN 2.0 A: ioctl(file, CANBUS4LINUX_SET_CAN_MODE, CANBUS_FORMAT_CAN_2_0_A);Set to CAN 2.0 B: ioctl(file, CANBUS4LINUX_SET_CAN_MODE, CANBUS_FORMAT_CAN_2_0_B);----------------------------------------------------------------------------Set default frame format:Set frame format in dependency of CAN mode. If CAN 2.0A is selected theframe format is always 11 bit (standard frame format). If CAN 2.0Bthe frame format can be 11 bit (CANBUS_TRANS_FMT_STD) or 29 bit (CANBUS_TRANS_FMT_EXT). Set to standard frames: ioctl(file, CANBUS4LINUX_SET_DEFAULT_FRAME_FORMAT, CANBUS_TRANS_FMT_STD);Set to extended frames: ioctl(file, CANBUS4LINUX_SET_DEFAULT_FRAME_FORMAT, CANBUS_TRANS_FMT_EXT);----------------------------------------------------------------------------Hardware test:Test if the hardware is installed. This is useful for external CAN devices, e.g for the parallel port or for USB or other ports. if (ioctl(file, CANBUS4LINUX_TEST_DEVICE, 0) > 0) { // CAN device is installed } else { // CAN device is not installed or an error ocured (return value < 0) }----------------------------------------------------------------------------Read time:With every event you get an absolute time stamp from the can driver. Also the actually timecan be read with this function. struct canbus_time time; ioctl(file, CANBUS4LINUX_READ_TIME, &time);The time is a 64 bit value, with a resolution of 1 microsecond. struct canbus_time { unsigned long low; unsigned long high; };If relative timings are needed, it must be calculated in the application, for example: .... time1 = read time with above function ... ... time2 = event from driver difference = time2 - time1 time1 = time2 ... ... time2 = event from driver difference = time2 - time1 ... ... etc. ----------------------------------------------------------------------------Transmit a CAN message:To transmit a message, this call is used. In CAN 2.0B mode the CAN id formatcan be specified in entry: "fmt" in the canbus_transmit_data structure.If this entry is 0, the default (set by: CANBUS4LINUX_SET_DEFAULT_FRAME_FORMAT)is used. In mode CAN 2.0A always standard frame format is used.Example: struct canbus_transmit_data data; data.fmt = 0; data.identifier = 0x1234 data.rtr = 0; data.dlc = 8; data.msg[0] = 0x11; data.msg[1] = 0x22; data.msg[2] = 0x33; data.msg[3] = 0x44; data.msg[4] = 0x55; data.msg[5] = 0x66; data.msg[6] = 0x77; data.msg[7] = 0x88; ioctl(file, CANBUS4LINUX_WRITE_TRANSMIT_DATA, &data);canbus_transmit_data structure: fmt Format of the transmitted CAN id CANBUS_TRANS_FMT_DEFAULT use default format set by ioctl(CANBUS4LINUX_SET_DEFAULT_FRAME_FORMAT) CANBUS_TRANS_FMT_STD force standard frame format CANBUS_TRANS_FMT_EXT force extended frame format (only useful in CAN 2.0B mode) identifier CAN identifier 11 or 29 bit rtr 0=data frame 1=remote transmission frame dlc data length code = number of valid entries in msg[] msg[] data bytes, maximal 8 bytes msg[0]...msg[7]----------------------------------------------------------------------------Event processing:The driver can send signals to the application. For example if followinglines are pass through after opening the CAN driver: fcntl(file,F_SETOWN,getpid()); fcntl(file,F_SETFL, FASYNC | fcntl(file,F_GETFL));To receive a signal in the application you need further code as shown here:void SignalFromDriver(int signum){ struct canbus_event data; while(1) { if (ioctl(file, CANBUS4LINUX_READ_EVENT_DATA, &data) <= 0) { break; } // interpret event: switch(data.event) { case CANBUS_EVENT_RECEIVED: // do something... break; case CANBUS_EVENT_TRANSMITTED: // do something... break; case CANBUS_EVENT_BUS_ERROR: // do something... break; case CANBUS_EVENT_WARNING: // do something... break; case CANBUS_EVENT_LEAVING_STANDBY: // do something... break; case CANBUS_EVENT_ARBITRATION_LOST: // do something... break; case CANBUS_EVENT_OVERRUN: // do something... break; case CANBUS_EVENT_PASSIVE: // do something... break; case CANBUS_EVENT_ENTERING_STANDBY: // do something... break; case CANBUS_EVENT_DEVICE_CHANGED: // do something... break; } } return;}void Init(){ // open CAN device and other initialization's file = open("/dev/can0",O_RDWR); if(file == -1) { printf("can't open canbus4linux device\n"); return; } else { // Because of the next 2 lines, a signal is generated on every event // (receiving, transmitting, errors, warnings,...) fcntl(file,F_SETOWN,getpid()); fcntl(file,F_SETFL, FASYNC | fcntl(file,F_GETFL)); } // now CAN device is ready to create signals // install signal handler struct sigaction sa; memset(&sa,0,sizeof(sa)); sa.sa_handler = Refresh; sa.sa_flags = SA_RESTART; sigaction(SIGIO,&sa,0);}All events are buffered in driver and at least one signal will be sent to theapplication. In the application all events are get with CANBUS4LINUX_READ_EVENT_DATA.****************************************************************************Implementing a layer 1 driver:Layer 1 driver (described in above model with SJA1000) need functions to:- open and close the CAN channel- 2 functions (read/write) for chip access with Reset-Bit=0- 2 functions (read/write) for chip access with Reset-Bit=1- a function to register a callback function from layer 2 for hardware interrupts- a function to free the callback from layer 2- if the driver have set CANBUS_CFS_POLLING, a callback function will not registered (this feature is not implemented yet!)Also the layer 2 (sja1000.o) need some information about the hardware and the layer 1driver:- bCanChipsetFlags With the following flags you specify the features of the hardware: CANBUS_CFS_CAN_2_0_A Chipset support CAN 2.0 A CANBUS_CFS_CAN_2_0_B Chipset support CAN 2.0 B CANBUS_CFS_EXT_FRAME Chipset support extended frame format This feature is used only if CANBUS_CFS_CAN_2_0_B is set CANBUS_CFS_POLLING Chipset driver supports only polling (not implemented yet) For a 82C200 chip the bits: CANBUS_CFS_2_0_B and CANBUS_CFS_EXT_FRAME are never set. - chipset_frequency Frequency of crystal (mostly 24MHz or 16 MHz, CAN200 project use 8MHz) This information is needed to calculate the baudrate- output_control_register The setting of this register in the SJA1000 chip. This information is needed to initialize the sja1000 chip.To register the driver at layer 2, a structure (sja_1000_access) must be filled out: struct sja1000_access { sja1000_openCanDevice pOpenCanDevice; sja1000_closeCanDevice pCloseCanDevice; sja1000_writeToRegister pWriteToRegister; sja1000_writeToRegisterRR pWriteToRegisterRR; sja1000_readFromRegister pReadFromRegister; sja1000_readFromRegisterRR pReadFromRegisterRR; sja1000_registerIsr pRegisterIsr; sja1000_unregisterIsr pUnregisterIsr; int bCanChipsetFlags; // show Flags: CANBUS_CSF_... int chipset_frequency; unsigned char output_control_register; };The first parameter in every function is a pointer to a user structure of the layer 1 driver. In this structure every driver can save settings and/or variables. Example: --------------------- registering -> | |-------------------- sja1000_register_device("name", <pointer to var.>, ...); | Layer 1 driver | | | | | | |<--------------------------------- | ---------| call functions; example: openCanDevice(<pointer to var.>); | | var. | | | | --------------------- var. = user structure of every driverWhile registering a layer 1 driver with "sja1000_register_device()", the pointer of this user structurewill be saved in the next layer 2 and will used in every function call.int openCanDevice(void *pSpecificPar); Parameter: pointer to user structure Return: standard return values (0 = OK) This function is called to open the can channel. In this function you can claim hardware resources. Don't initialize the CAN hardware in this function!int closeCanDevice(void *pSpecificPar); Parameter: pointer to user structure Return: standard return values (0 = OK) This function is called to close the can channel. In this function you can free hardware resources.void writeToRegister(void *pSpecificPar, unsigned char adr, unsigned char value); Parameter: pointer to user structure sja1000 register addresse (0...127) value to write This function is called to write data into sja1000. While access, the Reset-Bit should set to 0.void writeToRegisterRR(void *pSpecificPar, unsigned char adr, unsigned char value); Parameter: pointer to user structure sja1000 register addresse (0...127) value to write This function is called to write data into sja1000. While access, the Reset-Bit should set to 1.unsigned char readFromRegister(void *pSpecificPar, unsigned char adr); Parameter: pointer to user structure sja1000 register addresse (0...127) Return: value of sja1000 register This function is called to read data from sja1000. While access, the Reset-Bit should set to 0.unsigned char readFromRegisterRR(void *pSpecificPar, unsigned char adr); Parameter: pointer to user structure sja1000 register addresse (0...127) Return: value of sja1000 register This function is called to read data from sja1000. While access, the Reset-Bit should set to 1.****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -