L9958 & SX8847 SPI register access problem

Have anybody managed to access the registers in L9958 (from ST) or the SX8847 H-bridge board. I have this H bridge, http://www.ebay.com/itm/New-240W-H-bridge-Motor-Driver-Board-Motor-Controller-SPI-for-Arduino-Smart-Car-/251264551913?pt=LH_DefaultDomain_0&hash=item3a8088cbe9 I have the manual, http://www.st.com/web/catalog/sense_power/FM1965/SC1039/PF246497 , but there is information how to write and read the registers. I want to use Arduino and its SPI library for this purpose.

I have the same problem. I bought this motor driver and want to set the max current. If anybody has already a lib, what can do this with the SPI-Interface, please post it here. Otherwise I have to invent the wheel new. And that takes time, but I will do it if it is necessary.

Hi ,

it works. :) :) :) Yesterday I wrote a function to read out the diagnostic-register and write the config-register. It needs the Config-word and returns the diag_word. It is no heavy stuff, really simple.

Now, I want to make a L9958_Lib. For the easy use. When I am finished I post it here.

Here for the beginnig: Insert code into a new sketch. Upoad and Serial Monitor
The function is W_R_REG()

Sorry some comments are german :slight_smile:

// Konfigurationsregister  (CFG_REG)
// Bit		        Symbol		Beschreibung				Wert nach Reset
// 0 LSB		RES		Reserviert				-
// 1 			DR		Diagnostic Reset Bit 			0              -> Auf 1 ändern Reset nach Enable off
// 2 			CL_1		Bit1 for Regulation Current Level	0
// 3 			CL_2		Bit2 for Regulation Current Level 	1
// 4 			RES		Reserviert				-
// 5 			RES		Reserviert				-
// 6 			RES		Reserviert				-
// 7 			RES		Reserviert				-
// 8			VSR		Voltage Slew Rate Control Value		0
// 9 			ISR		Current Slew Rate Control Value 	0
// 10			ISR_DIS		Current Slew Rate Control Disable	0
// 11			OL_ON		Open Load in ON state Enable 		0
// 12			RES		Reserviert				-
// 13			RES		Reserviert		          	-
// 14			0		"0" to be written			-
// 15 MSB		0		"0" to be written			-

// Diagnoseregister  (DIAG_REG)
// Bit		        Symbol		Beschreibung				Wert nach Reset
// 0 LSB		OL_OFF		Open Load in OFF condition		0
// 1 			OL_ON		Open Load in ON condition		0
// 2 			VS_UV		Vs undervoltage                 	0
// 3 			VDD_OV		Vdd overvoltage                 	0
// 4 			ILIM    	Current Limitation reached      	0
// 5 			TWARN		Temperature warning 			0
// 6 			TSD		Over-temperature Shutdown		0
// 7 			ACT		Bridge enable 				1
// 8			OC_LS1 		Over-Current on Low Side 1	        0
// 9 			OC_LS2		Over-Current on Low Side 2       	0
// 10			OC_HS1 		Over-Current on High Side 1      	0
// 11			OC_HS2		Over-Current on High Side 2 		0
// 12			Null		Not used				-
// 13			Null		Not used		          	-
// 14			SGND_OFF	Short to Ground in OFF condition	0
// 15 MSB		SBAT_OFF	Short to Battery in OFF condition	0


// SPI-Mode=1


//   DIR: pin 3
//   DI:  pin 4
//   PWM: pin 5
//   EN:  pin 6
//   CS: pin 7
//   MOSI: pin 11
//   MISO: pin 12
//   SCK: pin 13


#include <SPI.h>

// Config vorbereiten
    // Diagnostic Reset Bit = HIGH  -> Fehlerreset nur bei ausgeschaltetem "Enable"
    // CL_1 und CL_2  = HIGH -> Maximaler Strom  = 8,6A 
const word CFG_REG = {0b0000000000001110};    // CFG_REG

const int CS_Pin = 7;

void setup() {
  Serial.begin(9600);

  // start the SPI library:
  SPI.setBitOrder(LSBFIRST);
  SPI.setDataMode(SPI_MODE1); 
  SPI.begin(); 

  // initalize the chip select pin:
  pinMode(CS_Pin, OUTPUT);


  delay(100);
  Serial.println("Init_Done");
  
}

