CROSS Technical Documentation User Manual and Technical Doc.
INFN Milano Bicocca
Loading...
Searching...
No Matches
The CAN bus

Can Bus operation

SUMMARY:

User use of CAN bus



CAN bus, as well I2C, is a communication protocol based on the CMSIS drivers. Adaptation and use of some drivers is exploited, as it will be explained in the following. First of all it needs to read the hw parte of the the address of the board at some pins of the microcontroller. The addresses are set by means of some switches and the function to be used within the initialization function is lettura_indirizzi_CAN(). The function returns a char with the hw address.
After the communication is completed, either transmission or reception, the interrupt call the CAN_SignalObjectEvent() and CAN_SignalUnitEvent() that have as an input the var event that containes some flags.
The flags from CAN_SignalUnitEvent() are general from the CAN and are the following:


Table signal Interrupt: Flags of the mask event from CAN_SignalUnitEvent()
Parameter event Bit Description
ARM_CAN_EVENT_UNIT_INACTIVE 0 Unit entered Inactive state.
ARM_CAN_EVENT_UNIT_ACTIVE 1 Unit entered Error Active state.
ARM_CAN_EVENT_UNIT_WARNING 2 Unit entered Error Warning state (one or both error counters >= 96).
ARM_CAN_EVENT_UNIT_PASSIVE 3 Unit entered Error Passive state.
ARM_CAN_EVENT_UNIT_BUS_OFF 4 Unit entered Bus-off state.


CAN_SignalObjectEvent() merely marks the ened of operation and the event var that generates is replicated to the global evento_CAN with the flags that summarazies the results from the objcet under consideration, reception or transmission. In addition to the var event also the var obj_idx is a mark of the data transmission or reception.
The flags of evento_CAN have the following meaning:


Table object Interrput: Flags of the mask evento_I2C from CAN_SignalObjectEvent(). The row highlighted in red marks the state expected after a successfully communication.
Parameter event Bit Description
ARM_CAN_EVENT_SEND_COMPLETE 1 << 0 Message was sent successfully by the obj_idx object.
ARM_CAN_EVENT_RECEIVE 1 << 1 Message was received successfully by the obj_idx object.
ARM_CAN_EVENT_RECEIVE_OVERRUN 1 << 2 Message was overwritten before it was read on the obj_idx object.


The function CAN_Inizialize() is used once to set the CAN into operation. The speed of the bus is defined in CAN_speed. In CAN_Inizialize() the hw address is exploited to compose the final 29 bis long address.


To communicate with the CAN bus we exploit part of the structure of functions from CMSIS. The structure typedef is this:

typedef struct _ARM_DRIVER_CAN {
ARM_DRIVER_VERSION (*GetVersion) (void); ///< Pointer to \ref ARM_CAN_GetVersion : Get driver version.
ARM_CAN_CAPABILITIES (*GetCapabilities) (void); ///< Pointer to \ref ARM_CAN_GetCapabilities : Get driver capabilities.
int32_t (*Initialize) (ARM_CAN_SignalUnitEvent_t cb_unit_event,
ARM_CAN_SignalObjectEvent_t cb_object_event); ///< Pointer to \ref ARM_CAN_Initialize : Initialize CAN interface.
int32_t (*Uninitialize) (void); ///< Pointer to \ref ARM_CAN_Uninitialize : De-initialize CAN interface.
int32_t (*PowerControl) (ARM_POWER_STATE state); ///< Pointer to \ref ARM_CAN_PowerControl : Control CAN interface power.
uint32_t (*GetClock) (void); ///< Pointer to \ref ARM_CAN_GetClock : Retrieve CAN base clock frequency.
int32_t (*SetBitrate) (ARM_CAN_BITRATE_SELECT select,
uint32_t bitrate,
uint32_t bit_segments); ///< Pointer to \ref ARM_CAN_SetBitrate : Set bitrate for CAN interface.
int32_t (*SetMode) (ARM_CAN_MODE mode); ///< Pointer to \ref ARM_CAN_SetMode : Set operating mode for CAN interface.
ARM_CAN_OBJ_CAPABILITIES (*ObjectGetCapabilities) (uint32_t obj_idx); ///< Pointer to \ref ARM_CAN_ObjectGetCapabilities : Retrieve capabilities of an object.
int32_t (*ObjectSetFilter) (uint32_t obj_idx,
ARM_CAN_FILTER_OPERATION operation,
uint32_t id,
uint32_t arg); ///< Pointer to \ref ARM_CAN_ObjectSetFilter : Add or remove filter for message reception.
int32_t (*ObjectConfigure) (uint32_t obj_idx,
ARM_CAN_OBJ_CONFIG obj_cfg); ///< Pointer to \ref ARM_CAN_ObjectConfigure : Configure object.
int32_t (*MessageSend) (uint32_t obj_idx,
ARM_CAN_MSG_INFO *msg_info,
const uint8_t *data,
uint8_t size); ///< Pointer to \ref ARM_CAN_MessageSend : Send message on CAN bus.
int32_t (*MessageRead) (uint32_t obj_idx,
ARM_CAN_MSG_INFO *msg_info,
uint8_t *data,
uint8_t size); ///< Pointer to \ref ARM_CAN_MessageRead : Read message received on CAN bus.
int32_t (*Control) (uint32_t control,
uint32_t arg); ///< Pointer to \ref ARM_CAN_Control : Control CAN interface.
ARM_CAN_STATUS (*GetStatus) (void); ///< Pointer to \ref ARM_CAN_GetStatus : Get CAN status.
} const ARM_DRIVER_CAN;


