Oscillators/PCA/Timers/SMBus/UART/SPI
  f340 SPI Duplex mode

Post New Topic  Post A Reply
profile | register | preferences | faq | search

UBBFriend: Email This Page to Someone! next newest topic | next oldest topic
Author Topic:   f340 SPI Duplex mode
hafblud
Member
posted August 10, 2010 12:39 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
I am using f340 controller as a master of SPI to receive data from a sensor (ADIS16350). A 16 bit data is trasmitted and a 16 bit value has to be read in the next cycle. I am using the following code to transmit and receive simultaneously. But I cannot receive data correctly. Please rectify my routine.

[This message has been edited by hafblud (edited August 10, 2010).]

IP: Logged

hafblud
Member
posted August 10, 2010 12:42 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
while (1)
{

NSSMD0 = 0 ;
SPIF = 0 ;
ub = SPI0DAT;
SPI0DAT = 0x0A;
while(SPIF == 0);
SPIF = 0;
lb = SPI0DAT;
SPI0DAT = 0x0B;
while(SPIF == 0);

}

IP: Logged

hafblud
Member
posted August 10, 2010 12:47 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
for ADIS16350 :

__
CSS: |________________________________|

DIN: A1A2A3A4A5A6A7A8D1D2D3D4D5D6D7D8

DOUT: <-------------Prevoius Data ---->

IP: Logged

Scotty
Member
posted August 10, 2010 10:05 AM     Click Here to See the Profile for Scotty     Edit/Delete Message
Hi hafblud,

I am using f340 controller as a master of SPI to receive data from a sensor (ADIS16350).
Too few information. 3/4-Wire Mode? Post your complete code.
Link to ADIS16350 datasheet? (I found it already, but would be nice to post a link to a datasheet next time )

A 16 bit data is trasmitted and a 16 bit value has to be read in the next cycle. I am using the following code to transmit and receive simultaneously. But I cannot receive data correctly.
Fine... And what is not correctly read? Keep in mind, post as much information as possible. Saying it doesn't work is not as half as good compared to saying what you expect and what you get

From my understanding of the datasheet, your read sequence is faulty. Go through yourself step-by-step:
- initially the readed data(UpperByte) will be undefined (okay)
- you send a command (okay)
- you read incoming data (LowerByte) -> hmm...
- you send the second byte (okay)
*** first sequence finished ***
- you read the UpperByte -> WRONG
- ...

This cannot work, because the ADIS16350 gives the first part of the answer of the previous command when the master transmits the third byte(or multiples of the third byte) and the second part on the fourth byte.
So, I think you must simply swap reading/writing of SPI0DAT in your code, and ignore the answer of the chip on the first call of your function.

Regards,

Scotty

IP: Logged

hafblud
Member
posted August 10, 2010 12:47 PM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
Sorry for mentioning so little. I have changed the code and my new code is as follow.

Also I am using 4-wire master mode, 1Mbps SCLK. I am now using SPI ISR to collect data as follow.

IP: Logged

hafblud
Member
posted August 10, 2010 12:52 PM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
while(1)
{
NSSMD0 = 0;
SPI0DAT = 0x02;
while(!txOk);
txOk = 0;

SPI0DAT = 0x00; // Don't Care
while(!txOk);
txOk = 0;
}

void SPI_ISR () interrupt 6
{
ch = SPI0DAT;
SPIF = 0;
txOk = 0;

tx_byte(ch);

}

IP: Logged

hafblud
Member
posted August 10, 2010 12:56 PM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
The above mentioned code should read the Supply Level of the Sensor. And it should give consistent result and correct as per conversion mentioned in the Data sheet. But I am receiving random values at the Master. This is also true for other values that I read from the sensor.
I varied the voltage applied to sensor and the data read also changed but that was random as well.

IP: Logged

erikm
Member
posted August 10, 2010 12:59 PM     Click Here to See the Profile for erikm   Click Here to Email erikm     Edit/Delete Message
'random'
Does the avarage readings (somewhat) vary in accordance to the input?.

Erik

IP: Logged

hafblud
Member
posted August 10, 2010 01:31 PM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
by random i mean out of range like :
00 01
CA 65
C0 08
00 08 etc.
These values vary in accordance to the input but still that change is random.

Is my routine ok or not (Theoretically). Am I missing some interrupt or anything imp ?

[This message has been edited by hafblud (edited August 10, 2010).]

IP: Logged

Scotty
Member
posted August 10, 2010 04:57 PM     Click Here to See the Profile for Scotty     Edit/Delete Message
Hi hafblud,

Also I am using 4-wire master mode, 1Mbps SCLK.
I didn't check the clock frequency capability of your chip, but if I remember the datasheet correctly the chip needs /SS to be low for 16 bits -> check it. Using four wire mode will release /SS after eight bits! Configure for three wire bus, skip the corresponding /SS pin on cross bar and set/release it with the appropriate timing manually for 16 bit access.

I have changed the code and my new code is as follow.
You call this complete code?
Sorry, but code means with comments so you and we can see what you think you're doing and what you're really doing

For example, txOK is what? A bit flag? A redefined SFR bit? A port bit?

Is my routine ok or not (Theoretically). Am I missing some interrupt or anything imp ?
Obviously it's not okay, otherwise you wouldn't ask for help =)
But from what I can see until now, I'd suggest you take a piece of paper, a pen and the datasheet of your chip and draw a program flow diagram. And I'm sure, on the paper you'll see and understand what to do.

If I had to communicate interrupt driven with such a chip, my flow would look like this:
1. prepare data
2. send data
3. prepare new data (or dummy bytes)
4. send new data (and receive the answer from the last command)

Steps 1/2 and 3/4 are the made of the same code. I'd use a function with two eight bit parameters -> Command and Data. The function will initiate a SPI transfer by setting the SPI interrupt flag.
The SPI interrupt will set a flag for indicating that a sequence is in progress. This flag is checked by the above mentioned function for data transfer and function has to wait for the flag until it is reset by the SPI ISR.
The SPI ISR takes the two bytes and send them, where also a flag is used to indicate if the upper or lower byte is transmitted.
After a byte has been sent, the SPI0DAT register is read and the value is written to one of two other bytes building the answer of the chip.
The function for initiating the transfer has also to read these two 'answer-bytes' and will return them.
You can make this procedure more easy to understand if you disclaim the two-byte-at-once approach and simply use a one-byte-approach, meaning you write to SPI0DAT, and the ISR sets a flag to indicate that a transmission is complete. The main application waits for the flag, clears it and saves the content of SPI0DAT to one of the answer bytes. Then the same procedure for the second byte. Keep in mind that you're using a chip with a 16-bit interface, so the two-byte-approach eases the handling of bit-banging for /SS.
NOTE: The above suggestion is plain out of my head, no paper or pen used

Regards,

Scotty

[This message has been edited by Scotty (edited August 10, 2010).]

IP: Logged

hafblud
Member
posted August 11, 2010 03:05 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
Thank you very much for suggestion. I will try to implement them as well.

As far as complete code is concerned , few weeks back you helped me correct the SPI usage. So I took it that my SPI initialization part is correct.

Also why 3-wire approach is better than 4-wire in this case : How will Interrupt generated in case of the 3-wire (& 16 bit data). I thought 8 bit completion will generate an interrupt.

IP: Logged

Scotty
Member
posted August 11, 2010 04:49 AM     Click Here to See the Profile for Scotty     Edit/Delete Message
Hi hafblud,

Also why 3-wire approach is better than 4-wire in this case : How will Interrupt generated in case of the 3-wire (& 16 bit data). I thought 8 bit completion will generate an interrupt.
Yes, interrupt is generated on each byte transfer, but as I said: your chip expects 16-bit transfers, thus you must not deactivate the /SS signal between two bytes - and this will happen automatically when using 4-wire mode. That's why I suggested to configure for 3-wire mode, skip the /SS pin on crossbar and modify the /SS pin manually via bit-banging.

Regards,

Scotty

IP: Logged

hafblud
Member
posted August 11, 2010 11:43 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
What is diff between Skipped pin & GPIO ?
.
.
Use of 3-wire and manual /SS also didn't work. It is still reading garbage as well as meaning full data.

IP: Logged

erikm
Member
posted August 11, 2010 11:48 AM     Click Here to See the Profile for erikm   Click Here to Email erikm     Edit/Delete Message
have you configured to SCLK starting high?

Erik

IP: Logged

Scotty
Member
posted August 11, 2010 12:19 PM     Click Here to See the Profile for Scotty     Edit/Delete Message
Hi hafblud,

What is diff between Skipped pin & GPIO ?
It depends on the enabled peripherals
If you've enabled peripherals which come behind SPI the peripheral(s) will take over the formerly hardware controlled /SS pin...

Use of 3-wire and manual /SS also didn't work. It is still reading garbage as well as meaning full data.
*sigh* Very useful information...

Erik made a also good hint, which he wouldn't have to do if... there were complete code...

Regards,

Scotty

IP: Logged

erikm
Member
posted August 11, 2010 01:15 PM     Click Here to See the Profile for erikm   Click Here to Email erikm     Edit/Delete Message
Erik made a also good hint, which he wouldn't have to do if... there were complete code...

I would still have made the hint, it gives the OP an opportunity to study the datasheet.

Erik

IP: Logged

hafblud
Member
posted August 12, 2010 05:11 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
#include "C8051F340.h"

sbit LED1 = P2^2; // Debug LEDs on The uC Board
sbit LED2 = P2^3;

sbit SCK = P0^0;
sbit MISO = P0^1;
sbit MOSI = P0^2;
sbit NSS = P0^3;

unsigned char cc;
unsigned int k = 0;

bit transmitted = 0 , ss = 0;

void main ()
{

init_s_io_t();

while(1)
{

NSS = 0; // SS Low

SPI0DAT = 0x02 ; // Hex Code for reading Supply of Sensor
while(!SPIF); // Wait untill byte is out of Shift Register
SPIF = 0; // Reset SPIF

SPI0DAT = 0x0F; // Second byte is Garbage
while(!SPIF);
SPIF = 0;

NSS = 1;

for(k=1;k<18;k++); // Wait for conversion of Data

NSS = 0;
SPI0DAT = 0x03 ;
while(!SPIF);
SPIF = 0;
cc = SPI0DAT; // Read High Byte

SPI0DAT = 0x0F;
while(!SPIF);
SPIF = 0;
cc = SPI0DAT; // Read Low Byte

NSS = 1;
for(k=1;k<14;k++);


}


}

void init_s_io_t ()
{

PCA0MD &= ~0x40;

P0MDOUT = 0x5D;
P2MDOUT = 0xFF;
P3MDOUT = 0x00;
P4MDOUT = 0xFF;
P0SKIP = 0x08;
P3 = 0x00;

XBR0 = 0x03; // Uart0 available at port Pins (bit 0)
XBR1 = 0x40; // Cross Bar enable (bit 6)
// Weak pull-ups enable (bit 7)
TMOD = 0x21; // Timer 0 set to mode 1
TCON = 0x01; // Interrupt 0 edge triggered
// TR0 = 0 (disable Timer 0)
// TR1 = 0 (disable Timer 1)
CKCON = 0x08; // System Clock / 12 (bit1 bit0 = 01)
// Timer 1 mode 1 (Use Sys Clk, ignore bit 1,0) (bit-3)
// Timer 0 mode 0 (Pre-Scaled Sys Clock) (bit-2)
TH1 = 0xCC; // Reload value for 9600 baud Rate (0x64)
// Reload value for 115K baud Rate (0xCC)


SCON0 = 0x10; // Uart Reception Enables (bit 4 = 1)
// 8-bit uart (bit 7)
// bit-6 for Read (1)
OSCICN = 0x83; // Internal HF Oscillator Enabled (bit7)
// SYS CLK is HF Oscillator div by 1 (bit1 bit0 = 11)
TR1 = 1; // Start Timer 1 (bit-7 of TCON)
TI0 = 1; // Set 1 for UART to Ready & cleared manually after Tx


SPI0CKR = 0x05; // I Mbps for SPI
SPI0CFG = 0x70; // Master Mode(bit6 = 1), CLKPH = 1 , CLKPOL = 1
SPI0CN = 0x01; // (bit 7 = SPI0 Interrup Flag), (bit6 =1 when Collision Occurs),
SPIF = 0;



}

