SPI between Atmega and Arduino DUE

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

Hello ,

 

I am trying to estalish SPI between ATMEGA256RFR2(master) and ARDUINO DUE(slave). I guess I did not understand the clock settings of the AVR proprerly. My understanding about clock is:

a. The FUSE CKDIV8 - when programmed divides the clock by 8 (If I connect it to 16mhz external one it makes it 2)

b. The LOW.CKSEL_SUT can choose between different clock sources. I chose Internal RC oscillator ,which is 16mhz as per datasheet .

Until I have read , these are the two points through which the sstem clock can be set/changed.

c.The clock rate of the SPI register is programmed with SPCR register SPR0 and SPR1 pins.

Questions :

 

1. The CKDIV8 is programmed. So, now , the general clock is at 2 mhz .  Am I right ? But to the SPI the clock signal  is 2mhz / 4 ? Is it so ?

 

2. I know the F_CPU is just a software reference for delay and it is not changing the hardware clock.

 

Status:

For now ,I have configured ATMEGA as master , DUE as slave. I sent a value and the DUE receives it , but with a very huge delay.

1. I defined clock with the given above settings and included #define F_CPU 2000000UL this in my code . I obviosly get delay.

2. I chose the Internal clock ; I unprogrammed the CKDIV8 assuming that 16 mhz is the clock frequency of the ATMEGA. SPCR is same 00 , expected that SPI would receive 4 mhz. But still the data receiving on the DUE receives with huge delay. #define F_CPU 16000000UL was included in the code

 

How can I make the hardware ATMEGA to run at 4mhz and be in sync? I want 4mhz because the DUE default is 4 mhz,as stated here :  https://www.arduino.cc/en/Refere.... I would also like to establish duplex communicaton but my "unclear knowledge" of clock seems to be a barrier .  Can somebody put me on the right track?

 

Last Edited: Mon. Mar 5, 2018 - 03:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pika wrote:
But to the SPI the clock signal is 2mhz / 4 ? Is it so ?
That depends what you set the SPR0 and SPR1 bits to and also how you have SPI2X set. If the two SPR bits are 0 then if SPI2X=0 then the SPI clock will be 2MHz / 4 = 512kHz while if SPI2X is one then it will be 2MHz / 2 = 1MHz.
pika wrote:
How can I make the hardware ATMEGA to run at 4mhz and be in sync?
As long as you stick with CKDIV8 you can't. The fastest SPR bits choose either /2 or /4 so to get 4MHz you would need the CPU to run at either 8MHz or 16MHz.

 

As the core clock source is 16MHz the "obvious" choice would seem to be to deactivate CKDIV8 so no F_CPU=16MHz then set SPR bits to both 0. Then set SPI2X=0. Now you will get an SPI clock of 16MHz / 4 = 4MHz.

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

SPI is synchronous, there is a clock line. So how can there be a "huge delay"? The data is received the moment it is sent.

The delay you see must have some other origin. How big is this delay?

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

clawson wrote:

 As long as you stick with CKDIV8 you can't. The fastest SPR bits choose either /2 or /4 so to get 4MHz you would need the CPU to run at either 8MHz or 16MHz.

As the core clock source is 16MHz the "obvious" choice would seem to be to deactivate CKDIV8 so no F_CPU=16MHz then set SPR bits to both 0. Then set SPI2X=0. Now you will get an SPI clock of 16MHz / 4 = 4MHz.

 

I never noticed the SPI2X , sure I will try with it. Is it necessary to specify the clock in the slave,in this case ARDUINO DUE for the SPI communication ?

Last Edited: Mon. Mar 5, 2018 - 03:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pika wrote:
Is it necessary to specify the clock in the slave,in this case ARDUINO DUE for the SPI communication ?
Nope, as El Tangas just said the whole point of SPI is that it is synchronous serial - it brings it's own clock along with it - everything is driven by the master.

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

El Tangas wrote:
SPI is synchronous, there is a clock line. So how can there be a "huge delay"?

indeed

 

The data is received the moment it is sent.

But it's also serial - so the data isn't received until the full word size has been sent

 

The delay you see must have some other origin.

indeed.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, that is why I am confused. With CKDIV disabled , internal RC enabled, #define F_CPU 16000000UL this line in the program code , the delay is about 3-4 mins.  should the slave also be assigned with the clock ? 

 

The output is :

receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80

 all the values are printed all at once; my expected value is 80.

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

pika wrote:
Is it necessary to specify the clock in the slave

That depends which "clock" you're talking about.

 

AS the others have said the SCK signal is generated by the Master - so there is nothing to configure in the slave for that.

 

