Arduino SPI MAX17841B

Hi,

I need to control a MAX17841B module with spi interface on an ATMEGA328PB

So, i don't know how i can control the module (https://datasheets.maximintegrated.com/en/ds/MAX17841B.pdf)

I think , I need to send an address and after several data ?

Thank you...

kealmlj:
Hi,

I need to control a MAX17841B module with spi interface on an ATMEGA328PB

So, i don’t know how i can control the module (https://datasheets.maximintegrated.com/en/ds/MAX17841B.pdf)

I think , I need to send an address and after several data ?

Thank you…

based on table 10 and 11 in the datasheets something like this maybe…
(compiles, NOT tested!)

//Include Libraries
#include <SPI.h>

#define cs_pin 10
#define intr_pin 9

void MAX17841B_init() {
  digitalWrite(cs_pin, LOW); //Select Chip
  //Daisy-Chain Initialization Sequence
  //TRANSACTION 1 Enable Keep-Alive mode (prior to the UART slave wake-up to prevent shutdown)
  SPI.transfer(0x10);	//response = xxh. Write Configuration 3 register
  SPI.transfer(0x05);	//response = xxh. Set keep - alive period to 160µs
  //TRANSACTION 2 Enable Rx Interrupt flags for RX_Error and RX_Overflow
  SPI.transfer(0x04);	//response = xxh. Write RX_Interrupt_Enable register
  SPI.transfer(0x88);	//response = xxh. Set the RX_Error_INT_Enable and RX_Overflow_INT_Enable bits
  //TRANSACTION 3 Clear receive buffer
  SPI.transfer(0xE0);	//response = xxh. Clear receive buffer
  //TRANSACTION 4 Wake-up UART slave devices (transmit preambles)
  SPI.transfer(0x0E);	//response = xxh. Write Configuration 2 register
  SPI.transfer(0x30);	//response = xxh. Enable Transmit Preambles mode
  //TRANSACTION 5 Wait for all UART slave devices to wake up (poll RX_Busy_Status bit)
  SPI.transfer(0x01);	//response = xxh. Read RX_Status register (RX_Busy_Status and RX_Empty_Status should be true)
  SPI.transfer(0xFF);	//response = 21h. If RX_Status = 21h, continue. Otherwise, repeat transaction until true or timeout.
  //TRANSACTION 6 End of UART slave device wake-up period
  SPI.transfer(0x0E);	//response = xxh. Write Configuration 2 register
  SPI.transfer(0x10);	//response = xxh. Disable Transmit Preambles mode
  //TRANSACTION 7 Wait for null message to be received (poll RX_Empty_Status bit)
  SPI.transfer(0x01);	//response = xxh. Read RX_Status register
  //TRANSACTION 8 Clear transmit buffer
  SPI.transfer(0x20);	//response = xxh. Clear transmit buffer
  //TRANSACTION 9 Clear receive buffer
  SPI.transfer(0xE0);	//response = xxh. Clear receive buffer
  //TRANSACTION 10 Load the HELLOALL command sequence into the load queue
  SPI.transfer(0xC0);	//response = xxh. WR_LD_Q SPI command byte (write the load queue)
  SPI.transfer(0x03);	//response = xxh. Message length
  SPI.transfer(0x57);	//response = xxh. HELLOALL command byte
  SPI.transfer(0x00);	//response = xxh. Register address (0x00)
  SPI.transfer(0x00);	//response = xxh. Initialization address of HELLOALL
  //TRANSACTION 11 Verify contents of the load queue
  SPI.transfer(0xC1);	//response = xxh. RD_LD_Q SPI command byte
  SPI.transfer(0xFF);	//response = 03h. OK
  SPI.transfer(0xFF);	//response = 57h. OK
  SPI.transfer(0xFF);	//response = 00h. OK
  SPI.transfer(0xFF);	//response = 00h. OK
  //TRANSACTION 12 Transmit HELLOALL sequence
  SPI.transfer(0xB0);	//response = xxh. WR_NXT_LD_Q SPI command byte (write the next load queue)
  //TRANSACTION 13 Poll RX_Stop_Status bit
  SPI.transfer(0x01);	//response = xxh. Read RX_Status register
  SPI.transfer(0xFF);	//response = 12h. If RX_Status[1] is true, continue. If false, then repeat transaction until true.
  //TRANSACTION 14 Service receive buffer. Read the HELLOALL message that propagated through the daisy-chain and was
  SPI.transfer(0x93);	//response = xxh. RD_NXT_MSG SPI transaction
  SPI.transfer(0xFF);	//response = 57h. Sent command byte (HELLOALL)
  SPI.transfer(0xFF);	//response = 00h. Sent address = 00h
  SPI.transfer(0xFF);	//response = 02h. Returned address = 02h
  //TRANSACTION 15 Check for receive buffer errors
  SPI.transfer(0x09);	//response = xxh. Read RX_Interrupt_Flags register
  SPI.transfer(0xFF);	//response = 00h. If no errors, continue. Otherwise, clear and go to error routine.

  digitalWrite(cs_pin, HIGH); //Deselect Chip
}

void MAX17841B_writeAll() {
  digitalWrite(cs_pin, LOW); //Select Chip

  //TRANSACTION 1 Load the WRITEALL command sequence into the load queue
  SPI.transfer(0xC0);	//response = xxh. WR_LD_Q SPI command byte
  SPI.transfer(0x06);	//response = xxh. Message length = 6
  SPI.transfer(0x02);	//response = xxh. WRITEALL command byte
  SPI.transfer(0x12);	//response = xxh. Register address of the device
  SPI.transfer(0xB1);	//response = xxh. LS byte of register data to be written
  SPI.transfer(0xB2);	//response = xxh. MS byte of register data to be written
  SPI.transfer(0xC4);	//response = xxh. PEC byte for 02h, 12h, B1h, B2h
  SPI.transfer(0x00);	//response = xxh. Alive-counter byte (seed value = 0)
  //TRANSACTION 2 Start transmitting the WRITEALL sequence from the transmit queue
  SPI.transfer(0xB0);	//response = xxh. WR_NXT_LD_Q SPI command byte
  //TRANSACTION 3 Check if a message has been received into the receive buffer
  SPI.transfer(0x01);	//response = xxh. Read RX_Status register
  SPI.transfer(0xFF);	//response = 12h. If RX_Status[1] is true, continue. Otherwise, repeat until true or timeout.
  //TRANSACTION 4 Read receive buffer to verify the sent WRITEALL message
  SPI.transfer(0x93);	//response = xxh. RD_NXT_MSG SPI
  SPI.transfer(0xFF);	//response = 02h. Sent command byte (WRITEALL)
  SPI.transfer(0xFF);	//response = 12h. Sent address
  SPI.transfer(0xFF);	//response = B1h. Sent LS byte
  SPI.transfer(0xFF);	//response = B2h. Sent MS byte
  SPI.transfer(0xFF);	//response = C4h. Sent PEC
  SPI.transfer(0xFF);	//response = 02h. Alive-counter byte (= sent seed + 2, if alive counter enabled)
  //TRANSACTION 5 Check for receive buffer errors
  SPI.transfer(0x09);	//response = xxh. Read RX_Interrupt_Flags register
  SPI.transfer(0xFF);	//response = 00h. If no errors, continue. Otherwise, clear and go to error routine.

  digitalWrite(cs_pin, HIGH); //Deselect Chip
}

void MAX17841B_readAll() {
  digitalWrite(cs_pin, LOW); //Select Chip

  //TRANSACTION 1 Load the READALL command sequence into the load queue
  SPI.transfer(0xC0);	//response = xxh. WR_NXT_LD_Q SPI command byte
  SPI.transfer(0x09);	//response = xxh. Message length (5 + 2 x n = 9)
  SPI.transfer(0x03);	//response = xxh. READALL command byte
  SPI.transfer(0x12);	//response = xxh. Register address
  SPI.transfer(0x00);	//response = xxh. Data-check byte (seed value = 00h)
  SPI.transfer(0xCB);	//response = xxh. PEC byte for bytes 03h, 12h, 00h
  SPI.transfer(0x00);	//response = xxh. Alive-counter byte (seed value = 00h)
  //TRANSACTION 2 Start transmitting the READALL sequence
  SPI.transfer(0xB0);	//response = xxh. WR_NXT_LD_Q SPI command byte
  //TRANSACTION 3 Check if a message has been received into the receive buffer
  SPI.transfer(0x01);	//response = xxh. Read the RX_Status register
  SPI.transfer(0xFF);	//response = 12h. If RX_Status[1] is true, continue. Otherwise, repeat until true or timeout.
  //TRANSACTION 4 Read the receive buffer and verify that the device register data is what was written during the WRITEALLsequence
  SPI.transfer(0x93);	//response = xxh. RD_NXT_MSG SPI command byte
  SPI.transfer(0xFF);	//response = 03h. Sent command byte (READALL)
  SPI.transfer(0xFF);	//response = 12h. Sent register address
  SPI.transfer(0xFF);	//response = B1h. LS byte of device 1
  SPI.transfer(0xFF);	//response = B2h. MS byte of device 1
  SPI.transfer(0xFF);	//response = B1h. LS byte of device 0
  SPI.transfer(0xFF);	//response = B2h. MS byte of device 0
  SPI.transfer(0xFF);	//response = 00h. Data-check byte (= 00h if all status bits have been cleared)
  SPI.transfer(0xFF);	//response = 67h. PEC (for the previous 7 bytes)
  SPI.transfer(0xFF);	//response = 02h. Alive-counter byte (= sent seed + 2, if alive counter is enabled)
  //TRANSACTION 5 Check for receive buffer errors
  SPI.transfer(0x09);	//response = xxh. Read RX_Interrupt_Flags register
  SPI.transfer(0xFF);	//response = 00h. If no errors, continue. Otherwise, clear and go to error routine

  digitalWrite(cs_pin, HIGH); //Deselect Chip
}

void setup() {
  
  Serial.begin(115200);
  
  //initialise IOs and SPI comms
  //SPI clock speed:4MHz, Data Shift:MSB First, Data Clock Idle: SPI_MODE0
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));

  pinMode(cs_pin, OUTPUT);    //MAX17841B_CS
  digitalWrite(cs_pin, HIGH); //Deselect Chip
  pinMode(intr_pin, INPUT);   //MAX17841B_INT

  MAX17841B_init();

  MAX17841B_writeAll();

  MAX17841B_readAll();

}

