______________________________________________________________________ > < > CAN bus driver v1.00 < > for < > PICos release 1.02 < > < > PICOS - Real-time kernel for PIC24/PIC30/PIC33 families < > < > < > www.picos18.com www.pragmatec.net < >______________________________________________________________________< This file contains all necessary informations to use properly the PIC CAN driver for PICos v1.xx. This driver let you design a multi-task application using the same CAN port without being concerned by the CAN shared access. Then every task of your application can send messages without being necessarily synchronised to the others. ______________________________________________________________________ > < > I - Zip file content < >______________________________________________________________________< The drv_can zip file contains : - drv_can.c - drv_can.h : header file - drv_can.txt : this file To use the PICos CAN driver, first unzip the file. Place the C and H file in your project directory. This driver is supposed to be use with PICos and has been tested with MPLAB 7.30 and C30 v2.00. Do not use this driver at a frequency lower than 8 Mhz (use the PIC PLL to increase the internal frequency). ______________________________________________________________________ > < > II - Hardware settings < >______________________________________________________________________< The driver is able to run in loopback mode. It means you can run your application with this driver without necessarily being connected to a real network. To activate the loopback mode, add the following compiler option in the MPLAB C30 panel of the Build Options window : __LOOPBACK__ The basic job of the driver is to filter the incoming message by software. If a task is waiting for a certain CAN ID, the CAN driver is in charge of waking the waiting task as soon as the expected message arrives. To disable this feature and so to force the driver to wake up ALL the task of your application each time a new message arrives, add the following option in the MPLAB C30 panel of the Build Options window : __NOFILTER__ In a current usage, you don't have to activate these both options. For instance the LOOPBACK mode could be use to test the hardware before starting the application and the NOFILTER option may be use to design a kind of software bus analyser. Moreover you HAVE to specify if you want to use this driver in 11 bits or in 29 bits mode (length of the CAN ID field). To activate the standart mode (11 bits) add the following option in the MPLAB C30 panel of the Build Options window : __SDT11BITS__ To activate the extended mode (29 bits) add the following option in the MPLAB C30 panel of the Build Options window : __EXT29BITS__ If you forget to select any one of the modes, the compiler will exit with an error message : "you should define 11 or 29 bits for CANID !" ______________________________________________________________________ > < > III - TASCDESC settings (1) < >______________________________________________________________________< Update also the tascdesc.c file to take into account the new CAN driver in your application : /********************************************************************** * ----------------------- TASK & STACK DEFINITION -------------------- **********************************************************************/ DeclareTask(Example); DeclareTask(CAN_Drv); ... volatile unsigned char stack0[DEFAULT_STACK_SIZE]; u_int __attribute__((__section__(".stack_tskcan"))) stack_can[DEFAULT_STACK_SIZE]; ... ______________________________________________________________________ > < > IV - TASCDESC settings (2) < >______________________________________________________________________< Finally add the task and alarm descriptor to the tascdesc.c file : ... /******************************************************************* * -------------------------- Task CAN ------------------------------ *******************************************************************/ { SREG(stack_can), /* Stack_register */ FREG(stack_can), /* Frame_register */ CAN_Drv, /* StartAddress */ stack_can, /* StackAddress */ sizeof(stack_can), /* StackSize */ CAN_DRV_ID, /* TaskID */ DRV_CAN_PRIO, /* Priority */ NONE, /* EventWaited */ NONE, /* EventReceived */ READY, /* State */ EXTENDED, /* Type */ 0, /* Time */ NULL /* next */ } ... To use the CAN we propose an EXAMPLE task that send some messages periodicaly. Because the task is a periodic one, we create an alarm : AlarmObject Alarm_list[] = { /******************************************************************* * ----------------------- Example task ---------------------------- *******************************************************************/ { OFF, /* State */ 0, /* AlarmValue */ 0, /* Cycle */ &Counter_kernel, /* ptrCounter */ Example, /* TaskID2Activate */ ALARM_EVENT, /* EventToPost */ 0 /* CallBack */ } }; ______________________________________________________________________ > < > V - TASK Settings < >______________________________________________________________________< Open define.h and add these definitions with suitable values : #define ALARM_EVENT 0x80 #define CAN_NEW_MSG 0x02 #define CAN_RCV_MSG 0x04 #define CAN_ERR_MSG 0x08 #define CAN_QUEUE_FULL 0x01 #define CAN_QUEUE_EMPTY 0x02 ... #define CAN_DRV_ID 6 #define DRV_CAN_PRIO 8 #define EXAMPLE_ID 4 #define EXAMPLE_PRIO 5 The CAN task is considered to be a driver, that means you have to give one of the highest priority to the CAN driver to let it run each time the CAN buffer is updated. Adapt the values to your application is necessary (event values...). ______________________________________________________________________ > < > VI - ISR connection < >______________________________________________________________________< no correction du to direct interrupt vector. ______________________________________________________________________ > < > VII - CAN driver usage (1) < >______________________________________________________________________< In the task, you have first to specify a SIDL and SIDH values as a CAN ID. In this CAN driver release only the SIDH field is managed by the driver, then the CAN ID is 8 bits long only. Check the next release to be able to manage 21 bits CAN ID field. In the Example task, include the driver header: #include "drv_can.h" And declare a CAN message (type CAN_message_t): CAN_ message_t CAN_msg; See hereafter a basic example to send a "Test: xx" message with a counter value to a CAN network: #include "define.h" #include "drv_can.h" /* Replace by the correct value of your alarm ID */ #define CAN_TASK_ALARM 0 /********************************************************************** * Variables shared with the rest of application. **********************************************************************/ CAN_message_t SND1_message; unsigned char data1, data2; /********************************************************************** * ------------------------- Internal test TASK ----------------------- * * The task sends a CAN message every 3 secondes. * **********************************************************************/ TASK(CAN_sender) { SetRelAlarm(CAN_TASK_ALARM, 3000, 3000); SND1_message.CANID = 0x7AA; // SND1_message.CANID = 0x1A55AA55; // In 29 bits mode only SND1_message.length = 8; SND1_message.data[0] = 'T'; SND1_message.data[1] = 'e'; SND1_message.data[2] = 's'; SND1_message.data[3] = 't'; SND1_message.data[4] = ':'; SND1_message.data[5] = ' '; SND1_message.data[6] = '0'; SND1_message.data[7] = '0'; data1 = 0x30; data2 = 0x30; while (1) { WaitEvent(ALARM_EVENT); ClearEvent(ALARM_EVENT); data2++; if (data2 == 0x3A) { data2 = 0x30; data1++; if (data1 == 0x3A) data1 = 0x30; } SND1_message.data[6] = data1; SND1_message.data[7] = data2; CAN_enqMsg(&SND1_message); SetEvent(CAN_DRV_ID, CAN_NEW_MSG); /* Optionnal : we don't need to wait for end of transmission */ WaitEvent(CAN_QUEUE_EMPTY); ClearEvent(CAN_QUEUE_EMPTY); } } ______________________________________________________________________ > < > VIII - CAN driver usage (2) < >______________________________________________________________________< In your application you can have one or more task waiting for a certain can message (specifyed by a certai CAN ID). In the Example task, include the driver header: #include "drv_can.h" And declare a CAN message (type CAN_message_t): CAN_ message_t CAN_msg; See hereafter a basic example to wait for a message with a specific CAN ID value : #include "define.h" #include "drv_can.h" /* Replace by the correct value of your alarm ID */ #define CAN_TASK_ALARM 0 /********************************************************************** * Variables shared with the rest of application. **********************************************************************/ CAN_message_t RCV_message; unsigned char data1, data2, length; /********************************************************************** * ------------------------- Internal test TASK ----------------------- * * The task wait for the CAN message with 64 as SIDH CAN ID. * **********************************************************************/ TASK(CAN_reciever) { unsigned char i; RCV_message.CANID = 0x7AA; //RCV_message.CANID = 0x1A55AA55; // In 29 bits mode only CAN_RCV_Register(&RCV_message); while(1) { WaitEvent(CAN_QUEUE_FULL); ClearEvent(CAN_QUEUE_FULL); length = RCV_message.length; data1 = RCV_message.data[length-2]; data2 = RCV_message.data[length-1]; CAN_freeMsg(RCV_message); SetEvent(CAN_DRV_ID, CAN_RCV_MSG); } } ______________________________________________________________________ > < > IX - Conclusion < >______________________________________________________________________< With a such example here is what you should see on the CAN network : ID 64 : ID 64 : ID 64 : ID 64 : The code has been tested on the dsPIC30F6014 without any trouble. This CAN driver is provided from the PICos18 web site with other drivers dedicated to oher peripherals. Some zip files are also provided to be used with a driver. Error are taken into account by the CAN driver but not yet report in a structured log file. Do not hesitate to check periodicaly the www.picos18.com web site in order to download the last versions of PIC30 drivers for PICos. /* End of File : drv_can.txt */