However, they may well be peripheral clocks within the SAM3 that need to be configured for that peripheral to work.

But, if you're using the Arduino framework, that should take care of it for you ...

 

awneil wrote:
the data isn't received until the full word size has been sent

A thought: you have got the Slave set to the same word size as the master - haven't you ... ?

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually , SPI2X is in SPSR register and I never assigned any value to that register. So ,it is already 4 mhz, I guess.

 

My code: incase

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "spi_master.h"

void spi_select()
{
	PORTB &= ~ (1<< PORTB0);
	
}

void spi_deselect()
{
	PORTB |= (1<< PORTB0);
 
}
void spi_master_int (void)
{
	
	DDRB = 0x07 ;  //PB2=MOSI ,PB1=SCK as output ,PB0 =SS as output
	SPCR =  (1<<SPE) | (1<<MSTR) | (1<<CPHA) ; //spi enabled master mode, spi_mode 1,prescalar :fosc/4
       
 }

int main(void)
{
    spi_master_int();
	
	  	
	while (1)
	{	
		spi_select(); // from here i commented
		spi_send(0x80);
		spi_deselect();
		
	 };
	   
	
}


spi master. h

#ifndef SPI_MASTER_H_
#define SPI_MASTER_H_

uint8_t spi_send (uint8_t r_data)
{
	
	SPDR = r_data;
  	while(!(SPSR & (1<<SPIF) ))
	{};
	return (SPDR);
}


#endif /* SPI_MASTER_H_ */

 

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

awneil wrote:

 

However, they may well be peripheral clocks within the SAM3 that need to be configured for that peripheral to work.

But, if you're using the Arduino framework, that should take care of it for you ...

 

awneil wrote:
the data isn't received until the full word size has been sent

A thought: you have got the Slave set to the same word size as the master - haven't you ... ?

 

 

 

I guess its taken care with Arduino , I did not set any word size ! Maybe I should I look into Arduino

 

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

pika wrote:
the delay is about 3-4 mins.
WHAT??? SPI is a synchronous exchange. The receiver has the sender's data as soon as the 8th(*) clock pulse has occurred. If you are running at 4MHz and you initiate a transfer then the receiver should have the data 8/4000000 s later. That is 2 MICROSECONDS later. Where on earth does this "3-4 minutes" come into things?

 

(*) I  am assuming SPI is configured for 8 bit transfers here - some devices (like 8bit AVR tiny/mega) don't allow this to be varied but some "power micros" might allow the bit width to be varied though it is VERY likely they default to 8 bit transfers

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

pika wrote:

Yes, that is why I am confused. With CKDIV disabled , internal RC enabled, #define F_CPU 16000000UL this line in the program code , the delay is about 3-4 mins.  should the slave also be assigned with the clock ? 

 

The output is :

receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80
receiving 80

 all the values are printed all at once; my expected value is 80.

 

Do you see these values printed by Arduino on its UART after several minutes since SPI transfer has started? If so, then I'd check UART buffering.

 

 

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

Yabusame wrote:

 

 

Do you see these values printed by Arduino on its UART after several minutes since SPI transfer has started? If so, then I'd check UART buffering.

 

 

 

Yes,exactly and all these are printed all at once.

 

I really do nothing with UART configuration, and when I try the program with other DUE (both as master and slave) this isn't a problem.

void loop() {

  byte in;
  
  Serial.print("receiving ");
  in= SPI.transfer(0x00);
  Serial.println(in,HEX);
}

 

 

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

pika wrote:
The output is :

receiving 80

receiving 80

The "output" on what display device? Is this data actually going to a terminal on a PC? If so then it's probably the PC that is buffering.

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

Atmega is 8 bit and the DUE's sam is 32 bit , but its transfer size is 8 bit. And also in another forum i read DUE runs at 84 Mhz !

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

Ya, this is the Arduino terminal - Serial terminal of Arduino IDE on the PC. ATMEGA <-->DUE<--->PC(output screen)

Last Edited: Tue. Mar 6, 2018 - 09:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pika wrote:

Ya, this is the Arduino terminal - Serial terminal of Arduino IDE on the PC. ATMEGA <-->DUE<--->PC(output screen)

 

 Arduino framework may (or may not) have a kind of a SW buffer for UART transfer. Or it could be its IDE, as clawson suggested. It feels like buffered output. Try blinking a LED after each SPIF. Or collecting SPI data into an array and dumping it to EEPROM. Maybe add a timestamp to each received byte.

 I'd also send changing data, not just 0x80. A counter or something.

 


Qoitech AB, The Home of Otii Arc, an SMU for every developer

Check out Otii solution at www.qoitech.com