void loop() {


}

hope that gets you going! :wink:

I would suggest you get there evaluation kit. This was originally an automotive part, probably custom. Your link does not work.

sherzaad:
based on table 10 and 11 in the datasheets something like this maybe…
(compiles, NOT tested!)

//Include Libraries

#include <SPI.h>

#define cs_pin 10
#define intr_pin 9

void MAX17841B_init() {
 digitalWrite(cs_pin, LOW); //Select Chip
 //Daisy-Chain Initialization Sequence
 //TRANSACTION 1 Enable Keep-Alive mode (prior to the UART slave wake-up to prevent shutdown)
 SPI.transfer(0x10); //response = xxh. Write Configuration 3 register
 SPI.transfer(0x05); //response = xxh. Set keep - alive period to 160µs
 //TRANSACTION 2 Enable Rx Interrupt flags for RX_Error and RX_Overflow
 SPI.transfer(0x04); //response = xxh. Write RX_Interrupt_Enable register
 SPI.transfer(0x88); //response = xxh. Set the RX_Error_INT_Enable and RX_Overflow_INT_Enable bits
 //TRANSACTION 3 Clear receive buffer
 SPI.transfer(0xE0); //response = xxh. Clear receive buffer
 //TRANSACTION 4 Wake-up UART slave devices (transmit preambles)
 SPI.transfer(0x0E); //response = xxh. Write Configuration 2 register
 SPI.transfer(0x30); //response = xxh. Enable Transmit Preambles mode
 //TRANSACTION 5 Wait for all UART slave devices to wake up (poll RX_Busy_Status bit)
 SPI.transfer(0x01); //response = xxh. Read RX_Status register (RX_Busy_Status and RX_Empty_Status should be true)
 SPI.transfer(0xFF); //response = 21h. If RX_Status = 21h, continue. Otherwise, repeat transaction until true or timeout.
 //TRANSACTION 6 End of UART slave device wake-up period
 SPI.transfer(0x0E); //response = xxh. Write Configuration 2 register
 SPI.transfer(0x10); //response = xxh. Disable Transmit Preambles mode
 //TRANSACTION 7 Wait for null message to be received (poll RX_Empty_Status bit)
 SPI.transfer(0x01); //response = xxh. Read RX_Status register
 //TRANSACTION 8 Clear transmit buffer
 SPI.transfer(0x20); //response = xxh. Clear transmit buffer
 //TRANSACTION 9 Clear receive buffer
 SPI.transfer(0xE0); //response = xxh. Clear receive buffer
 //TRANSACTION 10 Load the HELLOALL command sequence into the load queue
 SPI.transfer(0xC0); //response = xxh. WR_LD_Q SPI command byte (write the load queue)
 SPI.transfer(0x03); //response = xxh. Message length
 SPI.transfer(0x57); //response = xxh. HELLOALL command byte
 SPI.transfer(0x00); //response = xxh. Register address (0x00)
 SPI.transfer(0x00); //response = xxh. Initialization address of HELLOALL
 //TRANSACTION 11 Verify contents of the load queue
 SPI.transfer(0xC1); //response = xxh. RD_LD_Q SPI command byte
 SPI.transfer(0xFF); //response = 03h. OK
 SPI.transfer(0xFF); //response = 57h. OK
 SPI.transfer(0xFF); //response = 00h. OK
 SPI.transfer(0xFF); //response = 00h. OK
 //TRANSACTION 12 Transmit HELLOALL sequence
 SPI.transfer(0xB0); //response = xxh. WR_NXT_LD_Q SPI command byte (write the next load queue)
 //TRANSACTION 13 Poll RX_Stop_Status bit
 SPI.transfer(0x01); //response = xxh. Read RX_Status register
 SPI.transfer(0xFF); //response = 12h. If RX_Status[1] is true, continue. If false, then repeat transaction until true.
 //TRANSACTION 14 Service receive buffer. Read the HELLOALL message that propagated through the daisy-chain and was
 SPI.transfer(0x93); //response = xxh. RD_NXT_MSG SPI transaction
 SPI.transfer(0xFF); //response = 57h. Sent command byte (HELLOALL)
 SPI.transfer(0xFF); //response = 00h. Sent address = 00h
 SPI.transfer(0xFF); //response = 02h. Returned address = 02h
 //TRANSACTION 15 Check for receive buffer errors
 SPI.transfer(0x09); //response = xxh. Read RX_Interrupt_Flags register
 SPI.transfer(0xFF); //response = 00h. If no errors, continue. Otherwise, clear and go to error routine.

digitalWrite(cs_pin, HIGH); //Deselect Chip
}

