uint32_t CAN::getMailbox(CANListener* listener, uint32_t src, uint32_t srcMask) { ASSERT(_tableIdx<32); _table[_tableIdx].listener = listener; _table[_tableIdx].src = src; _table[_tableIdx].mode = RECV; _table[_tableIdx].srcMask = srcMask; _table[_tableIdx].msgObject = (tCANMsgObject*) Sys::malloc( sizeof(tCANMsgObject)); _table[_tableIdx].msgObject->pucMsgData = (unsigned char*) Sys::malloc(8); _table[_tableIdx].msgObject->ulMsgID = src; _table[_tableIdx].msgObject->ulMsgIDMask = srcMask; _table[_tableIdx].msgObject->ulMsgLen = 8; _table[_tableIdx].msgObject->ulFlags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; CANMessageSet(_CAN_BASE, _tableIdx + 1, _table[_tableIdx].msgObject, MSG_OBJ_TYPE_RX); // CANIntEnable(_CAN_BASE, _tableIdx + 1); _tableIdx++; _table[_tableIdx].msgObject = (tCANMsgObject*) Sys::malloc( sizeof(tCANMsgObject)); _table[_tableIdx].listener = listener; _table[_tableIdx].mode = SEND; _tableIdx++; return _tableIdx - 2; }
void platform_can_send( unsigned id, u32 canid, u8 idtype, u8 len, const u8 *data ) { tCANMsgObject msg_tx; const char *s = ( char * )data; char *d; // Wait for outgoing messages to clear while( can_tx_flag == 1 ); msg_tx.ulFlags = MSG_OBJ_TX_INT_ENABLE; if( idtype == ELUA_CAN_ID_EXT ) msg_tx.ulFlags |= MSG_OBJ_EXTENDED_ID; msg_tx.ulMsgIDMask = 0; msg_tx.ulMsgID = canid; msg_tx.ulMsgLen = len; msg_tx.pucMsgData = ( u8 * )can_tx_buf; d = can_tx_buf; DUFF_DEVICE_8( len, *d++ = *s++ ); can_tx_flag = 1; CANMessageSet(CAN0_BASE, 2, &msg_tx, MSG_OBJ_TYPE_TX); }
int getFormMachine(char* id) { int value = -999; // error code int rc = 0; g_MsgObjectRx.ulMsgID = (0x400); g_MsgObjectRx.ulMsgIDMask = 0x7f8; g_MsgObjectRx.ulFlags = MSG_OBJ_USE_ID_FILTER; g_MsgObjectRx.ulMsgLen = snprintf(ucBufferIn, BUFFER_LEN, "%s", id, value); g_MsgObjectRx.pucMsgData = ucBufferIn; CANMessageSet(CAN0_BASE, 1, &g_MsgObjectRx, MSG_OBJ_TYPE_RX); printf("getFormMachine Message: %s\n", g_MsgObjectRx.pucMsgData); while((CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT)) & 1 == 0) { } CANMessageGet(CAN0_BASE, 1, &g_MsgObjectRx, true); value = atoi(strstr(g_MsgObjectRx.pucMsgData) + 1); printf("getFromMachine GetMessage: %s\n", g_MsgObjectRx.pucMsgData); return rc; return value; }
void BCAN_init(unsigned long bitRate) { tCANMsgObject sCANMessage; //unsigned char ucMsgData[8]; GPIO_PORTE_AFSEL_R |= 0x30; //PORTE AFSEL bits 5,4 GPIO_PORTE_PCTL_R = (GPIO_PORTE_PCTL_R&0xFF00FFFF)|0x00880000; GPIO_PORTE_DEN_R |= 0x30; GPIO_PORTE_DIR_R |= 0x20; CAN_RX_FIFOFifo_Init(); OS_InitSemaphore(&CANmessagesReceived,0); CANInit(CAN0_BASE); CANBitRateSet(CAN0_BASE, 80000000, 250000); //CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); //these are enabled later with a seperate call //IntEnable(INT_CAN0); //since the filesystem can't seem to initialize while the ECU is shooting out CAN messages //CANEnable(CAN0_BASE); sCANMessage.ulMsgID = 0; // CAN msg ID - 0 for any sCANMessage.ulMsgIDMask = 0; // mask is 0 for any ID sCANMessage.ulFlags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; sCANMessage.ulMsgLen = 8; // allow up to 8 bytes CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); }
//******************************************************************************* // app_can_SetupMultipleMsg //******************************************************************************* void app_can_SendMultipleMsg(const uint64_t* pui64_msg, const uint16_t msg_length) //msg_length is in Byte (max. is 256 Byte) { const uint8_t CAN8BytePacketsNo = msg_length/8; // CAN 8-byte Packets number to transmit uint8_t CANByteOnLastPacket = msg_length%8; // Byte to transmit with last CAN frame (last frame could have length = 8 Bytes) uint8_t notExistShortCANPacket; uint8_t MsgVectorLastIndex; if(CANByteOnLastPacket) { // If you need to transmit a CAN frame with n < 8 bytes of data notExistShortCANPacket = 0; // exist a CAN frame which data length is < 8 bytes MsgVectorLastIndex = CAN8BytePacketsNo; // thus last index of the CAN messages vector is "CAN8BytePacketsNo". } // Note that ther's some 8 bytes packets and further (shorter) packet // if all CAN frame which data length is < 8 bytes else { // If all CAN frame are 8 Bytes lenght notExistShortCANPacket = 1; // not exist a CAN frame which data length is < 8 bytes, MsgVectorLastIndex = CAN8BytePacketsNo - 1; // thus last index of the CAN messages vector is "CAN8BytePacketsNo - 1". } tCANMsgObject sCANMsgObject[CAN8BytePacketsNo]; // Declaration of "msg_lenght" CANMSGObject structure if(CANByteOnLastPacket==0) CANByteOnLastPacket=8; // Impossible to have CANByteOnLastPacket=0. If it's =0, means // the last packet is an 8-bytes packet. // It occurs when msg_length is an integer multiple of 8: (8,16,24,...). /*____________________initialize and set all but the last CAN Message Objects_________________________*/ volatile uint8_t i; for(i=0; i<=(CAN8BytePacketsNo - notExistShortCANPacket - 1); i++) { sCANMsgObject[i].ui32MsgID = CANMSG_ID; sCANMsgObject[i].ui32MsgIDMask = 0; sCANMsgObject[i].ui32Flags = MSG_OBJ_TX_INT_ENABLE | MSG_OBJ_FIFO; // frame put into CAN message FIFO queue. sCANMsgObject[i].ui32MsgLen = 8; // 8 byte each frame sCANMsgObject[i].pui8MsgData = (uint8_t*) &pui64_msg[i]; CANMessageSet(CAN0_BASE,i+1,&sCANMsgObject[i], MSG_OBJ_TYPE_TX); // ObjId is in the range [1-32], not [0-31]. } /*________________________initialize and set the last CAN Message Objects____________________________*/ // if exist a CAN frame which data length is < 8 bytes, then vector index of last CAN frame is "CAN8BytePacketsNo + 1" // if NOT exist a CAN frame which data length is < 8 bytes, then vector index of last CAN frame is "CAN8BytePacketsNo" sCANMsgObject[MsgVectorLastIndex].ui32MsgID = CANMSG_ID; sCANMsgObject[MsgVectorLastIndex].ui32MsgIDMask = 0; sCANMsgObject[MsgVectorLastIndex].ui32Flags = MSG_OBJ_TX_INT_ENABLE; // On last frame must no exist flag MSG_OBJ_FIFO sCANMsgObject[MsgVectorLastIndex].ui32MsgLen = CANByteOnLastPacket; sCANMsgObject[MsgVectorLastIndex].pui8MsgData = (uint8_t*) &pui64_msg[MsgVectorLastIndex]; CANMessageSet(CAN0_BASE,MsgVectorLastIndex+1,&sCANMsgObject[MsgVectorLastIndex], MSG_OBJ_TYPE_TX); // ObjId is in the range [1-32], not [0-31]. }
void setup(){ Serial.begin(9600); Serial.println("DEBUG1"); SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); SysCtlPeripheralEnable(GPIO_PORTE_BASE); GPIOPinTypeCAN(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5); GPIOPinConfigure(GPIO_PE4_CAN0RX); GPIOPinConfigure(GPIO_PE5_CAN0TX); tCANMsgObject sCANMessage; uint8_t ucMsgData[8]; Serial.println("DEBUG2"); uint8_t pui8BufferIn[8]; uint8_t pui8BufferOut[8]; Serial.println("DEBUG3"); CANInit(CAN0_BASE); CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); CANEnable(CAN0_BASE); sCANMessage.ui32MsgID = 0; // CAN msg ID - 0 for any sCANMessage.ui32MsgIDMask = 0; // mask is 0 for any ID sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; sCANMessage.ui32MsgLen = 8; // allow up to 8 bytes // // Now load the message object into the CAN peripheral. Once loaded the // CAN will receive any message on the bus, and an interrupt will occur. // Use message object 1 for receiving messages (this is not the same as // the CAN ID which can be any value in this example). // CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); Serial.println("DEBUG5"); while((CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT) & 1) == 0) { // // Read the message out of the message object. // CANMessageGet(CAN0_BASE, 1, &sCANMessage, true); Serial.println(sCANMessage.ui32MsgLen); } Serial.println(sCANMessage.ui32MsgLen); Serial.println(sCANMessage.ui32MsgID); }
//Set up a message object. Can be a TX object or an RX object. void static CAN0_Setup_Message_Object( unsigned long MessageID, \ unsigned long MessageFlags, \ unsigned long MessageLength, \ unsigned char * MessageData, \ unsigned long ObjectID, \ tMsgObjType eMsgType){ tCANMsgObject xTempObject; xTempObject.ulMsgID = MessageID; // 11 or 29 bit ID xTempObject.ulMsgLen = MessageLength; xTempObject.pucMsgData = MessageData; xTempObject.ulFlags = MessageFlags; CANMessageSet(CAN0_BASE, ObjectID, &xTempObject, eMsgType); }
void NetworkMsgInit(void) { g_MsgRx.ulMsgID = MSG_ID_RX; g_MsgRx.ulMsgIDMask = 0; g_MsgRx.ulFlags = MSG_OBJ_RX_INT_ENABLE; g_MsgRx.ulMsgLen = 4; g_MsgRx.pucMsgData = (unsigned char *)&g_ulRxData; CANMessageSet(CAN0_BASE, MSG_NUM_RX, &g_MsgRx, MSG_OBJ_TYPE_RX); g_MsgTx.ulMsgID = MSG_ID_TX; g_MsgTx.ulMsgIDMask = 0; g_MsgTx.ulFlags = 0; g_MsgTx.ulMsgLen = 4; }
//***************************************************************************** // // This function handles connection with the other CAN device and also // handles incoming commands. // // /return None. // //***************************************************************************** void CANMain(void) { unsigned char pucData[8]; // // The data has been received. // if((g_ulFlags & FLAG_DATA_RECV) == 0) { return; } // // Read the data from the message object. // g_MsgObjectRx.pucMsgData = pucData; g_MsgObjectRx.ulMsgLen = 8; CANMessageGet(CAN0_BASE, MSGOBJ_NUM_DATA_RX, &g_MsgObjectRx, 1); // // Indicate that the data has been read. // g_ulFlags &= (~FLAG_DATA_RECV); switch(g_MsgObjectRx.pucMsgData[0]) { case CMD_GET_VERSION: { // // Send the Version. // g_ulFlags |= FLAG_DATA_TX_PEND; g_MsgObjectTx.pucMsgData = (unsigned char *)&g_ulVersion; g_MsgObjectTx.ulMsgLen = 4; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_DATA_TX, &g_MsgObjectTx, MSG_OBJ_TYPE_TX); } } // // Clear the flag. // g_ulFlags &= ~(FLAG_DATA_RECV); }
//***************************************************************************** // // This functions sends out a button update message. // //***************************************************************************** void SendMessage(unsigned char *data,volatile unsigned long count) { tx_msg_object.ulFlags = MSG_OBJ_EXTENDED_ID; tx_msg_object.ulMsgID = 0x10; tx_msg_object.ulMsgIDMask = 0; tx_msg_object.ulMsgLen = 8; tx_msg_object.pucMsgData = data; //allocate memory for TX buffer tx_msg_object.pucMsgData[0] = 1 + count; tx_msg_object.pucMsgData[1] = 2 + count; tx_msg_object.pucMsgData[2] = 3 + count; tx_msg_object.pucMsgData[3] = 4 + count; tx_msg_object.pucMsgData[4] = 5 + count; tx_msg_object.pucMsgData[5] = 6 + count; tx_msg_object.pucMsgData[6] = 7 + count; tx_msg_object.pucMsgData[7] = 8 + count; CANMessageSet(CAN0_BASE, 1, &tx_msg_object, MSG_OBJ_TYPE_TX); }
//***************************************************************************** // // This functions sends out a button update message. // //***************************************************************************** void SendButtonMsg(unsigned char ucEvent, unsigned char ucButton) { // // Set the flag to indicate that a button status is being sent. // g_ulFlags |= FLAG_BUTTON_PEND; // // Send the button status. // g_MsgObjectButton.pucMsgData[0] = ucEvent; g_MsgObjectButton.pucMsgData[1] = ucButton; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_BUTTON, &g_MsgObjectButton, MSG_OBJ_TYPE_TX); }
//***************************************************************************** // // This function handles incoming commands. // //***************************************************************************** void ProcessCmd(void) { unsigned char pucData[8]; // // If no data has been received, then there is nothing to do. // if((g_ulFlags & FLAG_DATA_RECV) == 0) { return; } // // Receive the command. // g_MsgObjectRx.pucMsgData = pucData; g_MsgObjectRx.ulMsgLen = 8; CANMessageGet(CAN0_BASE, MSGOBJ_NUM_DATA_RX, &g_MsgObjectRx, 1); // // Clear the flag to indicate that the data has been read. // g_ulFlags &= (~FLAG_DATA_RECV); switch(g_MsgObjectRx.pucMsgData[0]) { // // This is a request for the firmware version for this application. // case CMD_GET_VERSION: { // // Send the Version. // g_ulFlags |= FLAG_DATA_TX_PEND; g_MsgObjectTx.pucMsgData = (unsigned char *)&g_ulVersion; g_MsgObjectTx.ulMsgLen = 4; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_DATA_TX, &g_MsgObjectTx, MSG_OBJ_TYPE_TX); break; } } }
//***************************************************************************** // // This function sends a message to retrieve the firmware version from the // target board. // //***************************************************************************** int CANGetTargetVersion(unsigned long *pulVersion) { static unsigned char ucVerCmd = CMD_GET_VERSION; // // If there was already a previous message being transmitted then just // return. // if(g_ulFlags & FLAG_DATA_TX_PEND) { return(-1); } // // A transmit request is about to be pending. // g_ulFlags |= FLAG_DATA_TX_PEND; // // Send the button update request. // g_MsgObjectTx.pucMsgData = &ucVerCmd; g_MsgObjectTx.ulMsgLen = 1; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_DATA_TX, &g_MsgObjectTx, MSG_OBJ_TYPE_TX); // // Wait for some data back from the target. // while ((g_ulFlags & FLAG_DATA_RECV) == 0) { } // // Read the data from the message object. // g_MsgObjectRx.pucMsgData = (unsigned char *)pulVersion; g_MsgObjectRx.ulMsgLen = 4; CANMessageGet(CAN0_BASE, MSGOBJ_NUM_DATA_RX, &g_MsgObjectRx, 1); return(0); }
int sendToMachine(char* id, int value) { int rc = 0; g_MsgObjectRx.ulMsgID = (0x400); g_MsgObjectRx.ulMsgIDMask = 0x7f8; g_MsgObjectRx.ulFlags = MSG_OBJ_USE_ID_FILTER; g_MsgObjectRx.ulMsgLen = snprintf(ucBufferIn, BUFFER_LEN, "%s:%d", id, value); g_MsgObjectRx.pucMsgData = ucBufferIn; CANMessageSet(CAN0_BASE, 1, &g_MsgObjectRx, MSG_OBJ_TYPE_RX); printf("setToMachine SetMessage: %s\n", g_MsgObjectRx.pucMsgData); while((CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT)) & 1 == 0) {} CANMessageGet(CAN0_BASE, 1, &g_MsgObjectRx, true); printf("setToMachine Message: %s\n", g_MsgObjectRx.pucMsgData); return rc; }
static int can_init(const can_cfg_t *cfg) { tCANMsgObject MsgObjectRx; SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); GPIOPinTypeCAN(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1); CANInit(CAN0_BASE); //PLLclock is 400M, and can module clock is 8M(400/50) if (CANBitRateSet(CAN0_BASE, 8000000, cfg->baud) == 0) return 1; //can receive setting,set MsgIDMask value to zero, receive all! MsgObjectRx.ulFlags = MSG_OBJ_NO_FLAGS | MSG_OBJ_USE_ID_FILTER; MsgObjectRx.ulMsgIDMask = 0; CANMessageSet(CAN0_BASE, LM3S_RxMsgObjNr, &MsgObjectRx, MSG_OBJ_TYPE_RX); CANEnable(CAN0_BASE); return 0; }
/* nonblocked send, success return 0, else return -1 */ int can_send(const can_msg_t *msg) { unsigned long status; tCANMsgObject MsgObjectTx; status = CANStatusGet(CAN0_BASE, CAN_STS_TXREQUEST); if(status & (unsigned long)(1 << (LM3S_TxMsgObjNr - 1))) return 1; MsgObjectTx.ulMsgID = msg->id; MsgObjectTx.ulMsgLen = msg->dlc; MsgObjectTx.pucMsgData = (unsigned char *)msg->data; if (msg->flag) { MsgObjectTx.ulFlags = MSG_OBJ_EXTENDED_ID; } else { MsgObjectTx.ulFlags = MSG_OBJ_NO_FLAGS; } CANRetrySet(CAN0_BASE, LM3S_TxMsgObjNr); //set retry send CANMessageSet(CAN0_BASE, LM3S_TxMsgObjNr, &MsgObjectTx, MSG_OBJ_TYPE_TX); return 0; }
void send(){ // Bounds-check each pwm signal if(pwm0 > MAX_WIDTH_0) pwm0= MAX_WIDTH_0; else if(pwm0 < MIN_WIDTH_0) pwm0= MIN_WIDTH_0; if(pwm1 > MAX_WIDTH_1) pwm1= MAX_WIDTH_1; else if(pwm1 < MIN_WIDTH_1) pwm1= MIN_WIDTH_1; // Write both unsigned longs to the 8-byte space and send it msg[0]= (pwm0 & 0xFF000000) >> 24; msg[1]= (pwm0 & 0x00FF0000) >> 16; msg[2]= (pwm0 & 0x0000FF00) >> 8; msg[3]= pwm0 & 0x000000FF; msg[4]= (pwm1 & 0xFF000000) >> 24; msg[5]= (pwm1 & 0x00FF0000) >> 16; msg[6]= (pwm1 & 0x0000FF00) >> 8; msg[7]= pwm1 & 0x000000FF; transmit.pucMsgData= msg; CANMessageSet(CAN0_BASE, 1, &transmit, MSG_OBJ_TYPE_TX); }
//***************************************************************************** // // This function sends a message to set the current brightness for the LED on // the target board. // //***************************************************************************** void CANUpdateTargetLED(unsigned char ucLevel, tBoolean bFlash) { // // If there was already a previous message being transmitted then just // return. // if(g_ulFlags & FLAG_LED_TX_PEND) { return; } // // Set the global LED level. // g_ucLEDLevel = ucLevel; // // If a flash was requested then set the flag. // if(bFlash == true) { g_ucLEDLevel |= LED_FLASH_ONCE; } // // A transmit request is about to be pending. // g_ulFlags |= FLAG_LED_TX_PEND; // // Send the button update request. // CANMessageSet(CAN0_BASE, MSGOBJ_NUM_LED, &g_MsgObjectLED, MSG_OBJ_TYPE_TX); }
void CAN::send(uint32_t mailbox, uint32_t dstAddress, uint8_t* data, uint32_t length) { ASSERT(length<9); uint32_t idx = mailbox + 1; // +1 for transmission tCANMsgObject* mo = _table[idx].msgObject; _table[idx].mode = SEND; mo->ulMsgID = dstAddress; // CAN message ID mo->ulMsgIDMask = 0; // no mask needed for TX mo->ulFlags = MSG_OBJ_TX_INT_ENABLE + MSG_OBJ_FIFO; // enable interrupt on TX mo->ulMsgLen = length; // size of message is length mo->pucMsgData = data; // ptr to message content CANIntEnable(_CAN_BASE, idx + 1); CANMessageSet(_CAN_BASE, idx + 1, mo, MSG_OBJ_TYPE_TX); /* uint32_t st; while ((st = CANStatusGet(_CAN_BASE, CAN_STS_TXREQUEST)) == 0) { } CANMessageGet(_CAN_BASE, st, mo, true); while (CANStatusGet(_CAN_BASE, CAN_STS_TXREQUEST) == 0) { } st = CANStatusGet(_CAN_BASE, CAN_STS_TXREQUEST);*/ }
//***************************************************************************** // // Configure the CAN and enter a loop to receive CAN messages. // //***************************************************************************** int main(void) { tCANMsgObject sCANMessage; uint8_t pui8MsgData[8]; // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal used on your board. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for CAN operation. // InitConsole(); // // For this example CAN0 is used with RX and TX pins on port B4 and B5. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select CAN0 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PB4_CAN0RX); GPIOPinConfigure(GPIO_PB5_CAN0TX); // // Enable the alternate function on the GPIO pins. The above step selects // which alternate function is available. This step actually enables the // alternate function instead of GPIO for these pins. // TODO: change this to match the port/pin you are using // GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Initialize the CAN controller // CANInit(CAN0_BASE); // // Set up the bit rate for the CAN bus. This function sets up the CAN // bus timing for a nominal configuration. You can achieve more control // over the CAN bus timing by using the function CANBitTimingSet() instead // of this one, if needed. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() is used to determine the clock rate that // is used for clocking the CAN peripheral. This can be replaced with a // fixed value if you know the value of the system clock, saving the extra // function call. For some parts, the CAN peripheral is clocked by a fixed // 8 MHz regardless of the system clock in which case the call to // SysCtlClockGet() should be replaced with 8000000. Consult the data // sheet for more information about CAN peripheral clocking. // CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); // // Enable interrupts on the CAN peripheral. This example uses static // allocation of interrupt handlers which means the name of the handler // is in the vector table of startup code. If you want to use dynamic // allocation of the vector table, then you must also call CANIntRegister() // here. // // CANIntRegister(CAN0_BASE, CAN0_IRQHandler); // if using dynamic vectors // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN0); // // Enable the CAN for operation. // CANEnable(CAN0_BASE); // // Initialize a message object to receive CAN messages with ID 0x1001. // The expected ID must be set along with the mask to indicate that all // bits in the ID must match. // sCANMessage.ui32MsgID = 0x1001; sCANMessage.ui32MsgIDMask = 0xfffff; sCANMessage.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER | MSG_OBJ_EXTENDED_ID); sCANMessage.ui32MsgLen = 8; // // Now load the message object into the CAN peripheral message object 1. // Once loaded the CAN will receive any messages with this CAN ID into // this message object, and an interrupt will occur. // CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); // // Change the ID to 0x2001, and load into message object 2 which will be // used for receiving any CAN messages with this ID. Since only the CAN // ID field changes, we don't need to reload all the other fields. // sCANMessage.ui32MsgID = 0x2001; CANMessageSet(CAN0_BASE, 2, &sCANMessage, MSG_OBJ_TYPE_RX); // // Change the ID to 0x3001, and load into message object 3 which will be // used for receiving any CAN messages with this ID. Since only the CAN // ID field changes, we don't need to reload all the other fields. // sCANMessage.ui32MsgID = 0x3001; CANMessageSet(CAN0_BASE, 3, &sCANMessage, MSG_OBJ_TYPE_RX); // // Enter loop to process received messages. This loop just checks flags // for each of the 3 expected messages. The flags are set by the interrupt // handler, and if set this loop reads out the message and displays the // contents to the console. This is not a robust method for processing // incoming CAN data and can only handle one messages at a time per message // object. If many messages are being received close together using the // same message object, then some messages may be dropped. In a real // application, some other method should be used for queuing received // messages in a way to ensure they are not lost. You can also make use // of CAN FIFO mode which will allow messages to be buffered before they // are processed. // for(;;) { // // If the flag for message object 1 is set, that means that the RX // interrupt occurred and there is a message ready to be read from // this CAN message object. // if(g_bRXFlag1) { // // Reuse the same message object that was used earlier to configure // the CAN for receiving messages. A buffer for storing the // received data must also be provided, so set the buffer pointer // within the message object. This same buffer is used for all // messages in this example, but your application could set a // different buffer each time a message is read in order to store // different messages in different buffers. // sCANMessage.pui8MsgData = pui8MsgData; // // Read the message from the CAN. Message object number 1 is used // (which is not the same thing as CAN ID). The interrupt clearing // flag is not set because this interrupt was already cleared in // the interrupt handler. // CANMessageGet(CAN0_BASE, 1, &sCANMessage, 0); // // Clear the pending message flag so that the interrupt handler can // set it again when the next message arrives. // g_bRXFlag1 = 0; // // Print information about the message just received. // PrintCANMessageInfo(&sCANMessage, 1); } // // Check for message received on message object 2. If so then // read message and print information. // if(g_bRXFlag2) { sCANMessage.pui8MsgData = pui8MsgData; CANMessageGet(CAN0_BASE, 2, &sCANMessage, 0); g_bRXFlag2 = 0; PrintCANMessageInfo(&sCANMessage, 2); } // // Check for message received on message object 3. If so then // read message and print information. // if(g_bRXFlag3) { sCANMessage.pui8MsgData = pui8MsgData; CANMessageGet(CAN0_BASE, 3, &sCANMessage, 0); g_bRXFlag3 = 0; PrintCANMessageInfo(&sCANMessage, 3); } } // // Return no errors // return(0); }
int main(void) { char txtBuffer[32]; SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); GPIOPinConfigure(GPIO_PE4_CAN0RX); GPIOPinConfigure(GPIO_PE5_CAN0TX); GPIOPinTypeCAN(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5); CANInit(CAN0_BASE); CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); IntEnable(INT_CAN0); CANEnable(CAN0_BASE); // // Initialize a message object to be used for receiving CAN messages with // any CAN ID. In order to receive any CAN ID, the ID and mask must both // be set to 0, and the ID filter enabled. // sCANMessage.ui32MsgIDMask = 0x7ff; // mask is 0 for any ID sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; sCANMessage.ui32MsgLen = 16; // allow up to 8 bytes // // Now load the message object into the CAN peripheral. Once loaded the // CAN will receive any message on the bus, and an interrupt will occur. // Use message object 1 for receiving messages (this is not the same as // the CAN ID which can be any value in this example). // sCANMessage.ui32MsgID = 0x0b0; // wheels A sCANMessage.pui8MsgData = (uint8_t *)&wheel_a_data; CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); sCANMessage.ui32MsgID = 0x0b2; // wheels B sCANMessage.pui8MsgData = (uint8_t *)&wheel_b_data; CANMessageSet(CAN0_BASE, 2, &sCANMessage, MSG_OBJ_TYPE_RX); sCANMessage.ui32MsgID = 0x2c4; // engine sCANMessage.pui8MsgData = (uint8_t *)&engine_data; CANMessageSet(CAN0_BASE, 3, &sCANMessage, MSG_OBJ_TYPE_RX); sCANMessage.ui32MsgID = 0x398; // fuel sCANMessage.pui8MsgData = (uint8_t *)&fuel_data; CANMessageSet(CAN0_BASE, 4, &sCANMessage, MSG_OBJ_TYPE_RX); lcd_port_setup(); lcd_init(); for (;;) { unsigned int li, lf, ri, rf, fi, ff; // integral and fractional parts for left, right wheels' speed, and fuel consumption unsigned long int v = 0; // Average speed float vf, ef; // Float versions of speed and economy li = ntohs(wheel_a_data.wheel2); v += li; lf = li%100; li /= 100; ri = ntohs(wheel_a_data.wheel1); v += ri; rf = ri%100; ri /= 100; snprintf(txtBuffer, 21, "L %3d.%02d -- R %3d.%02d", li, lf, ri, rf); lcd_goto(0,0); lcd_puts(txtBuffer); li = ntohs(wheel_b_data.wheel2); v += li; lf = li%100; li /= 100; ri = ntohs(wheel_b_data.wheel1); v += ri; rf = ri%100; ri /= 100; snprintf(txtBuffer, 21, "L %3d.%02d -- R %3d.%02d", li, lf, ri, rf); lcd_goto(1,0); lcd_puts(txtBuffer); vf = v / 400.0; snprintf(txtBuffer, 21, "%4d RPM %3d.%02d KM/H", ntohs(engine_data.rpm), (int)vf, ((int)(vf*100))%100); lcd_goto(2,0); lcd_puts(txtBuffer); fi = ntohs(fuel_data.fuel); ff = fi % 100; fi /= 100; if (vf >= .01) { ef = vf/(fi/100.0); snprintf(txtBuffer, 21, "%2d.%02d L/H %2d.%02d KM/L", fi, ff, (int)ef, ((int)(ef*100))%100); } else { snprintf(txtBuffer, 21, "%2d.%02d L/H --.-- KM/L", fi, ff); } lcd_goto(3,0); lcd_puts(txtBuffer); } return (0); }
//***************************************************************************** // // Configure the CAN and enter a loop to transmit periodic CAN messages. // //***************************************************************************** int main(void) { // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal on your board. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for CAN operation. // InitConsole(); // // For this example CAN0 is used with RX and TX pins on port B4 and B5. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select CAN0 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PB4_CAN0RX); GPIOPinConfigure(GPIO_PB5_CAN0TX); // // Enable the alternate function on the GPIO pins. The above step selects // which alternate function is available. This step actually enables the // alternate function instead of GPIO for these pins. // TODO: change this to match the port/pin you are using // GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Initialize the CAN controller // CANInit(CAN0_BASE); // // Set up the bit rate for the CAN bus. This function sets up the CAN // bus timing for a nominal configuration. You can achieve more control // over the CAN bus timing by using the function CANBitTimingSet() instead // of this one, if needed. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() is used to determine the clock rate that // is used for clocking the CAN peripheral. This can be replaced with a // fixed value if you know the value of the system clock, saving the extra // function call. For some parts, the CAN peripheral is clocked by a fixed // 8 MHz regardless of the system clock in which case the call to // SysCtlClockGet() should be replaced with 8000000. Consult the data // sheet for more information about CAN peripheral clocking. // CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); // // Enable interrupts on the CAN peripheral. This example uses static // allocation of interrupt handlers which means the name of the handler // is in the vector table of startup code. If you want to use dynamic // allocation of the vector table, then you must also call CANIntRegister() // here. // // CANIntRegister(CAN0_BASE, CANIntHandler); // if using dynamic vectors // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN0); // // Enable the CAN for operation. // CANEnable(CAN0_BASE); // // Initialize the message object that will be used for sending CAN // messages. The message will be 4 bytes that will contain an incrementing // value. Initially it will be set to 0. // // // Initialize message object 1 to be able to send CAN message 1. This // message object is not shared so it only needs to be initialized one // time, and can be used for repeatedly sending the same message ID. // g_sCANMsgObject1.ui32MsgID = 0x1001; g_sCANMsgObject1.ui32MsgIDMask = 0; g_sCANMsgObject1.ui32Flags = MSG_OBJ_TX_INT_ENABLE; g_sCANMsgObject1.ui32MsgLen = sizeof(g_pui8Msg1); g_sCANMsgObject1.pui8MsgData = g_pui8Msg1; // // Initialize message object 2 to be able to send CAN message 2. This // message object is not shared so it only needs to be initialized one // time, and can be used for repeatedly sending the same message ID. // g_sCANMsgObject2.ui32MsgID = 0x2001; g_sCANMsgObject2.ui32MsgIDMask = 0; g_sCANMsgObject2.ui32Flags = MSG_OBJ_TX_INT_ENABLE; g_sCANMsgObject2.ui32MsgLen = sizeof(g_pui8Msg2); g_sCANMsgObject2.pui8MsgData = g_pui8Msg2; // // Enter loop to send messages. Four messages will be sent once per // second. The contents of each message will be changed each time. // for(;;) { // // Send message 1 using CAN controller message object 1. This is // the only message sent using this message object. The // CANMessageSet() function will cause the message to be sent right // away. // PrintCANMessageInfo(&g_sCANMsgObject1, 1); CANMessageSet(CAN0_BASE, 1, &g_sCANMsgObject1, MSG_OBJ_TYPE_TX); // // Send message 2 using CAN controller message object 2. This is // the only message sent using this message object. The // CANMessageSet() function will cause the message to be sent right // away. // PrintCANMessageInfo(&g_sCANMsgObject2, 2); CANMessageSet(CAN0_BASE, 2, &g_sCANMsgObject2, MSG_OBJ_TYPE_TX); // // Load message object 3 with message 3. This is needs to be done each // time because message object 3 is being shared for two different // messages. // g_sCANMsgObject3.ui32MsgID = 0x3001; g_sCANMsgObject3.ui32MsgIDMask = 0; g_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE; g_sCANMsgObject3.ui32MsgLen = sizeof(g_pui8Msg3); g_sCANMsgObject3.pui8MsgData = g_pui8Msg3; // // Clear the flag that indicates that message 3 has been sent. This // flag will be set in the interrupt handler when a message has been // sent using message object 3. // g_bMsgObj3Sent = 0; // // Now send message 3 using CAN controller message object 3. This is // the first message sent using this message object. The // CANMessageSet() function will cause the message to be sent right // away. // PrintCANMessageInfo(&g_sCANMsgObject3, 3); CANMessageSet(CAN0_BASE, 3, &g_sCANMsgObject3, MSG_OBJ_TYPE_TX); // // Wait for the indication from the interrupt handler that message // object 3 is done, because we are re-using it for another message. // while(!g_bMsgObj3Sent) { } // // Load message object 3 with message 4. This is needed because // message object 3 is being shared for two different messages. // g_sCANMsgObject3.ui32MsgID = 0x3002; g_sCANMsgObject3.ui32MsgIDMask = 0; g_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE; g_sCANMsgObject3.ui32MsgLen = sizeof(g_pui8Msg4); g_sCANMsgObject3.pui8MsgData = g_pui8Msg4; // // Now send message 4 using CAN controller message object 3. This is // the second message sent using this message object. The // CANMessageSet() function will cause the message to be sent right // away. // PrintCANMessageInfo(&g_sCANMsgObject3, 3); CANMessageSet(CAN0_BASE, 3, &g_sCANMsgObject3, MSG_OBJ_TYPE_TX); // // Wait 1 second before continuing // SimpleDelay(); // // Check the error flag to see if errors occurred // if(g_bErrFlag) { UARTprintf(" error - cable connected?\n"); } else { // // If no errors then print the count of message sent // UARTprintf(" total count = %u\n", g_ui32Msg1Count + g_ui32Msg2Count + g_ui32Msg3Count); } // // Change the value in the message data for each of the messages. // (*(uint32_t *)g_pui8Msg1)++; (*(uint32_t *)g_pui8Msg2)++; (*(uint32_t *)g_pui8Msg3)++; (*(uint32_t *)&g_pui8Msg4[0])++; (*(uint32_t *)&g_pui8Msg4[4])--; } // // Return no errors // return(0); }
//***************************************************************************** // // Configure the CAN and enter a loop to transmit periodic CAN messages. // //***************************************************************************** int main(void) { tCANMsgObject sCANMessage; uint32_t ui32MsgData; uint8_t *pui8MsgData; pui8MsgData = (uint8_t *)&ui32MsgData; // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal on your board. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for CAN operation. // InitConsole(); // // For this example CAN0 is used with RX and TX pins on port B4 and B5. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select CAN0 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PB4_CAN0RX); GPIOPinConfigure(GPIO_PB5_CAN0TX); // // Enable the alternate function on the GPIO pins. The above step selects // which alternate function is available. This step actually enables the // alternate function instead of GPIO for these pins. // TODO: change this to match the port/pin you are using // GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Initialize the CAN controller // CANInit(CAN0_BASE); // // Set up the bit rate for the CAN bus. This function sets up the CAN // bus timing for a nominal configuration. You can achieve more control // over the CAN bus timing by using the function CANBitTimingSet() instead // of this one, if needed. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() is used to determine the clock rate that // is used for clocking the CAN peripheral. This can be replaced with a // fixed value if you know the value of the system clock, saving the extra // function call. For some parts, the CAN peripheral is clocked by a fixed // 8 MHz regardless of the system clock in which case the call to // SysCtlClockGet() should be replaced with 8000000. Consult the data // sheet for more information about CAN peripheral clocking. // CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); // // Enable interrupts on the CAN peripheral. This example uses static // allocation of interrupt handlers which means the name of the handler // is in the vector table of startup code. If you want to use dynamic // allocation of the vector table, then you must also call CANIntRegister() // here. // // CANIntRegister(CAN0_BASE, CAN0_IRQHandler); // if using dynamic vectors // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN0); // // Enable the CAN for operation. // CANEnable(CAN0_BASE); // // Initialize the message object that will be used for sending CAN // messages. The message will be 4 bytes that will contain an incrementing // value. Initially it will be set to 0. // ui32MsgData = 0; sCANMessage.ui32MsgID = 1; sCANMessage.ui32MsgIDMask = 0; sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE; sCANMessage.ui32MsgLen = sizeof(pui8MsgData); sCANMessage.pui8MsgData = pui8MsgData; // // Enter loop to send messages. A new message will be sent once per // second. The 4 bytes of message content will be treated as an uint32_t // and incremented by one each time. // while(1) { // // Print a message to the console showing the message count and the // contents of the message being sent. // UARTprintf("Sending msg: 0x%02X %02X %02X %02X", pui8MsgData[0], pui8MsgData[1], pui8MsgData[2], pui8MsgData[3]); // // Send the CAN message using object number 1 (not the same thing as // CAN ID, which is also 1 in this example). This function will cause // the message to be transmitted right away. // CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX); // // Now wait 1 second before continuing // SimpleDelay(); // // Check the error flag to see if errors occurred // if(g_bErrFlag) { UARTprintf(" error - cable connected?\n"); } else { // // If no errors then print the count of message sent // UARTprintf(" total count = %u\n", g_ui32MsgCount); } // // Increment the value in the message data. // ui32MsgData++; } // // Return no errors // return(0); }
void NetworkTx(unsigned long ulData) { g_MsgTx.pucMsgData = (unsigned char *)&ulData; CANMessageSet(CAN0_BASE, MSG_NUM_TX, &g_MsgTx, MSG_OBJ_TYPE_TX); }
//***************************************************************************** // // This function configures the transmit FIFO and copies data into the FIFO. // //***************************************************************************** int CANTransmitFIFO(unsigned char *pucData, unsigned long ulSize) { int iIdx; // // This is the message object used to send button updates. This message // object will not be "set" right now as that would trigger a transmission. // g_sCAN.MsgObjectTx.ulMsgID = TRANSMIT_MESSAGE_ID; g_sCAN.MsgObjectTx.ulMsgIDMask = 0; // // This enables interrupts for transmitted messages. // g_sCAN.MsgObjectTx.ulFlags = MSG_OBJ_TX_INT_ENABLE; // // Return the maximum possible number of bytes that can be sent in a single // FIFO. // if(ulSize > CAN_FIFO_SIZE) { return(CAN_FIFO_SIZE); } // // Loop through all eight message objects that are part of the transmit // FIFO. // for(iIdx = 0; iIdx < 8; iIdx++) { // // If there are more than eight bytes remaining then use a full message // to transfer these 8 bytes. // if(ulSize > 8) { // // Set the length of the message, which can only be eight bytes // in this case as it is all that can be sent with a single message // object. // g_sCAN.MsgObjectTx.ulMsgLen = 8; g_sCAN.MsgObjectTx.pucMsgData = &pucData[iIdx * 8]; // // Set the MSG_OBJ_FIFO to indicate that this is not the last // data in a chain of FIFO entries. // g_sCAN.MsgObjectTx.ulFlags |= MSG_OBJ_FIFO; // // There are now eight less bytes to transmit. // ulSize -= 8; // // Write out this message object. // CANMessageSet(CAN0_BASE, iIdx + 1, &g_sCAN.MsgObjectTx, MSG_OBJ_TYPE_TX); } // // If there are less than or exactly eight bytes remaining then use a // message object to transfer these 8 bytes and do not set the // MSG_OBJ_FIFO flag to indicate that this is the last of the entries // in this FIFO. // else { // // Set the length to the remaining bytes and transmit the data. // g_sCAN.MsgObjectTx.ulMsgLen = ulSize; g_sCAN.MsgObjectTx.pucMsgData = &pucData[iIdx * 8]; // // Write out this message object. // CANMessageSet(CAN0_BASE, iIdx + 1, &g_sCAN.MsgObjectTx, MSG_OBJ_TYPE_TX); } } return(0); }
//***************************************************************************** // // This function configures the receive FIFO and should only be called once. // //***************************************************************************** int CANReceiveFIFO(unsigned char *pucData, unsigned long ulSize) { int iIdx; if(ulSize > CAN_FIFO_SIZE) { return(CAN_FIFO_SIZE); } // // Configure the receive message FIFO to accept the transmit message object. // g_sCAN.MsgObjectRx.ulMsgID = RECEIVE_MESSAGE_ID; g_sCAN.MsgObjectRx.ulMsgIDMask = 0; // // This enables interrupts for received messages. // g_sCAN.MsgObjectRx.ulFlags = MSG_OBJ_RX_INT_ENABLE; // // Remember the beginning of the FIFO location. // g_sCAN.MsgObjectRx.pucMsgData = pucData; // // Transfer bytes in multiples of eight bytes. // for(iIdx=0; iIdx < (CAN_FIFO_SIZE / 8); iIdx++) { // // If there are more than eight remaining to be sent then just queue up // eight bytes and go on to the next message object(s) for the // remaining bytes. // if(ulSize > 8) { // // The length is always eight as the full buffer is divisible by 8. // g_sCAN.MsgObjectRx.ulMsgLen = 8; // // There are now eight less bytes to receive. // ulSize -=8; // // Set the MSG_OBJ_FIFO to indicate that this is not the last // data in a chain of FIFO entries. // g_sCAN.MsgObjectRx.ulFlags |= MSG_OBJ_FIFO; // // Make sure that all message objects up to the last indicate that // they are part of a FIFO. // CANMessageSet(CAN0_BASE, iIdx + 9, &g_sCAN.MsgObjectRx, MSG_OBJ_TYPE_RX); } else { // // Get the remaining bytes. // g_sCAN.MsgObjectRx.ulMsgLen = ulSize; // // This is the last message object in a FIFO so don't set the FIFO // to indicate that the FIFO ends with this message object. // CANMessageSet(CAN0_BASE, iIdx + 9, &g_sCAN.MsgObjectRx, MSG_OBJ_TYPE_RX); } } return(0); }
//***************************************************************************** // // This function configures the message objects used by this application. // The following four message objects used by this application: // MSGOBJ_ID_BUTTON, MSGOBJ_ID_LED, MSGOBJ_ID_DATA_TX, and MSGOBJ_ID_DATA_RX. // //***************************************************************************** void CANConfigureNetwork(void) { // // Set the identifier and mask for the button object. // g_MsgObjectButton.ulMsgID = MSGOBJ_ID_BUTTON; g_MsgObjectButton.ulMsgIDMask = 0; // // This enables interrupts for received messages. // g_MsgObjectButton.ulFlags = MSG_OBJ_RX_INT_ENABLE; // // Set the size of the message and the data buffer used. // g_MsgObjectButton.ulMsgLen = 2; g_MsgObjectButton.pucMsgData = g_pucButtonMsg; // // Configure the Button receive message object. // CANMessageSet(CAN0_BASE, MSGOBJ_NUM_BUTTON, &g_MsgObjectButton, MSG_OBJ_TYPE_RX); // // This message object will receive updates to the LED. // g_MsgObjectLED.ulMsgID = MSGOBJ_ID_LED; g_MsgObjectLED.ulMsgIDMask = 0; // // This enables interrupts for received messages. // g_MsgObjectLED.ulFlags = MSG_OBJ_TX_INT_ENABLE; // // Set the length of the message and the data buffer used. // g_MsgObjectLED.ulMsgLen = 1; g_MsgObjectLED.pucMsgData = &g_ucLEDLevel; // // This message object will transmit commands. // g_MsgObjectTx.ulMsgID = MSGOBJ_ID_DATA_TX; g_MsgObjectTx.ulMsgIDMask = 0; // // This enables interrupts for received messages. // g_MsgObjectTx.ulFlags = MSG_OBJ_TX_INT_ENABLE; // // The length of the message, which should only be one byte. Don't set // the pointer until it is used. // g_MsgObjectTx.ulMsgLen = 1; g_MsgObjectTx.pucMsgData = (unsigned char *)0xffffffff; // // This message object will received data from commands. // g_MsgObjectRx.ulMsgID = MSGOBJ_ID_DATA_RX; g_MsgObjectRx.ulMsgIDMask = 0; // // This enables interrupts for received messages. // g_MsgObjectRx.ulFlags = MSG_OBJ_RX_INT_ENABLE; // // The length of the message, which should only be one byte. Don't set // the pointer until it is used. // g_MsgObjectRx.ulMsgLen = 1; g_MsgObjectRx.pucMsgData = (unsigned char *)0xffffffff; // // Configure the data receive message object. // CANMessageSet(CAN0_BASE, MSGOBJ_NUM_DATA_RX, &g_MsgObjectRx, MSG_OBJ_TYPE_RX); }
//***************************************************************************** // // This function is the interrupt handler for the CAN peripheral. It checks // for the cause of the interrupt, and maintains a count of all messages that // have been transmitted. // //***************************************************************************** extern "C" void CAN0IntHandler(void) { unsigned long ulStatus; // Read the CAN interrupt status to find the cause of the interrupt ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); // // If the cause is a controller status interrupt, then get the status // if (ulStatus == CAN_INT_INTID_STATUS) { // // Read the controller status. This will return a field of status // error bits that can indicate various errors. Error processing // is not done in this example for simplicity. Refer to the // API documentation for details about the error status bits. // The act of reading this status will clear the interrupt. If the // CAN peripheral is not connected to a CAN bus with other CAN devices // present, then errors will occur and will be indicated in the // controller status. // ulStatus = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL); if (ulStatus == CAN_STATUS_TXOK) { } else if (ulStatus == CAN_STATUS_RXOK) { } else /* CAN_STS_CONTROL - the main controller status CAN_STS_TXREQUEST - bit mask of objects pending transmissio CAN_STS_NEWDAT - bit mask of objects with new data CAN_STS_MSGVAL - bit mask of objects with valid configuration CAN_STATUS_BUS_OFF - controller is in bus-off condition CAN_STATUS_EWARN - an error counter has reached a limit of at least 96 CAN_STATUS_EPASS - CAN controller is in the error passive state CAN_STATUS_RXOK - a message was received successfully (independent of any mes-sage filtering). CAN_STATUS_TXOK - a message was successfully transmitted CAN_STATUS_LEC_MSK - mask of last error code bits (3 bits) CAN_STATUS_LEC_NONE - no error CAN_STATUS_LEC_STUFF - stuffing error detected CAN_STATUS_LEC_FORM - a format error occurred in the fixed format part of amessage CAN_STATUS_LEC_ACK - a transmitted message was not acknowledged CAN_STATUS_LEC_BIT1 - dominant level detected when trying to send in recessive mode CAN_STATUS_LEC_BIT0 - recessive level detected when trying to send in dominant mode CAN_STATUS_LEC_CRC - CRC error in received message */ can0._countErr++; } // // Check if the cause is message object 1, which what we are using for // sending messages. // else if (ulStatus < can0._tableIdx + 1 && ulStatus > 0) { uint32_t idx = ulStatus - 1; if (can0._table[idx].mode == CAN::RECV) { tCANMsgObject* msgObj = (can0._table[idx].msgObject); CANIntClear(CAN0_BASE, idx + 1); CANMessageGet(CAN0_BASE, idx + 1, msgObj, true); can0._countRxd++; CANListener* listener = can0._table[idx].listener; listener->recv(msgObj->ulMsgID, msgObj->ulMsgLen, msgObj->pucMsgData); CANMessageSet(CAN0_BASE, ulStatus, msgObj, MSG_OBJ_TYPE_RX); // CANMessageSet(CAN0_BASE, ulStatus, msgObj, MSG_OBJ_TYPE_TX); // reload } else if (can0._table[idx].mode == CAN::SEND) { CANListener* listener = can0._table[idx].listener; tCANMsgObject* msgObj = (can0._table[idx].msgObject); CANIntClear(CAN0_BASE, idx + 1); can0._countTxd++; listener->sendDone(msgObj->ulMsgID, E_OK); } } else { // // Spurious interrupt handling can go here. // CANIntClear(CAN0_BASE, ulStatus); } }
//***************************************************************************** // // Configure CAN message objects for the application. // // This function configures the message objects used by this application. // The following four message objects used by this application: // MSGOBJ_ID_BUTTON, MSGOBJ_ID_LED, MSGOBJ_ID_DATA_TX, and MSGOBJ_ID_DATA_RX. // // /return None. // //***************************************************************************** void CANConfigureNetwork(void) { // // This is the message object used to send button updates. This message // object will not be "set" right now as that would trigger a transmission. // g_MsgObjectButton.ulMsgID = MSGOBJ_ID_BUTTON; g_MsgObjectButton.ulMsgIDMask = 0; // // This enables interrupts for transmitted messages. // g_MsgObjectButton.ulFlags = MSG_OBJ_TX_INT_ENABLE; // // Set the length of the message, which should only be two bytes and the // data is always whatever is in g_pucButtonMsg. // g_MsgObjectButton.ulMsgLen = 2; g_MsgObjectButton.pucMsgData = g_pucButtonMsg; // // This message object will receive updates for the LED brightness. // g_MsgObjectLED.ulMsgID = MSGOBJ_ID_LED; g_MsgObjectLED.ulMsgIDMask = 0; // // This enables interrupts for received messages. // g_MsgObjectLED.ulFlags = MSG_OBJ_RX_INT_ENABLE; // // The length of the message, which should only be one byte. // g_MsgObjectLED.ulMsgLen = 1; g_MsgObjectLED.pucMsgData = &g_ucLEDLevel; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_LED, &g_MsgObjectLED, MSG_OBJ_TYPE_RX); // // This message object will transmit commands and command responses. It // will not be "set" right now as that would trigger a transmission. // g_MsgObjectTx.ulMsgID = MSGOBJ_ID_DATA_TX; g_MsgObjectTx.ulMsgIDMask = 0; // // This enables interrupts for transmitted messages. // g_MsgObjectTx.ulFlags = MSG_OBJ_TX_INT_ENABLE; // // The length of the message, which should only be one byte. Don't set // the pointer until it is used. // g_MsgObjectTx.ulMsgLen = 1; g_MsgObjectTx.pucMsgData = (unsigned char *)0xffffffff; // // This message object will receive commands or data from commands. // g_MsgObjectRx.ulMsgID = MSGOBJ_ID_DATA_RX; g_MsgObjectRx.ulMsgIDMask = 0; // // This enables interrupts for received messages. // g_MsgObjectRx.ulFlags = MSG_OBJ_RX_INT_ENABLE; // // The length of the message, which should only be one byte. Don't set // the pointer until it is used. // g_MsgObjectRx.ulMsgLen = 1; g_MsgObjectRx.pucMsgData = (unsigned char *)0xffffffff; CANMessageSet(CAN0_BASE, MSGOBJ_NUM_DATA_RX, &g_MsgObjectRx, MSG_OBJ_TYPE_RX); }
//***************************************************************************** // // Configure the CAN and enter a loop to receive CAN messages. // //***************************************************************************** int main(void) { #if defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) uint32_t ui32SysClock; #endif tCANMsgObject sCANMessage; uint8_t pui8MsgData[8]; // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal used on your board. // #if defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_OSC) 25000000); #else SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); #endif // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for CAN operation. // InitConsole(); // // For this example CAN0 is used with RX and TX pins on port B4 and B5. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select CAN0 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PB4_CAN0RX); GPIOPinConfigure(GPIO_PB5_CAN0TX); // // Enable the alternate function on the GPIO pins. The above step selects // which alternate function is available. This step actually enables the // alternate function instead of GPIO for these pins. // TODO: change this to match the port/pin you are using // GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Initialize the CAN controller // CANInit(CAN0_BASE); // // Set up the bit rate for the CAN bus. This function sets up the CAN // bus timing for a nominal configuration. You can achieve more control // over the CAN bus timing by using the function CANBitTimingSet() instead // of this one, if needed. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() or ui32SysClock is used to determine the // clock rate that is used for clocking the CAN peripheral. This can be // replaced with a fixed value if you know the value of the system clock, // saving the extra function call. For some parts, the CAN peripheral is // clocked by a fixed 8 MHz regardless of the system clock in which case // the call to SysCtlClockGet() or ui32SysClock should be replaced with // 8000000. Consult the data sheet for more information about CAN // peripheral clocking. // #if defined(TARGET_IS_TM4C129_RA0) || \ defined(TARGET_IS_TM4C129_RA1) || \ defined(TARGET_IS_TM4C129_RA2) CANBitRateSet(CAN0_BASE, ui32SysClock, 500000); #else CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); #endif // // Enable interrupts on the CAN peripheral. This example uses static // allocation of interrupt handlers which means the name of the handler // is in the vector table of startup code. If you want to use dynamic // allocation of the vector table, then you must also call CANIntRegister() // here. // // CANIntRegister(CAN0_BASE, CANIntHandler); // if using dynamic vectors // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN0); // // Enable the CAN for operation. // CANEnable(CAN0_BASE); // // Initialize a message object to be used for receiving CAN messages with // any CAN ID. In order to receive any CAN ID, the ID and mask must both // be set to 0, and the ID filter enabled. // sCANMessage.ui32MsgID = 0; sCANMessage.ui32MsgIDMask = 0; sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; sCANMessage.ui32MsgLen = 8; // // Now load the message object into the CAN peripheral. Once loaded the // CAN will receive any message on the bus, and an interrupt will occur. // Use message object 1 for receiving messages (this is not the same as // the CAN ID which can be any value in this example). // CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); // // Enter loop to process received messages. This loop just checks a flag // that is set by the interrupt handler, and if set it reads out the // message and displays the contents. This is not a robust method for // processing incoming CAN data and can only handle one messages at a time. // If many messages are being received close together, then some messages // may be dropped. In a real application, some other method should be used // for queuing received messages in a way to ensure they are not lost. You // can also make use of CAN FIFO mode which will allow messages to be // buffered before they are processed. // for(;;) { unsigned int uIdx; // // If the flag is set, that means that the RX interrupt occurred and // there is a message ready to be read from the CAN // if(g_bRXFlag) { // // Reuse the same message object that was used earlier to configure // the CAN for receiving messages. A buffer for storing the // received data must also be provided, so set the buffer pointer // within the message object. // sCANMessage.pui8MsgData = pui8MsgData; // // Read the message from the CAN. Message object number 1 is used // (which is not the same thing as CAN ID). The interrupt clearing // flag is not set because this interrupt was already cleared in // the interrupt handler. // CANMessageGet(CAN0_BASE, 1, &sCANMessage, 0); // // Clear the pending message flag so that the interrupt handler can // set it again when the next message arrives. // g_bRXFlag = 0; // // Check to see if there is an indication that some messages were // lost. // if(sCANMessage.ui32Flags & MSG_OBJ_DATA_LOST) { UARTprintf("CAN message loss detected\n"); } // // Print out the contents of the message that was received. // UARTprintf("Msg ID=0x%08X len=%u data=0x", sCANMessage.ui32MsgID, sCANMessage.ui32MsgLen); for(uIdx = 0; uIdx < sCANMessage.ui32MsgLen; uIdx++) { UARTprintf("%02X ", pui8MsgData[uIdx]); } UARTprintf("total count=%u\n", g_ui32MsgCount); } } // // Return no errors // return(0); }