I am getting to grips with MBED and SPI and I seem to have difficulty in reading from slave device registers. I can write to them without issue and confirmed this with a picoscope. However, I get nothing when trying to read from it.
For a little back ground, I am using the DRV8711 stepper motor driver with a LPC1768. the driver uses a 16 bit format with the MSB as the r/w bit (set high to read), followed by a 3 bit address and the remaining 12 bits are instructional. The MISO line also uses a 2K pullup resistor.
Could some one please help me to understand where I could be going wrong and possibly give some advice regarding best practice when programming SPI?
int main(){
initSPI();
initDRV8711();
wait_us(500000);
while(1){
readReg(0b111); //read STATUS Reg, confirm using PicoScope
wait_us(500000);
};
}
void initSPI(){
_cs = CS_DISABLE;
DRV8711.format(16, 3); //16 bits, mode 3
DRV8711.frequency(125000); //125KHz
}
void writeReg(int address, int data){
int setWrite = 0 << 3; //set the write bit and format it to represent w000
int instruct = setWrite | address; //OR the address with the write instruction, WAAA
int formattedInstruct = address << 12; //format the instruct into a 16 bit word, WAAA 0000 0000 0000
int command = formattedInstruct | data; //OR the formatted instruction with the data to be sent, WAAA DDDD DDDD DDDD
_cs.write(CS_ENABLE);
wait_ns(6);
DRV8711.write(command); //send command
wait_ns(6);
_cs.write(CS_DISABLE);
}
int readReg(int address){
int setRead = 1 << 3; //set the read bit and format it to represent w000
int instruct = setRead | address; //OR the address with the write instruction, WAAA
int formattedInstruct = address << 12; //format the instruct into a 16 bit word, WAAA 0000 0000 0000
int command = formattedInstruct | 0b000000000000; //OR the formatted instruction with the data to be sent, WAAA DDDD DDDD DDDD
_cs.write(CS_ENABLE);
wait_ns(6);
int value = DRV8711.write(command); //send dummy command
wait_ns(6);
_cs.write(CS_DISABLE);
return value;
}
Your code works for writing to registers because the read/write bit should be set to 0. But it doesn’t in case of reading because it should be set to 1, however it is set to 0.
I believe your original plan was to use it that way (as you wrote in the comment). This type of bug often happens to me too and it is difficult to find. You need another person to spot it
To read from the device registers, I’ve implemented a seperate function int readReg(int address) which sets the read bit high before sending the command which is a ‘dummy’ command since in this case only the first four bit are needed. (Ive added a screen shot of the data sheet below for clarity). Apologies if i wasn’t clear about the read/write being seperatefunctions, ill make a note in the original post.
To read from the device registers, I’ve implemented a seperate function int readReg(int address) which sets the read bit high before sending the command …
I have seen the readReg function. But, as I said in my first post, it does not set the read bit high!
int readReg(int address){
int setRead = 1 << 3; //set the read bit and format it to represent w000
int instruct = setRead | address; //OR the address with the write instruction, WAAA
//============================================================================
// Please have a closer look. The bug is below!
//
// At this point:
// address = 0AAA and instruct = 1AAA
int formattedInstruct = address << 12; //formats the address into a 16 bit word, 0AAA 0000 0000 0000
// Because the address variable was used in the expression above,
// after the assignment the read bit (most significant bit) is set to 0.
// At this point:
// formattedInstruct = 0AAA 0000 0000 0000
//============================================================================
// Fixed code.
//
// At this point:
// address = 0AAA and instruct = 1AAA
int formattedInstruct = instruct << 12; //formats the instruct into a 16 bit word, 1AAA 0000 0000 0000
// Because the instruct variable was used in the expression above (rather
// than address), after the assignment the read bit (most significant bit)
// is set to 1.
// At this point:
// formattedInstruct = 1AAA 0000 0000 0000
//============================================================================
int command = formattedInstruct | 0b000000000000; //OR the formatted instruction with the data to be sent, WAAA DDDD DDDD DDDD
_cs.write(CS_ENABLE);
wait_ns(6);
int value = DRV8711.write(command); //send dummy command
wait_ns(6);
_cs.write(CS_DISABLE);
return value;
}