void MAX17841B_writeAll() {
 digitalWrite(cs_pin, LOW); //Select Chip

//TRANSACTION 1 Load the WRITEALL command sequence into the load queue
 SPI.transfer(0xC0); //response = xxh. WR_LD_Q SPI command byte
 SPI.transfer(0x06); //response = xxh. Message length = 6
 SPI.transfer(0x02); //response = xxh. WRITEALL command byte
 SPI.transfer(0x12); //response = xxh. Register address of the device
 SPI.transfer(0xB1); //response = xxh. LS byte of register data to be written
 SPI.transfer(0xB2); //response = xxh. MS byte of register data to be written
 SPI.transfer(0xC4); //response = xxh. PEC byte for 02h, 12h, B1h, B2h
 SPI.transfer(0x00); //response = xxh. Alive-counter byte (seed value = 0)
 //TRANSACTION 2 Start transmitting the WRITEALL sequence from the transmit queue
 SPI.transfer(0xB0); //response = xxh. WR_NXT_LD_Q SPI command byte
 //TRANSACTION 3 Check if a message has been received into the receive buffer
 SPI.transfer(0x01); //response = xxh. Read RX_Status register
 SPI.transfer(0xFF); //response = 12h. If RX_Status[1] is true, continue. Otherwise, repeat until true or timeout.
 //TRANSACTION 4 Read receive buffer to verify the sent WRITEALL message
 SPI.transfer(0x93); //response = xxh. RD_NXT_MSG SPI
 SPI.transfer(0xFF); //response = 02h. Sent command byte (WRITEALL)
 SPI.transfer(0xFF); //response = 12h. Sent address
 SPI.transfer(0xFF); //response = B1h. Sent LS byte
 SPI.transfer(0xFF); //response = B2h. Sent MS byte
 SPI.transfer(0xFF); //response = C4h. Sent PEC
 SPI.transfer(0xFF); //response = 02h. Alive-counter byte (= sent seed + 2, if alive counter enabled)
 //TRANSACTION 5 Check for receive buffer errors
 SPI.transfer(0x09); //response = xxh. Read RX_Interrupt_Flags register
 SPI.transfer(0xFF); //response = 00h. If no errors, continue. Otherwise, clear and go to error routine.

digitalWrite(cs_pin, HIGH); //Deselect Chip
}