We use only CAN1 which is defined here:

ARM_DRIVER_CAN Driver_CAN1 = {
CAN_GetVersion,
CAN_GetCapabilities,
CAN1_Initialize,
CAN1_Uninitialize,
CAN1_PowerControl,
CAN1_GetClock,
CAN1_SetBitrate,
CAN1_SetMode,
CAN1_ObjectGetCapabilities,
CAN1_ObjectSetFilter,
CAN1_ObjectConfigure,
CAN1_MessageSend, //This is the function exploited for transmission
CAN1_MessageRead, //This is the function exploited for reception
CAN1_Control,
CAN1_GetStatus
};
ARM_DRIVER_CAN Driver_CAN1
Viene inclusa la Periferica CAN1.


We exploit mainly CAN1_MessageSend, for transmission, CAN1_MessageRead, for reception. If a polling is needed tehere are 3 varaibles that can be used. The first was mentioned above and is evento_CAN that assumes value according to Table Table_interrupt_obj_event. This variable marks a concluded reception or transmission. Other 2 boolean variables have been introduced, messaggio_CAN_arrivato and messaggio_CAN_spedito that are set to true when the operation is conlcuded. In case these 2 variables are used they need to be set to false just before the CAN operation is started.

Remarks
There are several available functions. we exploit only a few of them. Some are exploited in CAN_Inizialize(). Two important functions we need to consider are the transmission and reception. Although we use only one of the 2 available CAN bus, for generality an example of the suggested use is as it follows:
extern ARM_DRIVER_CAN Driver_CAN1; // Viene inclusa la Periferica CAN1
ARM_DRIVER_CAN *CANdrv= &Driver_CAN1; //!< Puntatore alla periferica CAN
tx_msg_info.id = ARM_CAN_EXTENDED_ID(some_address); //In case it needs to specify the address
CANdrv->MessageSend(tx_obj_idx, &tx_msg_info, tx_data, 8U);
while( messaggio_CAN_spedito==false ); // Wait transmission completes, if we need to wait
CANdrv->MessageRead(rx_obj_idx, &rx_msg_info, (uint8_t *) rx_data, 8U);
while( messaggio_CAN_arrivato == false ); // Wait reception completes, if we need to wait
uint8_t tx_data[8]
Transmission data vector.
Definition: Can.c:321
uint32_t tx_obj_idx
This is the variable which resembles the flags from the communication.
Definition: Can.c:323
bool messaggio_CAN_arrivato
This variable is set to true as soon as a reception have been concluded.
Definition: Can.c:328
volatile uint8_t rx_data[8]
Received data vector.
Definition: Can.c:318
ARM_DRIVER_CAN * CANdrv
Definition: Can.c:333
bool messaggio_CAN_spedito
This variable is set to true as soon as a transmission have been concluded.
Definition: Can.c:329

Note
To the CAN a generic address is assigned. Every board will answer to this address. To identify the answer of the board of interest only the board should be connecte to the bus or oits switch is the "generic address" position. The generic address set is the following indirizzo_generico_CAN:
13#define indirizzo_generico_CAN 0xAAAAAAA /*< CAN generic address*/
Remarks
Another polling alternative is this:
CANdrv->MessageSend(tx_obj_idx, &tx_msg_info, tx_data, 8U);
while( evento_CAN !=ARM_CAN_EVENT_SEND_COMPLETE ){} // Wait transmission completes, if we need to wait
CANdrv->MessageRead(rx_obj_idx, &rx_msg_info, (uint8_t *) rx_data, 8U);
while( evento_CAN != ARM_CAN_EVENT_RECEIVE ); // Wait reception completes, if we need to wait
uint32_t volatile evento_CAN
This is the variable which resembles the flags from the communication.
Definition: Can.c:326



See also
That shown above is an extraction of the documentation from CMSIS drivers. For a complete reference to the CAN bus driver from CMSIS see the webs at Keil or ARM (in case of failure of either):


The codes for CAN bus is at: