-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
916e416
commit 1b65c84
Showing
1 changed file
with
180 additions
and
180 deletions.
There are no files selected for viewing
360 changes: 180 additions & 180 deletions
360
STM32F1/libraries/HardwareCAN/examples/HardwareCANexample/HardwareCANexample.ino
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,181 +1,181 @@ | ||
#include <HardwareCAN.h> | ||
#include "changes.h" | ||
/* | ||
* Example of use of the HardwareCAN library | ||
* This application receives two frames containing various data. It also produces data that are sent periodically using another two frames. | ||
* Please read the file changes.h to see the changes to be performed to the core in order to use this | ||
*/ | ||
// Define the values of the identifiers | ||
#define GYRO_ID 0x27 | ||
#define JOYSTICK_VALUES_ID 0x5A | ||
#define TANK_LEVEL_ID 0x78 | ||
#define MOTOR_CONTROL_ID 0x92 | ||
|
||
// Limit time to flag a CAN error | ||
#define CAN_TIMEOUT 100 | ||
#define CAN_DELAY 10 // ms between two processings of incoming messages | ||
#define CAN_SEND_RATE 200 // ms between two successive sendings | ||
|
||
// Message structures. Each message has its own identifier. As many such variables should be defined | ||
// as the number of different CAN frames the application has to send. Here, they are two. | ||
CanMsg msgGyroscope ; | ||
CanMsg msgMotorControl ; | ||
|
||
// Traffic handling data | ||
int CANquietTime ; // Quiet time counter to detect no activity on CAN bus | ||
bool CANError ; // Indicates that incoming CAN traffic is missing | ||
int CANsendDivider ; // Used to send frames once every so many times loop() is called | ||
|
||
// Applicaton variables | ||
int Contents[4] ; // Contents of the four tanks | ||
int JoystickX ; // Setting of the joystick, X axis | ||
int JoystickY ; // ... Y axis | ||
int AngularRate ; // Output of local gyroscope | ||
int Throttle ; // Motor control value, produced by some local processing | ||
bool ErreurGyroscope = false ; | ||
|
||
// Instanciation of CAN interface | ||
HardwareCAN canBus(CAN1_BASE); | ||
|
||
|
||
// Note : for the predefined identifiers, please have a look in file can.h | ||
|
||
void CANSetup(void) | ||
{ | ||
CAN_STATUS Stat ; | ||
|
||
// Initialize the message structures | ||
// A CAN structure includes the following fields: | ||
msgGyroscope.IDE = CAN_ID_STD; // Indicates a standard identifier ; CAN_ID_EXT would mean this frame uses an extended identifier | ||
msgGyroscope.RTR = CAN_RTR_DATA; // Indicated this is a data frame, as opposed to a remote frame (would then be CAN_RTR_REMOTE) | ||
msgGyroscope.ID = GYRO_ID ; // Identifier of the frame : 0-2047 (0-0x3ff) for standard idenfiers; 0-0x1fffffff for extended identifiers | ||
msgGyroscope.DLC = 3; // Number of data bytes to follow | ||
msgGyroscope.Data[0] = 0x0; // Data bytes, there can be 0 to 8 bytes. | ||
msgGyroscope.Data[1] = 0x0; | ||
msgGyroscope.Data[2] = 0x0; | ||
|
||
msgMotorControl.IDE = CAN_ID_STD; | ||
msgMotorControl.RTR = CAN_RTR_DATA; | ||
msgMotorControl.ID = MOTOR_CONTROL_ID ; | ||
msgMotorControl.DLC = 2; | ||
msgMotorControl.Data[0] = 0x0; | ||
msgMotorControl.Data[1] = 0x0; | ||
|
||
// Initialize CAN module | ||
canBus.map(CAN_GPIO_PB8_PB9); // This setting is already wired in the Olimexino-STM32 board | ||
Stat = canBus.begin(CAN_SPEED_125, CAN_MODE_NORMAL); // Other speeds go from 125 kbps to 1000 kbps. CAN allows even more choices. | ||
|
||
canBus.filter(0, 0, 0); | ||
canBus.set_irq_mode(); // Use irq mode (recommended), so the handling of incoming messages | ||
// will be performed at ease in a task or in the loop. The software fifo is 16 cells long, | ||
// allowing at least 15 ms before processing the fifo is needed at 125 kbps | ||
Stat = canBus.status(); | ||
if (Stat != CAN_OK) | ||
/* Your own error processing here */ ; // Initialization failed | ||
} | ||
|
||
// Send one frame. Parameter is a pointer to a frame structure (above), that has previously been updated with data. | ||
// If no mailbox is available, wait until one becomes empty. There are 3 mailboxes. | ||
CAN_TX_MBX CANsend(CanMsg *pmsg) | ||
{ | ||
CAN_TX_MBX mbx; | ||
|
||
do | ||
{ | ||
mbx = canBus.send(pmsg) ; | ||
#ifdef USE_MULTITASK | ||
vTaskDelay( 1 ) ; // Infinite loops are not multitasking-friendly | ||
#endif | ||
} | ||
while(mbx == CAN_TX_NO_MBX) ; // Waiting outbound frames will eventually be sent, unless there is a CAN bus failure. | ||
return mbx ; | ||
} | ||
|
||
// Process incoming messages | ||
// Note : frames are not fully checked for correctness: DLC value is not checked, neither are the IDE and RTR fields. However, the data is guaranteed to be corrrect. | ||
void ProcessMessages(void) | ||
{ | ||
int Pr = 0 ; | ||
int i ; | ||
|
||
CanMsg *r_msg; | ||
|
||
// Loop for every message in the fifo | ||
while ((r_msg = canBus.recv()) != NULL) | ||
{ | ||
CANquietTime = 0 ; // Reset at each received frame | ||
CANError = false ; // Clear CAN silence error | ||
switch ( r_msg->ID ) | ||
{ | ||
case TANK_LEVEL_ID : // This frame contains four 16-bit words, little endian coded | ||
for ( i = 0 ; i < 4 ; i++ ) | ||
Contents[i] = (int)r_msg->Data[2*i] | ((int)r_msg->Data[(2*i)+1]) << 8 ; | ||
break ; | ||
|
||
case JOYSTICK_VALUES_ID : // This frame contains two 16-bit words, little endian coded | ||
Pr = (int)r_msg->Data[0] ; | ||
Pr |= (int)r_msg->Data[1] << 8 ; | ||
JoystickX = Pr ; | ||
|
||
Pr = (int)r_msg->Data[2] ; | ||
Pr |= (int)r_msg->Data[3] << 8 ; | ||
JoystickY = Pr ; | ||
break ; | ||
|
||
default : // Any frame with a different identifier is ignored | ||
break ; | ||
} | ||
|
||
canBus.free(); // Remove processed message from buffer, whatever the identifier | ||
#ifdef USE_MULTITASK | ||
vTaskDelay( 1 ) ; // Infinite loops are not multitasking-friendly | ||
#endif | ||
} | ||
} | ||
|
||
// Send messages | ||
// Prepare and send 2 frames containing the value of process variables | ||
// Sending all frames at once is a choice; they could be sent separately, at different times and rates. | ||
void SendCANmessages(void) | ||
{ | ||
// Prepare Gyroscope frame : send angular rate | ||
msgGyroscope.Data[0] = AngularRate & 0xff ; | ||
msgGyroscope.Data[1] = ( AngularRate >> 8 ) & 0xff ; | ||
msgGyroscope.Data[2] = ErreurGyroscope ? 1 : 0 ; | ||
CANsend(&msgGyroscope) ; // Send this frame | ||
|
||
msgMotorControl.Data[0] = Throttle & 0xff ; | ||
msgMotorControl.Data[1] = ( Throttle >> 8 ) & 0xff ; | ||
CANsend(&msgMotorControl) ; | ||
} | ||
|
||
// The application program starts here | ||
void setup() { | ||
// put your setup code here, to run once: | ||
CANSetup() ; // Initialize the CAN module and prepare the message structures. | ||
} | ||
|
||
void loop() { | ||
// Process incoming messages periodically (should be often enough to avoid overflowing the fifo) | ||
ProcessMessages() ; // Process all incoming messages, update local variables accordingly | ||
|
||
// This is an example of timeout management. Here it is global to all received frames; | ||
// it could be on a frame by frame basis, with as many control variables as the number of frames. | ||
CANquietTime++ ; | ||
if ( CANquietTime > CAN_TIMEOUT ) | ||
{ | ||
CANquietTime = CAN_TIMEOUT + 1 ; // To prevent overflowing this variable if silence prolongs... | ||
CANError = true ; // Flag CAN silence error. Will be cleared at first frame received | ||
} | ||
|
||
// Send messages containing variables to publish. Sent less frequently than the processing of incoming frames (here, every 200 ms) | ||
CANsendDivider-- ; | ||
if ( CANsendDivider < 0 ) | ||
{ | ||
CANsendDivider = CAN_SEND_RATE / CAN_DELAY ; | ||
SendCANmessages() ; | ||
} | ||
delay(CAN_DELAY) ; // The delay must not be greater than the time to overflow the incoming fifo (here about 15 ms) | ||
} | ||
|
||
#include <HardwareCAN.h> | ||
//#include "changes.h" | ||
/* | ||
* Example of use of the HardwareCAN library | ||
* This application receives two frames containing various data. It also produces data that are sent periodically using another two frames. | ||
* Please read the file changes.h to see the changes to be performed to the core in order to use this | ||
*/ | ||
// Define the values of the identifiers | ||
#define GYRO_ID 0x27 | ||
#define JOYSTICK_VALUES_ID 0x5A | ||
#define TANK_LEVEL_ID 0x78 | ||
#define MOTOR_CONTROL_ID 0x92 | ||
|
||
// Limit time to flag a CAN error | ||
#define CAN_TIMEOUT 100 | ||
#define CAN_DELAY 10 // ms between two processings of incoming messages | ||
#define CAN_SEND_RATE 200 // ms between two successive sendings | ||
|
||
// Message structures. Each message has its own identifier. As many such variables should be defined | ||
// as the number of different CAN frames the application has to send. Here, they are two. | ||
CanMsg msgGyroscope ; | ||
CanMsg msgMotorControl ; | ||
|
||
// Traffic handling data | ||
int CANquietTime ; // Quiet time counter to detect no activity on CAN bus | ||
bool CANError ; // Indicates that incoming CAN traffic is missing | ||
int CANsendDivider ; // Used to send frames once every so many times loop() is called | ||
|
||
// Applicaton variables | ||
int Contents[4] ; // Contents of the four tanks | ||
int JoystickX ; // Setting of the joystick, X axis | ||
int JoystickY ; // ... Y axis | ||
int AngularRate ; // Output of local gyroscope | ||
int Throttle ; // Motor control value, produced by some local processing | ||
bool ErreurGyroscope = false ; | ||
|
||
// Instanciation of CAN interface | ||
HardwareCAN canBus(CAN1_BASE); | ||
|
||
|
||
// Note : for the predefined identifiers, please have a look in file can.h | ||
|
||
void CANSetup(void) | ||
{ | ||
CAN_STATUS Stat ; | ||
|
||
// Initialize the message structures | ||
// A CAN structure includes the following fields: | ||
msgGyroscope.IDE = CAN_ID_STD; // Indicates a standard identifier ; CAN_ID_EXT would mean this frame uses an extended identifier | ||
msgGyroscope.RTR = CAN_RTR_DATA; // Indicated this is a data frame, as opposed to a remote frame (would then be CAN_RTR_REMOTE) | ||
msgGyroscope.ID = GYRO_ID ; // Identifier of the frame : 0-2047 (0-0x3ff) for standard idenfiers; 0-0x1fffffff for extended identifiers | ||
msgGyroscope.DLC = 3; // Number of data bytes to follow | ||
msgGyroscope.Data[0] = 0x0; // Data bytes, there can be 0 to 8 bytes. | ||
msgGyroscope.Data[1] = 0x0; | ||
msgGyroscope.Data[2] = 0x0; | ||
|
||
msgMotorControl.IDE = CAN_ID_STD; | ||
msgMotorControl.RTR = CAN_RTR_DATA; | ||
msgMotorControl.ID = MOTOR_CONTROL_ID ; | ||
msgMotorControl.DLC = 2; | ||
msgMotorControl.Data[0] = 0x0; | ||
msgMotorControl.Data[1] = 0x0; | ||
|
||
// Initialize CAN module | ||
canBus.map(CAN_GPIO_PB8_PB9); // This setting is already wired in the Olimexino-STM32 board | ||
Stat = canBus.begin(CAN_SPEED_125, CAN_MODE_NORMAL); // Other speeds go from 125 kbps to 1000 kbps. CAN allows even more choices. | ||
|
||
canBus.filter(0, 0, 0); | ||
canBus.set_irq_mode(); // Use irq mode (recommended), so the handling of incoming messages | ||
// will be performed at ease in a task or in the loop. The software fifo is 16 cells long, | ||
// allowing at least 15 ms before processing the fifo is needed at 125 kbps | ||
Stat = canBus.status(); | ||
if (Stat != CAN_OK) | ||
/* Your own error processing here */ ; // Initialization failed | ||
} | ||
|
||
// Send one frame. Parameter is a pointer to a frame structure (above), that has previously been updated with data. | ||
// If no mailbox is available, wait until one becomes empty. There are 3 mailboxes. | ||
CAN_TX_MBX CANsend(CanMsg *pmsg) | ||
{ | ||
CAN_TX_MBX mbx; | ||
|
||
do | ||
{ | ||
mbx = canBus.send(pmsg) ; | ||
#ifdef USE_MULTITASK | ||
vTaskDelay( 1 ) ; // Infinite loops are not multitasking-friendly | ||
#endif | ||
} | ||
while(mbx == CAN_TX_NO_MBX) ; // Waiting outbound frames will eventually be sent, unless there is a CAN bus failure. | ||
return mbx ; | ||
} | ||
|
||
// Process incoming messages | ||
// Note : frames are not fully checked for correctness: DLC value is not checked, neither are the IDE and RTR fields. However, the data is guaranteed to be corrrect. | ||
void ProcessMessages(void) | ||
{ | ||
int Pr = 0 ; | ||
int i ; | ||
|
||
CanMsg *r_msg; | ||
|
||
// Loop for every message in the fifo | ||
while ((r_msg = canBus.recv()) != NULL) | ||
{ | ||
CANquietTime = 0 ; // Reset at each received frame | ||
CANError = false ; // Clear CAN silence error | ||
switch ( r_msg->ID ) | ||
{ | ||
case TANK_LEVEL_ID : // This frame contains four 16-bit words, little endian coded | ||
for ( i = 0 ; i < 4 ; i++ ) | ||
Contents[i] = (int)r_msg->Data[2*i] | ((int)r_msg->Data[(2*i)+1]) << 8 ; | ||
break ; | ||
|
||
case JOYSTICK_VALUES_ID : // This frame contains two 16-bit words, little endian coded | ||
Pr = (int)r_msg->Data[0] ; | ||
Pr |= (int)r_msg->Data[1] << 8 ; | ||
JoystickX = Pr ; | ||
|
||
Pr = (int)r_msg->Data[2] ; | ||
Pr |= (int)r_msg->Data[3] << 8 ; | ||
JoystickY = Pr ; | ||
break ; | ||
|
||
default : // Any frame with a different identifier is ignored | ||
break ; | ||
} | ||
|
||
canBus.free(); // Remove processed message from buffer, whatever the identifier | ||
#ifdef USE_MULTITASK | ||
vTaskDelay( 1 ) ; // Infinite loops are not multitasking-friendly | ||
#endif | ||
} | ||
} | ||
|
||
// Send messages | ||
// Prepare and send 2 frames containing the value of process variables | ||
// Sending all frames at once is a choice; they could be sent separately, at different times and rates. | ||
void SendCANmessages(void) | ||
{ | ||
// Prepare Gyroscope frame : send angular rate | ||
msgGyroscope.Data[0] = AngularRate & 0xff ; | ||
msgGyroscope.Data[1] = ( AngularRate >> 8 ) & 0xff ; | ||
msgGyroscope.Data[2] = ErreurGyroscope ? 1 : 0 ; | ||
CANsend(&msgGyroscope) ; // Send this frame | ||
|
||
msgMotorControl.Data[0] = Throttle & 0xff ; | ||
msgMotorControl.Data[1] = ( Throttle >> 8 ) & 0xff ; | ||
CANsend(&msgMotorControl) ; | ||
} | ||
|
||
// The application program starts here | ||
void setup() { | ||
// put your setup code here, to run once: | ||
CANSetup() ; // Initialize the CAN module and prepare the message structures. | ||
} | ||
|
||
void loop() { | ||
// Process incoming messages periodically (should be often enough to avoid overflowing the fifo) | ||
ProcessMessages() ; // Process all incoming messages, update local variables accordingly | ||
|
||
// This is an example of timeout management. Here it is global to all received frames; | ||
// it could be on a frame by frame basis, with as many control variables as the number of frames. | ||
CANquietTime++ ; | ||
if ( CANquietTime > CAN_TIMEOUT ) | ||
{ | ||
CANquietTime = CAN_TIMEOUT + 1 ; // To prevent overflowing this variable if silence prolongs... | ||
CANError = true ; // Flag CAN silence error. Will be cleared at first frame received | ||
} | ||
|
||
// Send messages containing variables to publish. Sent less frequently than the processing of incoming frames (here, every 200 ms) | ||
CANsendDivider-- ; | ||
if ( CANsendDivider < 0 ) | ||
{ | ||
CANsendDivider = CAN_SEND_RATE / CAN_DELAY ; | ||
SendCANmessages() ; | ||
} | ||
delay(CAN_DELAY) ; // The delay must not be greater than the time to overflow the incoming fifo (here about 15 ms) | ||
} | ||
|
||
|