Go Down

Topic: Reading MOSI data from Bosch ASIC (Read 3669 times) previous topic - next topic

jtw11

Jan 24, 2013, 04:33 pm Last Edit: Jan 25, 2013, 12:40 am by jtw11 Reason: 1
Hi there,

EDIT - please see latest posts. EDIT.

I'm using a Bosch ASIC in a project I'm toying with, and am trying to communicate with the chip over SPI, essential to its use. However, the Bosch datasheet is incredibly thin on SPI information. Here's all the SPI information on the chip.





I'm struggling with how to write code to interface with this chip, in my SPI setup I've got the following, to correspond with the MSB first requirements, and the clock frequency set as the chip is max 2MBaud.

Code: [Select]
SPI.begin();
SPI.setBitOrder(MSBFIRST); // sets SPI data transfer to MSB first
SPI.setDataMode(SPI_MODE0); // sets SPI mode to MODE0
SPI.setClockDivider(SPI_CLOCK_DIV8); // sets shared clock rate to 16Mhz / 8 = 2Mhz


...and to actually read from a register, RD: 78H, I've got the following...

Code: [Select]
// select chip
digitalWrite(chip_select, LOW);

// send generic 01 address prefix

// send 78H hexadecimal address
SPI.transfer(0x78H);

// send parity?
SPI.transfer();

// send don't care, if needed?

// send 8 dummy bits of data


Any advice would  be greatly appreciated;

1) The generic 01 pre address, I'm not sure how to send this? What to type
2) I'm not sure what parity is?
3) Don't care, I guess I need to send a bit, 1 or 0?
4) How would I go about sending those 8 dummy bits?
5) That leads me into a whole other ball park, how do I go about reading/saving the bits sent back?

Many thanks in advance.

MarkT

