SPI and atmega168

This post gives a little background so the scope pictures make sense. Overall, I’m having problems reading from the SPI interface. What causes the clock line to go active on the atmega168?

Here’s the details:

I’m trying to get SPI working with atmega168 talking to a Nordic semiconductor RF chip (on a board from sparkfun).
I’m trying to write to the CONFIG register on the NRF, and then read it. According to the Nordic spec, To write to a register, I need to write the address of the register Or-ed with bit 5 high. Then I need to write the value to write to the register. EX:
spi_write( addr | 1<<5);
spi_write ( reg_value);

To read any register, you just send the register address to the NRF chip:
spi_write( addr );

reg_val = spi_read();

Simultaneous to any outgoing command, the NRF returns the 8-bit status register. This is followed by any further requested data. (The spi_write/read() functions pull the SlaveSelect line low and do minor other stuff to manage the transaction.)

If I understand all of this correctly, I still can’t figure out how to get the data requested by the read command. In my scope pics, I’m trying to write to the CONFIG register at 0x0, and then I’m trying to read the value I’ve written. However, I can’t get the data back.

Top line is SlaveSelect, then clock, then MOSI, then MISO. I tried reading the SPDR register to get the data (first the status register value, then the requested data) to no avail.

Any ideas what I’m doing wrong? In particular, I can’t see how to get the atmega168 to drive the clock line to trigger the nrf chip to send data on the MISO line. (See Read_Write.png)

Should I expect the SCK line to go active whenever I read the atmel168 SPDR?

I couldn’t upload the pictures, so here they are on my flickr page:


Every SPI transaction results in dataflow in both directions. As you shift bits to the slave using MOSI, the slave is shifting bits to you using MISO. These bits are shifted at the rate of one bit per SCK cycle. The SCK is only active while the master is transmitting (i.e. when you set SPDR). If you want to read data from the slave, you accomplish this by:

  1. making sure the slave has had time to load its SPDR
  2. transmitting something to the slave

As you transmit your junk byte, the slave’s data is being transmitted to you and will be located in SPDR once the transmission is done.

Our Orangutan X2 robot controller functions by using high speed SPI communication between the user mega644 microcontroller and an auxiliary mega168 microcontroller with preloaded firmware. Please take a look at section 2 of the X2 command documentation for a more detailed account of how you can use SPI to transmit and receive data. Note that the sample code is for the mega644, but it is very similar to what you would use on the mega168 (maybe even the same?).

If this doesn’t answer your questions or solve your problems, please let me know.

- Ben

Edit: By the way, it’s very cool that you included oscilloscope captures! It makes it so much easier to see what’s going on. As far as I can tell, your captures look like what I would expect for SPI communication.


First off, I commend Pololu for having great documentation for the Orangutan. Makes me wish I’d bought one of them… next time! Second, these forums have really high-quality answers on them. I appreciate the hard work.

I will try out your solution when I get back from work tonight. It makes sense because the Nordic Chip has a NOP command that had puzzled me till now. Thanks for your help.


That seems to have been the trick. I now send the NOP and read the register just fine.


Great, I’m glad to hear you have everything working! Good luck with the rest of your project.

- Ben

I wish I had seen this Atmel application note (AVR151) at the time of this problem:
atmel.com/dyn/resources/prod … oc2585.pdf