This software works with CAN shield (int 2) on Arduino UNO/Mega2560. Need FreeRTOS.
Receive CAN frames and send them via serial.
CAN 250 Kbps
Serial 9600 bps
//**********************************
// CAN Read
// oceam2@yahoo.com
// V 1.0
//***********************************
#if defined ARDUINO_SAM_DUE
#include <FreeRTOS_ARM.h>
#else
#include <FreeRTOS_AVR.h>
#endif
#include <SPI.h>
#include "mcp_can_j1939_v2.h"
#include "can_ext_j1939_v2.h"
#define Int_Can 2
//Asignaciones
QueueHandle_t xQueue1;
//Variables
TaskHandle_t xHandle_1;
struct AMessage {
byte nPriority;
byte nSrcAddr;
byte nDestAddr;
byte nData[8];
int nDataLen;
long lPGN;
long time;
uint32_t cuenta;
} xMessage, *pxMessage, *pxRxedMessage;
struct trama_can {
//EEC2
uint16_t Accelerator_Pedal_Position_1;
uint16_t Engine_Percent_Load_At_Current_Speed;
//IC1
uint16_t Engine_Intake_Manifold_1_Pressure;
uint16_t Engine_Intake_Manifold_1_Temperature;
//EEC1
uint16_t pressure_measurement_air_intake_manifold;
uint16_t Drivers_Demand_Engine_requested;
uint16_t actual_engine_calculated_torque;
uint16_t engine_demand_requested_torque;
uint16_t engine_speed_rpm;
uint16_t engine_speed_rpm2;
//VEP1
float Vehicle_Electrical_Power;
//ET1
uint16_t Engine_Coolant_Temperature;
//EFL_P2
uint16_t Fan_Drive_State;
uint16_t Estimated_Percent_Fan_Speed;
//AMB
uint16_t Barometric_Pressure_Absolute;
//EFL_P1
uint16_t Engine_Fuel_Delivery_Pressure;
uint16_t Engine_Oil_Pressure;
//Fuel
uint16_t Fuel_Level;
} can_mega2560;
void setup() {
// initialize SPI:
SPI.begin();
//Serial
Serial.begin(9600);
// Creamos la cola CAN
xQueue1 = xQueueCreate(100, sizeof(struct AMessage *));
if (xQueue1 == NULL) Serial.println("Queue Fail !"); else Serial.println("Queue Created OK.");
canInitialize(10); // 11=250k @8MHz 10=250K @16MHz
//FreeRTOS
if (xTaskCreate(vPeriodicTask1, "CAN_RX", 300, NULL, tskIDLE_PRIORITY + 1, &xHandle_1) == pdPASS) { NULL; }
// INT Cola CAN
attachInterrupt(digitalPinToInterrupt(Int_Can), recibir_can, FALLING); //Can
vTaskStartScheduler();
for (;;);
}
// Tarea 1
void vPeriodicTask1(void *pvParameters)
{
static char sString[80];
TickType_t xLastWakeTime = xTaskGetTickCount();
for (;;)
{
// Lectura cola CAN RX
if (xQueue1 != 0)
{
// Receive a message on the created queue. Block for 10 ticks if a message is not immediately available
if (xQueueReceive(xQueue1, &(pxRxedMessage), (TickType_t)10))
{
long lMessageID2 = ((long)pxRxedMessage->nPriority << 26) + ((long)pxRxedMessage->lPGN << 8) + (long)pxRxedMessage->nSrcAddr;
switch (lMessageID2)
{
case 0x18FEF803: {
// can_mega2560.temperatura_transmision = (uint16_t)(0.03125* (pxRxedMessage->nData[4] + 256 * pxRxedMessage->nData[5]) - 273);
break; }
case 0x18F00200: {
can_mega2560.engine_speed_rpm = (pxRxedMessage->nData[5] + 256 * pxRxedMessage->nData[6]);
break; }
default:
{
break;
}
}
ltoa(lMessageID2, sString, 16);
strupr(sString);
Serial.print("ID:");
Serial.print(sString);
Serial.print(" ");
sprintf(sString, "PGN:%05u P:%X S:%X D:%X ", (int)pxRxedMessage->lPGN, pxRxedMessage->nPriority, pxRxedMessage->nSrcAddr, pxRxedMessage->nDestAddr);
Serial.print(sString);
Serial.print("Data:");
for (int nIndex = 0; nIndex < pxRxedMessage->nDataLen; nIndex++)
{
sprintf(sString, "%X ", pxRxedMessage->nData[nIndex]);
Serial.print(sString);
} Serial.println("");
vTaskDelayUntil(&xLastWakeTime, (50 / portTICK_PERIOD_MS));
}
}//if xQueue1
}
}
void recibir_can() {
if (xQueue1 != NULL)
{
j1939Receive(&xMessage.lPGN, &xMessage.nPriority, &xMessage.nSrcAddr, &xMessage.nDestAddr, xMessage.nData, &xMessage.nDataLen);
pxMessage = &xMessage;
xQueueSend(xQueue1, (void *)&pxMessage, (TickType_t)0);
}
}
void loop() { }