void MAX17841B_readAll() {
 digitalWrite(cs_pin, LOW); //Select Chip

//TRANSACTION 1 Load the READALL command sequence into the load queue
 SPI.transfer(0xC0); //response = xxh. WR_NXT_LD_Q SPI command byte
 SPI.transfer(0x09); //response = xxh. Message length (5 + 2 x n = 9)
 SPI.transfer(0x03); //response = xxh. READALL command byte
 SPI.transfer(0x12); //response = xxh. Register address
 SPI.transfer(0x00); //response = xxh. Data-check byte (seed value = 00h)
 SPI.transfer(0xCB); //response = xxh. PEC byte for bytes 03h, 12h, 00h
 SPI.transfer(0x00); //response = xxh. Alive-counter byte (seed value = 00h)
 //TRANSACTION 2 Start transmitting the READALL sequence
 SPI.transfer(0xB0); //response = xxh. WR_NXT_LD_Q SPI command byte
 //TRANSACTION 3 Check if a message has been received into the receive buffer
 SPI.transfer(0x01); //response = xxh. Read the RX_Status register
 SPI.transfer(0xFF); //response = 12h. If RX_Status[1] is true, continue. Otherwise, repeat until true or timeout.
 //TRANSACTION 4 Read the receive buffer and verify that the device register data is what was written during the WRITEALLsequence
 SPI.transfer(0x93); //response = xxh. RD_NXT_MSG SPI command byte
 SPI.transfer(0xFF); //response = 03h. Sent command byte (READALL)
 SPI.transfer(0xFF); //response = 12h. Sent register address
 SPI.transfer(0xFF); //response = B1h. LS byte of device 1
 SPI.transfer(0xFF); //response = B2h. MS byte of device 1
 SPI.transfer(0xFF); //response = B1h. LS byte of device 0
 SPI.transfer(0xFF); //response = B2h. MS byte of device 0
 SPI.transfer(0xFF); //response = 00h. Data-check byte (= 00h if all status bits have been cleared)
 SPI.transfer(0xFF); //response = 67h. PEC (for the previous 7 bytes)
 SPI.transfer(0xFF); //response = 02h. Alive-counter byte (= sent seed + 2, if alive counter is enabled)
 //TRANSACTION 5 Check for receive buffer errors
 SPI.transfer(0x09); //response = xxh. Read RX_Interrupt_Flags register
 SPI.transfer(0xFF); //response = 00h. If no errors, continue. Otherwise, clear and go to error routine

digitalWrite(cs_pin, HIGH); //Deselect Chip
}

