The purpose in this post is to describe how to build a Master Device with the same configuration than the one we setup on the receiver side and described in the previous post. So, let’s continue this Serie!

Facing the problem

As I did before, I’m going to use the code used in the AVR Reference Manual for inizialize and perform a transmission in SPI. The original code looks like this:

void SPI_MasterInit(void)
{
   /* Set MOSI and SCK output, all others input */
   DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
   /* Enable SPI, Master, set clock rate fck/16 */
   SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(char cData)
{
   /* Start transmission */
   SPDR = cData;
   /* Wait for transmission complete */
   while(!(SPSR & (1<<SPIF)))
;
}

If you try to use this code in your program you will see that doesn’t looks to run, because the progrom doesn’t recognizes neither DDR_SPI, DD_MOSI nor DD_SCK. Reading the manual page 168 you will find a important point:

DDR_SPI in the examples must be replaced by the actual Data Direction Register controlling the SPI pins. DD_MOSI, DD_MISO and DD_SCK must be replaced by the actual data direction bits for these pins. E.g. if MOSI is placed on pin PB5, replace DD_MOSI with DDB5 and DDR_SPI with DDRB.

That’s very important!! Even trying to use SCK and MOSI instead of DD_SCK and DD_MOSI it’s a problem using Arduino IDE. If you try, your program will be compiled and loaded into your board. But you cannot be succesfull with the comunication. Why? The answer is inside the pin definition used by Arduino. In pins_arduino.h file you can find something similar to this:

static const uint8_t SS   = 10;
static const uint8_t MOSI = 11;
static const uint8_t MISO = 12;
static const uint8_t SCK  = 13;

We cannot configure the Arduino in that way, due that pin definition.

The working code

To solve the problem there are many sollutions. The one I found more usefull is using the Atmel’s advice. That is, use the labels DD_SCK, DD_SS and DD_MOSI with a right pin definition.

/*
 *******************************************************
 *  Name:            SPI Master Test    
 *
 *  Author:        Joan Martínez
 *
 *  Start Date:         19 jul 2012        
 *
 *  Version Date:       1 ago 2012
 *
 *  Description:    Use of SPI Mode in ATmega as master
 *                      SCK: PB5(D13), MISO: PB4(D12),
 *                      MOSI: PB3(D11), SS: PB2(D10).
 *  Platform:           Arduino UNO, 2009,...
 *
 *******************************************************/

#define DD_SS (1<<DDB2)
#define DD_SCK (1<<DDB5)
#define DD_MOSI (1<<DDB3)
#define DD_MISO (1<<DDB4)

byte bData;

void setup(){
  Serial.begin(9600);
  SPI_MasterInit();
  Serial.println("Master Ready!!"); 
}

void loop(){
  if(Serial.available()){
   Serial.print('.'); 
   bData=Serial.read(); 
   Serial.print('.');

   //Drive the SS low.
   PORTB &= ~DD_SS;
   Serial.print("[0x");

   SPI_MasterTransmit(bData); 
   Serial.print(bData,HEX);
   //Drive the SS high
   PORTB |= DD_SS;
   Serial.println(']');
  }
}

void SPI_MasterInit(void){
  /* Set SCK, MOSI & SS as outputs, left unchanged others
     (MISO is set as input as default of SPI master mode) */
  DDRB = DD_MOSI | DD_SCK | DD_SS;
  PORTB |= ((1<<DD_SS)|(1<<DD_MOSI) | (1<<DD_SCK));

  /* Set mode 2, Enable SPI, set clock, master mode and bit order */
  SPSR &= ~(1<<SPI2X);
  SPCR &= ~((1<<SPIE) | (1<<CPHA) | (1<<DORD)) ;  
  SPCR |=  (1<<SPE) | (1<<MSTR) | (1<<CPOL) | (1<<SPR1) | (1<<SPR0);
}

byte SPI_MasterTransmit(byte cData){
  SPDR=cData;
  while(!(SPSR & (1<<SPIF)))
  ;
  return SPDR;
}

Of course, the code has been completed with a serial data monitoring.

Doing:

#define DD_SCK (1<<DDB5)

I’m creating a mask that notes the SCK pin overriden in PORTB. The same is done for the rest of SPI lines.

The scattered Serial.print() instructions inside the void loop() has been a good helping tool to find where bugs were. So I keep it this way, even if they look uggly inside the code.

Connecting Master and Slave

To check that everything is running let’s connect both, the Master and the slave Arduino, as is shown in the image

Black wire: GND
White wire: SCK
Yellow wire: MOSI
Blue wire: SS

Using any serial monitor is possible to send data from both sides. Master echoes data in HEX mode. Also slave shows SPI received data as HEX.

Anuncios