IP: Logged

hafblud
Member
posted August 12, 2010 05:16 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
This is the complete code. I monitored all the signal at the sensor pins. They are as per requirement in the data sheet of sensor except the data out is not OK.

IP: Logged

erikm
Member
posted August 12, 2010 08:15 AM     Click Here to See the Profile for erikm   Click Here to Email erikm     Edit/Delete Message
except the data out is not OK.

which DOUT sensor or uC?

Erik

IP: Logged

hafblud
Member
posted August 12, 2010 09:41 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
I am using an oscilloscope to monitor din, dout, /ss & sck of the sensor. The sensor is not transmitting data as expected.
e.g. If 0x02 or 0x03 is transmitted to sensor it should return a 16 bit value which give supply of the sensor.

IP: Logged

Scotty
Member
posted August 13, 2010 12:42 AM     Click Here to See the Profile for Scotty     Edit/Delete Message
Hi hafblud,

If 0x02 or 0x03 is transmitted to sensor it should return a 16 bit value which give supply of the sensor.
- And what is returned?
- What about answers to other commands? Also garbage?
- What about reset? Do you reset the chip via port pin or at least software reset command?

Regards,

Scotty

[This message has been edited by Scotty (edited August 13, 2010).]

IP: Logged

hafblud
Member
posted August 13, 2010 12:45 AM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
Reading supply is just an example to explain my point. Its behavior was similar to all the commands (not sending valid data). I am working on a f340-DK, so i burn the code and reset it every time i have to use. If u are refering to sensor, no i am not resetting it (can it be a problem ?).

Anyway I got it right this time .

1) 3-wire master
2) manual /SS
3) 16 bit transmission
4) 1Mbps SCK
5) 25 us delay between commands

These settings are working perfectly. Thanyou very much for your guidance.

[This message has been edited by hafblud (edited August 13, 2010).]

IP: Logged

Scotty
Member
posted August 13, 2010 01:46 AM     Click Here to See the Profile for Scotty     Edit/Delete Message
Hi hafblud,

If u are refering to sensor, no i am not resetting it (can it be a problem ?).
Yes, I mean the sensor. If I have the possibility to reset, I'd do

Anyway I got it right this time .
...
5) 25 us delay between commands

These settings are working perfectly.
Hm, seems the delay was the crux. I couldn't locate the corresponding datasheet entry

Thanyou very much for your guidance.
You found the error yourself

Regards,

Scotty

IP: Logged

hafblud
Member
posted August 15, 2010 03:06 PM     Click Here to See the Profile for hafblud   Click Here to Email hafblud     Edit/Delete Message
that error was one thing but main problem was solved by you guys which was transmission of 16 bits in two cycles.
Thanks again

Regards
hafblud

IP: Logged

All times are CT (US)

next newest topic | next oldest topic

Administrative Options: Close Topic | Archive/Move | Delete Topic
Post New Topic  Post A Reply
Hop to:

Contact Us | MCU User Forum

Have you seen our MCU Knowledge Base?


Ultimate Bulletin Board 5.47b