Help a newbie -> SPI

Go To Last Post
12 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I'm using an atmel128L and I tried to use the SPI bus. I made a stupid software just to see if it seems to work :

#include

void SPI_masterinit(void)
{

DDRB=0x07; //MOSI SCK /SS are output
PORTB=0xFB;
SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0);
SPSR=(1<<SPI2X);
}

void main(void)
{
SPI_masterinit();

PORTB=0xFC; // put /cs at 0
SPDR=0x21; //juste try to put this value
while(!(SPSR & (1<<SPIF)));
PORTB=0xFB; // put /cs at 1
}

I used the avrstudio 4.06 debugger to see if the registers have the values expected and if fact :
- SPCR has the good value (0x51) so this one is ok
BUT SPDR never has the value asked (0x21). He's always at 0x00.why? why? why?

Why one of the SPI registers works and not the other. I tried also to put to 1 the bit SPI2X in the SPSR register and it doesn't work.

Please help a poor trainee who doesn't know what to do!!! :-(

admin's test signature
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

An SPI transfer is bidirectional, so each time you transfer a byte, you also receives one. When you read the SPDR register you read the received byte, which in this case would be 0x00 as you don't have an SPI slave to provice useful data (if I have understood correctly).

-Geir

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In fact I have a slave (eeprom 25LC320).

But for now I don't think it's the problem because when I use a scope on the MOSI I see anything. I see that /CS go to 0 (so it's seems ok) but I don't have any clock and any bit pattern on the MOSI.

admin's test signature
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Arnuad,

don't mix up 2 issues. At first you asked for simulation and it seems there is no possibility to simulate SPI in AVRstudio (I didn't use the tool so I can't verify it).

At second you switch to the real hardware. There you didn't get data on MOSI.

Do you set the M103 compatibility flag correctly?

In this line
PORTB=0xFC; // put /cs at 0
you change 2 bits in PORTB. Is it what you want? Better use something like this:
PORTB &= ~_BV(0); // put /cs at 0

(newest avr-gcc assumed)

Volkmar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

>Please help a poor trainee who doesn't know what to do!
Add another little subroutine to send , say, capital U or 0x55 in a loop over and over... then you'll be able to see the 8 clk pulses and the 01010101 in the Us on the scope.

admin's test signature
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had verify that the compatibility mod was not checked (I did this error for I2C bus ;-) )

For the PORTB I go from 0xFB to 0xFC so I change only one bit so I think it should work...
I'm using codevision as compiler so I don't think I have the function you mentionned Volkmar.

For the clock I will try but I don't understand why it will resolve my problem :-(

admin's test signature
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, but:
0xFB = 11111011
0xFC = 11111100

You change 3 bits, and all are defined as outputs in DDRB. Even that enabling SPI the bit for MOSI isn't using the value of PORTB.

I don't know if this resolves your problem. Maybe I will look tonight in my simulation environment for this issue. I never used SPI until now, but I want to do it in the near future.

Volkmar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shame on me, you are right Volkmar the values were not good... but it still doesn't work! :-(

I don't understand something : in the lastest datasheet of the mega128L, on page 163, there's an exemple of initialization and transmission of a single data :
- For the SPI_masterinit() I don't understand why they don't put the /SS as a output
-For the SPI_mastertransmit() they never handle the /SS line, why??? in the page juste before they said "When configured as a Master, the SPI interface has no automatic control of the SS line. This must be handled by user software before communication can start." So normally we need to do this, no?

I think this problem with /SS must explain why it doen't work. But someone knows exactely what I need to do to transmit something? Any example?

admin's test signature
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Arnoud,

I tried to simulate it in VMLAB and you can see the output in the attached picture.

Maybe you can't see anything in the hardware because you only sending the data once. Implement a loop without looking at the received data and then measure on the pins.

I assume they didn't set /SS because their might be devices or constallations where it isn't necessary to use this output for SPI. I don't think that it doesn't habe anything to do with your problem. Because it has no effect on sending via SPI master.

Volkmar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Volkmar you are my savior!!!
You save me for the i2c and now for the SPI... Thank You :-D
I think I will have to buy you some chocolates ;-)

Seriously, about the atmel : I modified a little bit my soft and put as you said a loop.

#include

void SPI_masterinit(void)
{
DDRB=0x07; //MOSI SCK /SS are output
PORTB=0x01;
SPCR=(1>8;
low_byte=ADDRESS & 0x00FF;

//allow to write en the EEPROM
SPI_msend(0x06);

//Now we can write
SPI_msend(0x02);
SPI_msend(hi_byte);
SPI_msend(low_byte);
SPI_msend(DATA);

}

void main(void)
{
int i;

SPI_masterinit();
PORTB=0x00;

for (i=0;i<50;i++) {

//SPI_msend(0x11);
eeprom_write(0x0000, 0x11);

}
PORTB=0x01;

}

So as I said now it works BUT...
I don't understand why if I ask to make the loop 20000 for exemple it's always work and I can alayws see the bit pattern on the scope and if I put just 50 or less, sometimes I see the bit pattern on the scope and sometimes not!

Is it just a problem of "visualisation" (and in fact it always sends the bit pattern) or need I really to send many times to be sure that my eeprom would be written?

admin's test signature
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think it is a problem of visualisation. Because if you start the mcu it runs through your code until 'PORTB = 0x01'. But I don't know what code codevision creates at this point. AVRGCC creates an endless loop, so the mcu will run into a defined dead end. Maybe codevision didn't create such an endless loop, the mcu tries to interprete the maybe non programmed area of the flash. And it seems that it steps over this (I have seen similiar at my desk in another project) until it starts again.

better build an endless program. Because it is another situation as on a PC where there is an OS which might waiting for the end of such a program.

Volkmar

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Arnaud,
Two things to be aware of:
1) /SS is only used in slave mode BUT if you are in master mode AND /SS is an input AND /SS is driven low by other hardware then the SPI port will be disabled (it assumes another master is accessing the SPI bus). In other words, make sure /SS is an output and drive it high.

2) In CodeVision you can access individual port bits using the dot notation:
PORTA.0=1
will set bit0 of PORTA high. This is convenient for setting individual bits.

As for data visualisation, if you have a storage scope try single shot triggering on the /CS line of the EEPROM and you should catch the first write. You should also make sure that the code waits at the end of the program in a loop.
baremetal

admin's test signature