1 Use with Arduino Uno Q
1 Hardware Overview MAX33041ESHLD
Critical: This board only contains CAN PHY chip (no CAN protocol controller). Classic ATmega328P Arduino Uno lacks hardware CAN controller, so an external MCP2515 SPI CAN controller module + MCP_CAN v1.5 library is mandatory for full CAN2.0 protocol communication.
Refer to MAX33041E Shield-Evaluates: MAX33041E , below is MAX33041ESHLD

rear side view
`
Here is the MAX33041 chip

stack the MAX33041ESHLD with Arduino Uno Q
with JUMPER configuration
| Jumper | Default Setting | Function |
| JU1 | TXD=D1, RXD=D0 | PHY TX ← Arduino D1; PHY RX → Arduino D0 |
| JU10 | 1-2 | STBY pin tied to Arduino D6 (LOW=normal CAN, HIGH=sleep) |
| JU9 | 1-2 | SHDN pin tied to Arduino D7 |
| JU11 | 2-3 | External VDD power; switch to 1-2 to power MAX33041E from Arduino 3.3V |
| JU7/JU8 | 2-3 | 60Ω internal load; set 1-2 for integrated 120Ω CAN bus termination |

via Arduino Pin
- MCP2515 SPI to Uno: SCK=D13, MOSI=D11, MISO=D12, CS=D10, INT=D2 (MCP_CAN default pin definition)
- MAX33041ESHLD Logic Lines:
- Shield TXD(D1) ← MCP2515 TX output
- Shield RXD(D0) → MCP2515 RX input
- Shield STBY(D6)=LOW (permanently enable transceiver working mode)

For other part of CAN ,
CAN Bus: Connect MCP2515 CANH/CANL to MAX33041ESHLD CANH/CANL; enable 120Ω termination at bus endpoints via JU7/JU8=1-2.
2 Run the pilot test code
Open the Arduino App LAB and search the board
download and install the can library for arduino, refer to GitHub - coryjfowler/MCP_CAN_lib: MCP_CAN Library · GitHub
Core API Features for the MCP_CAN lib,
Initialization: CAN.begin(mcp_type, baudrate, crystal) supports 5k~1000k baud @8/16/20MHz MCP2515 clock; after init defaults to loopback mode, use setMode(MCP_NORMAL) to switch to real bus communication.
Receive API readMsgBuf(&id, &len, buf):
id & 0x80000000 = true: 29-bit extended CAN ID; else standard 11-bit IDid & 0x40000000 = true: received remote frame- Alternative overload
readMsgBuf(&id, &ext, &len, buf):ext=1= extended ID (no remote flag inside ID)
Transmit API:
sendMsgBuf(id, len, buf):id|=0x80000000→ extended ID;id|=0x40000000→ remote transmit requestsendMsgBuf(id, ext, len, buf): second parameterext=1for extended ID
enOneShotTX()/disOneShotTX(): enable/disable single-shot transmitsetSleepWakeup(1): open bus-wake interrupt for sleep mode recovery
Here is the test code
#include <mcp_can.h>
#include <SPI.h>
// Pin definition for MAX33041ESHLD# Shield
#define CAN_CS_PIN 10
#define CAN_INT_PIN 2
// Initialize CAN controller
MCP_CAN CAN(CAN_CS_PIN);
// CAN message buffers
unsigned char canRxData[8]; // Received data
unsigned char canTxData[8] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}; // Send data
long unsigned int rxId; // Received ID
unsigned char len; // Data length
unsigned char extFlag = 0; // 0 = Standard ID (11-bit), 1 = Extended ID (29-bit)
void setup() {
Serial.begin(115200);
while (!Serial);
// Initialize CAN bus: 500kbps baud rate, 8MHz clock (standard)
if (CAN.begin(MCP_ANY, CAN_500KBPS, MCP_8MHZ) == CAN_OK) {
Serial.println("CAN Initialized Successfully! (MAX33041E)");
} else {
Serial.println("CAN Init Failed! Check Wiring/Power");
while (1); // Halt if failed
}
// Set CAN mode to normal (transmit/receive)
CAN.setMode(MCP_NORMAL);
// Enable interrupt for receiving
pinMode(CAN_INT_PIN, INPUT);
}
void loop() {
// --------------------------
// 1. RECEIVE CAN MESSAGE
// --------------------------
if (!digitalRead(CAN_INT_PIN)) {
CAN.readMsgBuf(&rxId, &len, canRxData);
Serial.print("Received ID: 0x");
Serial.print(rxId, HEX);
Serial.print(" | Data Length: ");
Serial.print(len);
Serial.print(" | Data: ");
for (int i = 0; i < len; i++) {
Serial.print(canRxData[i], HEX);
Serial.print(" ");
}
Serial.println();
}
// --------------------------
// 2. SEND CAN MESSAGE (every 1 second)
// --------------------------
// Send to ID: 0x123 (standard 11-bit), 8 bytes data
byte sendStatus = CAN.sendMsgBuf(0x123, 0, 8, canTxData);
if (sendStatus == CAN_OK) {
Serial.println("Message Sent Successfully!");
} else {
Serial.println("Send Failed!");
}
delay(1000);
}
Press run for the progress
and here is output from terminal, since this is only one side of CAN transmitter, fail it is right result. Improve later.
Be noted, python is run as well. That is Arduino Uno Q, and how it plays
3 Summary
Now the CAN transceiver is ready to go,
Next step, get data from sensor data from another CAN terminal .