void setup() {
 
 Serial.begin(115200);
 
 //initialise IOs and SPI comms
 //SPI clock speed:4MHz, Data Shift:MSB First, Data Clock Idle: SPI_MODE0
 SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));

pinMode(cs_pin, OUTPUT);    //MAX17841B_CS
 digitalWrite(cs_pin, HIGH); //Deselect Chip
 pinMode(intr_pin, INPUT);   //MAX17841B_INT

MAX17841B_init();

MAX17841B_writeAll();

MAX17841B_readAll();

}

void loop() {

}




hope that gets you going! ;)

Thank you very much ! I understand how I can send and receive with SPI interface right now ! Thank you, i’m going to test this

gilshultz:
I would suggest you get there evaluation kit. This was originally an automotive part, probably custom. Your link does not work.

Yes this is an automotive module to control cell in battery.
My link refer to the datasheet of the module

kealmlj:
Thank you very much ! I understand how I can send and receive with SPI interface right now ! Thank you, i’m going to test this

hope all goes well! :wink:

just to clarify, to get/view the ‘return’ value when using SPI.transfer() n’ you should update the code I proposed in the following manner for all the SPI.transfers():

byte c;
c = SPI.transfer(0x10); //0x10 to be updated to the desired value for each SPI transfer
Serial.println(c,HEX); //print to serial monitor in Hexadecimal format

hope that helps…

So If I understand when i Send an SPI Command (SPI.Transfer) I have a return value directly ?.. SPI.Transfer is a function that send and receive ?

kealmlj:
So If I understand when i Send an SPI Command (SPI.Transfer) I have a return value directly ?... SPI.Transfer is a function that send and receive ?

Yes that is correct.
ie for example if you do c = SPI.transfer(0x10);
'0x10' is sent out on the SPI MOSI line, and the received value (on the MISO line) is returned by the function and stored in 'c'.

Thanks ! So i Have one last question, how I can set the INT pin for the spi1 ?

kealmlj:
Thanks ! So i Have one last question, how I can set the INT pin for the spi1 ?

the INT pin is specific to the chip and not SPI comms.
not too sure what is the purpose of the INT pin here (ie what conditions it goes LOW). you would need to study the data sheet a bit more for that.
whether it needs to be checked before doing any SPI reads, I cannot say....