Where is the link to the datasheet?
[ I won't respond to messages, use the forum please ]

jtw11

#2
Jan 24, 2013, 05:22 pm Last Edit: Jan 24, 2013, 07:06 pm by jtw11 Reason: 1

Where is the link to the datasheet?


My bad...

http://www.bosch-semiconductors.de/media/pdf_1/einzeldownloads/engine_management/CJ125_Product_Info.pdf

EDIT - As you may have guessed, this is my first venture in to SPI. The hex values I've used in the above code, I've realised don't make sense to me as hex is A through F.... and I've got an H, so I've gone over to binary.

So if I want to transmit a 16bit dataframe, for example, to read the diagnoses register 78h, or decimal 120 - this is what I'm stuck with, where I put this address etc.

kg4wsv

78H means 78 hex.  It's sometimes written as 78H.

In C we write it as 0x78, not 78H (and definitely not 0x78H).

Did 0x78H actually get past the compiler?  It shouldn't  My gcc (solaris and linux) dies with "error: invalid suffix "H" on integer constant" when I tried 0x78H.

-j

jtw11

#4
Jan 24, 2013, 10:24 pm Last Edit: Jan 24, 2013, 11:08 pm by jtw11 Reason: 1
Quote
Did 0x78H actually get past the compiler?  It shouldn't  My gcc (solaris and linux) dies with "error: invalid suffix "H" on integer constant" when I tried 0x78H.


Ha, no don't worry - it did not. I hadn't yet attempted to compile as I knew the code was far from complete, just earlier on I did have a check and no, it threw it out with the same error as you stated.

The problem is, looking at the sequence - I need to enter

0, 1, address bit 1, address bit 2, address bit 3, address bit 4, parity bit (not sure what this is), then any bit as it's don't care, followed by 8 random bits. Found some more info here. http://www.breitband-lambda.de/pages/lambda---english/controlling-the-cj125.php?lang=EN

However, I'm not sure how to enter those 4 address bits, as I know I've now got 0x78, but have no idea how to enter this as four bits?

I'm thinking perhaps, send a 0, send a 1, send a four bit byte that corresponds to 0x78 (is there such thing as a four bit byte?, then send the parity bit, then either a 1 or 0.


EDIT - You know when you try and work something out all day, then for some reason it clicks. Well, it's clicked.

The address MUST be of the format 01xxxxx-, where x is 0 or 1, and - is don't care.

So, converting ALL the possible hex addresses to 8 bit binary, they all start 01, so for example - the diag register of 0x78 is 01111000, so to read from that one simply transmits 01111000, followed by any other 8 bits.

However, how do I go about capturing the data bits that come back in response?

MarkT

SPI.transfer returns a byte result, capture those...
[ I won't respond to messages, use the forum please ]

jtw11


SPI.transfer returns a byte result, capture those...


That's exactly what I'm trying to achieve - I just don't know the syntax or whatnot to achieve this, the SPI library page in the playground has no mention either...

Nick Gammon

Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

michinyon

Lots of datasheets have a description of the SPI protocol.  It doesn't mean you
have to implement it.

If the device works according to the SPI standards,    then the SPI implementation
on the Arduino should be able to talk to it.

If it doesn't,  give up.  I think it is beyond the capability of most people to identify the
problem, and how would you correct it, even if you could diagnose it ?

What this means,  is that you have to have the wiring correct.    And you have to be
making the correct calls from your arduino sketch to the functions of the SPI interface
library.

jtw11

#9
Jan 25, 2013, 12:08 pm Last Edit: Jan 25, 2013, 09:10 pm by Nick Gammon Reason: 1
Quote
http://gammon.com.au/spi


Brilliant, cheers. So, reading the text under heading "sending & receiving data", because the appropriate data is sent back is sent back at the same time as the data going out, let's check I understand this right.

SPI.transfer (4) would send the value of 4, of course - and writing an a = SPI.transfer(4) would capture the data returned as a result of sending a value of 4 out over SPI?

Code: [Select]
a = SPI.transfer (4);
// a is now 1

b = SPI.transfer (3);
// b is now 2


If I send my data as two binary bytes, as below for example, the data I then capture back using the above method, does that come back and save as a binary byte? I've added two entries in to my code to declare bytes to save the contents of the registers.

Code: [Select]

byte ident_reg_contents = B00000000;
byte diag_reg_contents = B00000000;

SPI.transfer(B01111000);
diag_reg_contents = SPI.transfer(B00000000);


Quote
If it doesn't,  give up


That somewhat defeats the point of learning to interface with the SPI bus....

Nick Gammon


SPI.transfer (4) would send the value of 4, of course - and writing an a = SPI.transfer(4) would capture the data returned as a result of sending a value of 4 out over SPI?


No, as my page tries to explain.

As each bit is sent and received simultaneously it isn't possible for a single transfer to send data and receive a response (to that same data).

Quote
... because the appropriate data is sent back is sent back at the same time as the data going out, let's check I understand this right.


It is possible to receive valid data as you send stuff, but it won't be in direct response to the byte being sent.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

jtw11

#11
Jan 25, 2013, 11:38 pm Last Edit: Jan 25, 2013, 11:40 pm by jtw11 Reason: 1
Quote
As each bit is sent and received simultaneously it isn't possible for a single transfer to send data and receive a response (to that same data).


Ah, okay. Maybe i've misunderstood the following from your web page, perhaps you could steer me on the correct track?

Quote
Basically, while the master hardware is clocking out bits on the MOSI line (master out, slave in) it is also clocking in bits on the MISO (master in, slave out). Effectively, during one character time, it both sends and receives one byte. Hence the name of the function SPI.transfer.


Code: [Select]
char a, b;

a = SPI.transfer (4);

// a is now 1

b = SPI.transfer (3);

// b is now 2


...as I have replicated this in my code, for example - to read the contents of the identification register, IDENT_REG, at address B01001000 - I have done as you have, declared storage for the received data, I have then sent out the address B01001000, then sent a second transfer B00000000. The second transfer being the dummy bits required to retrieve the contents of the register.

Code: [Select]
byte ident_reg_contents = B00000000;

SPI.transfer(B01001000);
ident_reg_contents = SPI.transfer(B00000000);


Certainly that's how this page is implying to do so - http://www.breitband-lambda.de/pages/lambda---english/controlling-the-cj125.php?lang=EN

The 'Read Access' bit of the datasheet shows that too, send the address - then send 8 dummy bits, and the return of each dummy bit is the corresponding register entry, MSB first.

Perhaps i'm missing something fundamental? Do you mean my methodology is wrong, or my syntax to save the returned data is wrong? If it's of any help, I have no compiler errors at all.

Many thanks so far!

Nick Gammon

Code: [Select]

SPI.transfer(B01001000);


How about:

Code: [Select]

SPI.transfer(0x48);


That's easier to read, and matches the spec.

Their page seems to suggest the data is in 16-bit lots:



So without the device to hand it is hard to be sure. You could try the 16-bit approach:

Code: [Select]

SPI.transfer(0);  // MS byte
SPI.transfer(0x48);  // LS byte

byte result1 = SPI.transfer(0);
byte result2 = SPI.transfer(0);


And then try printing those.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

jtw11

I went over to binary to make dealing with setting individual bits on or off, as I can simply line them up with their graphical display in the datasheet. On that note, may one mix hex & binary in the same code?

Quote
Their page seems to suggest the data is in 16-bit lots


Yes, page 5 specifies a 16-bit data frame.

However, sorry - I'm not with you on your 16 bit approach example?

Nick Gammon

Each transfer sends 8 bits, so 2 x transfer does 16 bits.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up