void loop(){
  String DIAG_REG[2][16]={{
                "RES      =",           //Open Load in OFF condition		
 	        "DR       =",	        //Open Load in ON condition		
       		"CL_1     =",		//Vs undervoltage                 	
 		"CL_2     =",		//Vdd overvoltage                 	
 		"RES      =",      	//Current Limitation reached      	
 		"RES      =",		//Temperature warning 			
 		"RES      =",		//Over-temperature Shutdown		
 		"RES      =",		//Bridge enable 	        	
		"VSR      =", 		//Over-Current on Low Side 1	        
 		"ISR      =",		//Over-Current on Low Side 2       	
		"ISR_DIS  =", 		//Over-Current on High Side 1      	
		"OL_ON    =",		//Over-Current on High Side 2 		
		"RES      =",		//Not used				-
		"RES      =", 		//Not used		          	-
		"0        =",	        //Short to Ground in OFF condition	
		"0        ="},	        //Short to Battery in OFF condition	       
                          {
                "OL_OFF   =",           //Open Load in OFF condition		
 	        "OL_ON    =",	        //Open Load in ON condition		
       		"VS_UV    =",		//Vs undervoltage                 	
 		"VDD_OV   =",		//Vdd overvoltage                 	
 		"ILIM     =",      	//Current Limitation reached      	
 		"TWARN    =",		//Temperature warning 			
 		"TSD      =",		//Over-temperature Shutdown		
 		"ACT      =",		//Bridge enable 	        	
		"OC_LS1   =", 		//Over-Current on Low Side 1	        
 		"OC_LS2   =",		//Over-Current on Low Side 2       	
		"OC_HS1   =", 		//Over-Current on High Side 1      	
		"OC_HS2   =",		//Over-Current on High Side 2 		
		"Null     =",		//Not used				-
		"Null     =", 		//Not used		          	-
		"SGND_OFF =",	        //Short to Ground in OFF condition	
		"SBAT_OFF ="}};	        //Short to Battery in OFF condition	    
      
  Serial.println("\n\nW/R_Prozedur\n");

  
  // Ausgabe der Register
  Serial.println("\n\nKonfigurationsregister\n");
  for (int i=0 ; i<16;i++){
    Serial.print(DIAG_REG[0][i]);
    if ((CFG_REG>>i & 0b1)==1){
      Serial.println("Ein");
    }else Serial.println("Aus");
  }
  
  Serial.println(CFG_REG,BIN);
  word DIAG=W_R_REG(CFG_REG);
  // Ausgabe der Register
  Serial.println("\n\nDiagnoseregister\n");
  for (int i=0 ; i<16;i++){
    Serial.print(DIAG_REG[1][i]);
    if ((DIAG>>i & 0b1)==1){
      Serial.println("Ein");
    }else Serial.println("Aus");
    
  }
  delay(10000); 
}


//Schreiben/Lesen vom L9958:
word W_R_REG(word CFG ) {
  
  //Zwischenspeicher vorbereiten
  byte buffer[2]={0b0,0b0};

  // Zwischenspeicher mit Config-Registerdaten laden
  buffer[0] = CFG;      // LSB
  buffer[1] = CFG >>8;  // MSB (CFG 8bit schieben)

  // den "chip select" low zur Geräteauswahl:
  digitalWrite(CS_Pin, LOW);
  
  // Daten senden und Empfangen
   buffer[0] =SPI.transfer(buffer[0]);
   buffer[1] =SPI.transfer(buffer[1]);
  // Dauer ca 500us
  
  // den "chip select" high zur Abwahl:
  digitalWrite(CS_Pin, HIGH);

  // Empfangene Daten für die Rückgabe vorbereiten
  CFG = buffer[1];          // MSB 
  CFG = CFG <<8;            // erstes Byte nach links schieben
  CFG = CFG | buffer[0];    // LSB laden
  
  // Rückgabewert
  return (CFG);
}

I just want to say thanks to henktronik, and post the following revised code, which is commented in English, has somewhat MORE in the way of comments, and is structured slightly better (IMHO), although it uses up more memory (slightly).

