[C] Simple SPI "library"

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

  After a while spent trying to find out about the SPI capability of AVRs, I decided the best way to learn was to create my own library (an approach I have found works very well for beginners). I found an excellent example at https://sites.google.com/site/qe... and quickly turned it into a header file for easy reuse, adding a little more functionality for my own purposes. Since I am new to coding in raw C (I have escaped from the clutches of the Arduino IDE!), I thought it would be a good idea to see what the community here thinks of it, and if they have any advice to improve it. I also don't have the means to test it at the moment (that I am aware of), so I would appreciate it if anyone could try it out, following a successful build in ATMEL Studio 6. SPI.h is as follows:

/*
 * SPI.c
 *
 * Created: 20/12/2014 14:40:18
 *  Author: Benedict
 */ 
#ifndef SPI
#define SPI
#include <avr/io.h>

#ifndef csPORT
# warning "Define csPORT (default PORTB)"
#define csPort PORTB
#endif

#ifndef cs1 
# warning "Define cs1 if needed"
#define cs1 0
#endif

#ifndef cs2
# warning "Define cs2 if needed"
#define cs2 0
#endif

#ifndef cs3
# warning "Define cs3 if needed"
#define cs3 0
#endif

char dataIn;

void spiInitMaster(void){

	DDRB |= (1<<2)|(1<<3)|(1<<5);    // SCK, MOSI and SS as outputs
	DDRB &= ~(1<<4);                 // MISO as input
	csPort |= (1<<cs1) | (1<<cs2) | (1<<cs3);//Set slaves high
	
	SPCR |= (1<<MSTR);               // Set as Master
	SPCR |= (1<<SPR0)|(1<<SPR1);     // divided clock by 128
	SPCR |= (1<<SPE);                // Enable SPI
}

void spiInitSlave(void){

	DDRB &= ~((1<<2)|(1<<3)|(1<<5));   // SCK, MOSI and SS as inputs
	DDRB |= (1<<4);                    // MISO as output

	SPCR &= ~(1<<MSTR);                // Set as slave
	SPCR |= (1<<SPR0)|(1<<SPR1);       // divide clock by 128
	SPCR |= (1<<SPE);
}

int spiReceive(void){//Call in while(1)
	while(!(SPSR & (1<<SPIF)));    // wait until all data is received
	dataIn = SPDR;
	return dataIn;
}

void spiTransmit(char dataOut, int slavePin){//Call in while(1)
	csPort &= ~ 1<<slavePin;
	SPDR = dataOut;                 // send the data
	while(!(SPSR & (1<<SPIF)));
}
#endif

Thank you to anyone who takes the time to read this!

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

First its a fine beginning but not a complete library of code.

There is no selection of clock speed,

only one out of four possible spi modes,

the read/write functions are incomplete, ie. a slave read, but no slave write, visa versa, a master write, but no master read.

Only polling mode, no interrupt operation. 

 

I would say keep working on it and post your results in the mega forum, as this does not seem to be a tutorial.

Ask questions if you get stuck.

 

JC

 

 

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

Quite honestly,   SPI initialisation is only PORTB, DDRB, SPCR, SPSR.    i.e. four simple assignments.

The SPI invocation is a single uint8_t spi_xfer(uint8_t c) function.  i.e. another three lines.

 

The pin usage varies with AVR model .  So it is difficult to make anything universal.

 

Just stick to simple code with a comment (when necessary)

 

David.