#include <mcp_can.h>
#include <SPI.h>
#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {11, 9, 8, 7};
byte colPins[COLS] = {6, 5, 4, 3};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
LiquidCrystal_I2C lcd(0x27, 20, 4);
MCP_CAN CAN0(10); // Set CS to pin 10
long unsigned int rxId;
unsigned char len = 0;
unsigned char rxBuf[8];
char msgString[128]; // Array to store serial string
#define CAN0_INT 2 // Set INT to pin 2
void setup() {
Serial.begin(115200);
lcd.init();
lcd.backlight();
if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) {
Serial.println("MCP2515 Initialized Successfully!");
} else {
Serial.println("Error Initializing MCP2515...");
}
CAN0.setMode(MCP_NORMAL); // Change to normal mode to allow messages to be transmitted
pinMode(CAN0_INT, INPUT);
}
byte data[8];
void loop() {
lcd.setCursor(0,0);
lcd.print("A: Send message");
lcd.setCursor(0,1);
lcd.print("B: Receive message");
char key1 = keypad.getKey();
if (key1) {
if (key1=='A'){
send();
}
else if (key1=='B'){
receive();
}
}
}
void displayData() {
lcd.setCursor(0, 1);
lcd.print(":");
for (int i = 0; i < 8; i++) {
lcd.print(data[i], HEX);
lcd.print(" ");
}
delay(5000);
}
void send() {
lcd.clear();
lcd.print("Message 8 bytes:");
lcd.setCursor(0, 1);
int index = 0;
String input = "";
while (index < 8) {
char key = keypad.getKey();
if (key) {
if (key == '#') {
// Convert input to byte
byte value = (byte) strtol(input.c_str(), NULL, 16); //Convertit une chaîne de caractères en entier
data[index] = value;
index++;
input = "";
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the input area
lcd.setCursor(0, 1);
} else if (key == '*') {
// Clear current input
input = "";
lcd.setCursor(0, 1);
lcd.print(" "); // Clear the input area
lcd.setCursor(0, 1);
} else {
input += key;
lcd.print(key);
}
}
}
byte sndStat = CAN0.sendMsgBuf(0x00, 0, 8, data); // CAN_SEND.sendMsgBuf(id, ext, len, buf);
if (sndStat == CAN_OK) {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Sent Successfully!");
displayData();
delay(2000);
lcd.clear();
} else {
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("Error Sending...");
displayData();
delay(1500);
lcd.clear();
}
delay(100); // send data per 100ms
}
void receive() {
if(!digitalRead(CAN0_INT)) // If CAN0_INT pin is low, read receive buffer
{
CAN0.readMsgBuf(&rxId, &len, rxBuf); // Read data: len = data length, buf = data byte(s)
//stocker l'ID du message dans rxId, la longueur des données dans len, et les données elles-mêmes dans le tableau rxBuf.
if((rxId & 0x80000000) == 0x80000000) // Le code vérifie si le message CAN a un ID étendu ou standard en regardant le bit 31 (0x80000000) de rxId. Si ce bit est défini (1), l'ID est étendu. Sinon, l'ID est standard.
sprintf(msgString, "Extended ID: 0x%.8lX DLC: %1d Data:", (rxId & 0x1FFFFFFF), len);
else
sprintf(msgString, "Standard ID: 0x%.3lX DLC: %1d Data:", rxId, len);
lcd.clear();
lcd.print(msgString);
delay(5000);
lcd.clear();
if((rxId & 0x40000000) == 0x40000000){ //vérifie si le message est une trame de demande distante (remote request frame)
sprintf(msgString, " REMOTE REQUEST FRAME"); // si le bit 30=1
lcd.setCursor(0,3);
lcd.print(msgString);
} else {
for(byte i = 0; i<len; i++){
sprintf(msgString, " 0x%.2X", rxBuf[i]);
lcd.setCursor(0,3);
lcd.print(msgString);
}
}
}
}