// CODE by Henktronik, modified and converted to English comments 
// by spike7638. 
//
// NOTES: 
// Configuration Register bits  (CFG_REG)
// Bit		    Symbol	Meaning	                           Value after Reset
// 0 LSB		RES	    Reserved                           -
// 1 			DR	    Diagnostic Reset Bit               0              -> Is set to 1 during a Reset with Enable off
// 2 			CL_1    Bit1 for Regulation Current Level  0
// 3 			CL_2    Bit2 for Regulation Current Level  1
// 4 			RES	    Reserved                           -
// 5 			RES	    Reserved                           -
// 6 			RES	    Reserved                           -
// 7 			RES	    Reserved                           -
// 8			VSR	    Voltage Slew Rate Control Value    0
// 9 			ISR	    Current Slew Rate Control Value    0
// 10			ISR_DIS Current Slew Rate Control Disable  0
// 11			OL_ON   Open Load in ON state Enable       0
// 12			RES	    Reserved                           -
// 13			RES     Reserved                           -
// 14			0       "0" to be written                  -
// 15 MSB		0       "0" to be written                  -

// Diagnostic Register  bits (DIAG_REG)
// Bit          Symbol      Meaning                        Value after Reset
// 0 LSB		OL_OFF		Open Load in OFF condition     0
// 1 			OL_ON		Open Load in ON condition      0
// 2 			VS_UV		Vs undervoltage                0
// 3 			VDD_OV		Vdd overvoltage                0
// 4 			ILIM    	Current Limitation reached     0
// 5 			TWARN		Temperature warning            0
// 6 			TSD         Over-temperature Shutdown      0
// 7 			ACT         Bridge enable                  1
// 8			OC_LS1      Over-Current on Low Side 1     0
// 9 			OC_LS2      Over-Current on Low Side 2     0
// 10			OC_HS1      Over-Current on High Side 1    0
// 11			OC_HS2      Over-Current on High Side 2    0
// 12			Null        Not used                       -
// 13			Null        Not used                       -
// 14			SGND_OFF    Short to Ground in OFF condition  0
// 15 MSB		SBAT_OFF    Short to Battery in OFF condition 0


// SPI-Mode=1

// CONNECTIONS TO BE MADE BETWEEN ARDUINO AND MOTOR CONTROL BOARD
//   DIR: pin 3
//   DI:  pin 4
//   PWM: pin 5
//   EN:  pin 6
//   CS: pin 7
//   MOSI: pin 11    <---- on my motor board, the order is SO, SI, SCK, so these require a swap!
//   MISO: pin 12
//   SCK: pin 13

// Definitions of pins for later use
const int DIR_Pin  = 3;
const int DI_Pin   = 4;
const int PWM_Pin  = 5;
const int EN_Pin   = 6;
const int CS_Pin   = 7;
const int MOSI_Pin = 11;
const int MISO_Pin = 12;
const int SCK_Pin  = 13;

#include <SPI.h>

// Config preparation
   // Diagnostic Reset Bit = HIGH  -> (Errors are reset only when ENABLE)
   // CL_1 und CL_2  = HIGH -> max current = 8,6A 
   // Note: 
   // CL_1, CL_2 = 00 -> max = 2.5A
   // CL_1, CL_2 = 10 -> max = 4A
   // CL_1, CL_2 = 01 -> max = 6.6A
   

// You should enter in this table thr values you want for the various configuration properties. 
const int config[16] = {
	0,	// 0 LSB		RES	    Reserved                           -
	1,	// 1 			DR	    Diagnostic Reset Bit               0              -> Is set to 1 during a Reset with Enable off
	1,	// 2 			CL_1    Bit1 for Regulation Current Level  0 (1, 1) generates 8.6A max current
	1,	// 3 			CL_2    Bit2 for Regulation Current Level  1
	0,	// 4 			RES	    Reserved                           -
	0, 	// 5 			RES	    Reserved                           -
	0,	// 6 			RES	    Reserved                           -
	0,	// 7 			RES	    Reserved                           -
	0,	// 8			VSR	    Voltage Slew Rate Control Value    0
	0,	// 9 			ISR	    Current Slew Rate Control Value    0
	0,	// 10			ISR_DIS Current Slew Rate Control Disable  0
	0,	// 11			OL_ON   Open Load in ON state Enable       0
	0,	// 12			RES	    Reserved                           -
	0,	// 13			RES     Reserved                           -
	0,	// 14			0       "0" to be written                  -
	0, 	// 15 MSB		0       "0" to be written                  -
};

word CFG_REG = 0;

void setup() {
 int i = 0;
 for (i = 15; i >= 0; i--) {
 	CFG_REG = CFG_REG<<1;
 	CFG_REG += config[i];
 }
 //const word CFG_REG = {0b0000000000001110};    // CFG_REG data

 Serial.begin(9600);

 // start the SPI library:
 SPI.setBitOrder(LSBFIRST);
 SPI.setDataMode(SPI_MODE1); 
 SPI.begin(); 

 // initalize the chip select pin:
 pinMode(CS_Pin, OUTPUT);
 pinMode(EN_Pin, OUTPUT);
 pinMode(DI_Pin, OUTPUT);

 delay(100);
 Serial.println("\n\n### Init_Done");
 
}

