Simple SPI driver

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Simple SPI driver

17,808 Views
admin
Specialist II
Anyone have a simple SPI driver written in C for an HC08?
 
Thanks,
Tomahawk
Labels (1)
0 Kudos
8 Replies

586 Views
bigmac
Specialist III

Hello Tomahawk,

As SPI master or slave?  The solutions would be quite different - master is simpler.

Regards,
Mac

 

0 Kudos

586 Views
admin
Specialist II
Master - and I'm only talking to one slave.  I'm experienced with I2C, but new to SPI.  Some examples would be helpful, too.  I have some basic questions, too, for example:
 
1) when you're addressing the slave is the R/W bit the MSB or the LSB?  None of the app notes/literature says - they all assume I already know.
 
2) when I want to read from the slave, I first send it the address in the device from which I want to read.  OK, fine.  Now, in order to actually get the data from the device, do I need to send out some dummy data in order to clock the data in from the device?
 
btw, I'm using the MC68HC908QB4.
 
thanks,
Tomahawk

Message Edited by Tomahawk on 2006-07-25 09:54 AM

0 Kudos

586 Views
bigmac
Specialist III

Hello Tomahawk,

Firstly, there seems to be a little confusion with the SPI operation.

  1. With SPI there is no "address".  You directly enable a slave device by activating its /SS (slave select) line.  In many cases, this will be a GPIO line at the master.  For the master, data is simultaneously sent from the MOSI line and received via the MISO line - there is no "RW bit" like in I2C.
  2. For the master to receive data from a SPI slave, you would send a dummy byte to initiate the transfer of data from the slave.  The returned byte value would need to be within the slave send buffer prior to the dummy byte being sent, so it is not possible for data to be returned in response to a command, within a single byte transaction.

I am not sure what your slave device is, but as an example, assume you wish to read data from a SPI compatible EEPROM.  The following steps would typically be involved.

Send READ command - ignore return
Send first address byte - ignore return
Send second address byte - ignore return
Send dummy byte - first data byte returned
Send dummy byte - second data byte returned
etc.

When initialising the SPI module as a master you will need to match the CPOL and CPHA parameters to the requirements of the slave device.  Whether or not you need to de-activate and then re-activate the /SS signal after each byte will also depend on the slave requirements.  Provided a relatively fast SPI clock rate is selected, it is usually not necessary to use SPI interrupts for a master.  This is not the case for the MCU operating as a slave.

For each master SPI transaction, you need to write a byte to SPDR, and a short while later you will have received a returned byte from the SPI slave. So the SPI function might be similar to the following code, but does not include control of the /SS line, that may need to be added.

byte SPI_proc (byte data)
{
   while (!SPSCR_SPTE);  /* Wait for Tx buffer empty */
   SPDR = data;          /* Send byte */
   while (!SPSCR_SPRF);  /* Wait for Rx buffer full */
   return (SPDR);        /* Received byte value */
}

For the EEPROM example given above -

SPI_proc (READ_CMD);
SPI_proc (address1);
SPI_proc (address2);
value1 = SPI_proc (0);
value2 = SPI_proc (0);

Regards,
Mac

 

0 Kudos

586 Views
admin
Specialist II
Sorry about the confusion.  When I was speaking of addresses, I was talking about the internal registers of my slave part.  I have to send it a register address byte, then a command to that register, then the slave will send a response byte.
 
After looking at your code, and looking at what I wrote based off of sec. 15.3.4 "Queuing Transmission Data" from my micro's data sheet (attached), I may have "over-engineered" my code in order to follow the diagram in 15.3.4.  I now realize that the diagram is constructed for maximum efficency with continuous communication.
 
Thanks,
Tomahawk
 
Message Edited by t.dowe on 2009-09-16 10:26 AM
0 Kudos

586 Views
bigmac
Specialist III

Hello Tomahawk,

I could be more specific if I knew what slave device you are using.

I can only repeat that I have never found it necessary to use interrupts for master operation.  Typically, I would use SPI when I require serial EEPROM, but more often I use SPI for communicating with shift register chains, both parallel input and parallel output, for the purpose of I/O expansion.

Since I have been able to use a fast SPI clock rate, that each data transaction takes a few microseconds to complete has not been an issue for me.

Regards,
Mac

 

0 Kudos

586 Views
admin
Specialist II
Here's my slave part.  I implemented your code, and my functions are much cleaner now.  I think the possible performance hit will be negligible compared to the example in the master data sheet.
 
Thanks,
Tomahawk
 
Message Edited by t.dowe on 2009-10-27 12:33 PM
0 Kudos

586 Views
bigmac
Specialist III

Hello Tomahawk,

For the accelerometer device, I guess you are already aware of the settings CPHA = 1, CPOL =1 as the requirement.  The data sheet is rather confusing when it identifies the bit associated with the first clock pulse as "bit 0".  SPI is normally MS bit first, and this matches the data sent to and received from SPDR.  For the first send byte, the R/W bit is therefore the MS bit of the address byte.

For the read/write protocol, the following sequence would apply -

Enable /CS
Send address byte, ignore return byte
Send input data, return byte is the output data
Disable /CS

I would also suggest fitting an external pull-up resistor for MISO line, say 10k, since it appears that SPDO pin of the device is high-Z for some of the time.

Regards,
Mac

 

0 Kudos

586 Views
admin
Specialist II
Thanks for the help, mac.
0 Kudos