void loop(){
 String CONFIG_REG[16]={
        "RES      = ",       //Reserved		
	    "DR       = ",	    //Diagnostic reset bit		
      	"CL_1     = ",		//Bit 1 for current regulation                 	
		"CL_2     = ",		//Bit 2 for current regulation                 	
		"RES      = ",      	//Reserved	     	
		"RES      = ",		//Reserved				
		"RES      = ",		//Reserved		
		"RES      = ",		//Reserved	 	        	
		"VSR      = ", 		//Voltage Slew Rate Control Value	        
		"ISR      = ",		//Current Slew Rate Control Value      	
		"ISR_DIS  = ", 		//Current Slew Rate Control Disable     	
		"OL_ON    = ",		//Open Load in ON state Enable  		
		"RES      = ",		//Reserved			-
		"RES      = ", 		//Reserved		          	-
		"0        = ",	        //0 to be written	
		"0        = "};	        //0 to be written	       
 String DIAG_REG[16]={          
        "OL_OFF   = ",           //Open Load in OFF condition		
	    "OL_ON    = ",	        //Open Load in ON condition		
      	"VS_UV    = ",		//Vs undervoltage                 	
		"VDD_OV   = ",		//Vdd overvoltage                 	
		"ILIM     = ",      	//Current Limitation reached      	
		"TWARN    = ",		//Temperature warning 			
		"TSD      = ",		//Over-temperature Shutdown		
		"ACT      = ",		//Bridge enable 	        	
		"OC_LS1   = ", 		//Over-Current on Low Side 1	        
		"OC_LS2   = ",		//Over-Current on Low Side 2       	
		"OC_HS1   = ", 		//Over-Current on High Side 1      	
		"OC_HS2   = ",		//Over-Current on High Side 2 		
		"Null     = ",		//Not used				-
		"Null     = ", 		//Not used		          	-
		"SGND_OFF = ",	        //Short to Ground in OFF condition	
		"SBAT_OFF = "};	        //Short to Battery in OFF condition	    
		
 Serial.println("\n\nRead/Write Procedure\n"); // Output from register
 Serial.println("\n\nConfiguration register settings:\n");
 for (int i=0 ; i<16;i++){
   Serial.print(CONFIG_REG[i]);
   if ((CFG_REG>>i & 0b1)==1){
     Serial.println("1");
   }else Serial.println("0");
 }
 
 Serial.println(CFG_REG,BIN);
 word DIAG=W_R_REG(CFG_REG);
 // Ausgabe der Register
 Serial.println("\n\nDiagnostic register\n");
 for (int i=0 ; i<16;i++){
   Serial.print(DIAG_REG[i]);
   if ((DIAG>>i & 0b1)==1){
     Serial.println("1");
   }else Serial.println("0");
   
 }
 delay(10000); 
}


//Write and Read to/from L9958:
word W_R_REG(word CFG ) {
 
 // Space in which to read/write data
 byte buffer[2]={0b0,0b0};

 // Load the two bytes from the config register into the buffer
 buffer[0] = CFG;      // LSB
 buffer[1] = CFG >>8;  // MSB (CFG 8bit schieben)

 // Set "chip select" low to allow reading/writing
 digitalWrite(CS_Pin, LOW);
 
 // Send the config data to the SPI; read back the Diagnostic register
 // Note that the readback is from the PREVIOUS setting of the config data; you need
 // to wait one cycle to read the diagonistic register following the current config. 
  buffer[0] =SPI.transfer(buffer[0]);
  buffer[1] =SPI.transfer(buffer[1]);
 // This takes about 500us
 
 // Set "chip select" high so you can continue with other chip operations (and prepare for next write/read)
 digitalWrite(CS_Pin, HIGH);
 //digitalWrite(EN_Pin, LOW);
 //digitalWrite(DI_Pin, HIGH);

 // Load the data you read into the two-byte buffer
 word DIAG;
 DIAG = buffer[1];          // MSB 
 DIAG = DIAG <<8;            // erstes Byte nach links schieben
 DIAG = DIAG | buffer[0];    // LSB laden
 
 // ...and return it
 return (DIAG);
}