| Xmega Application Note | |||||
XMEGA SPI driver header file. More...
#include "avr_compiler.h"

Go to the source code of this file.
Data Structures | |
| struct | SPI_DataPacket |
| SPI data packet struct. More... | |
| struct | SPI_Master |
| SPI master struct. Holds pointer to SPI module, buffers and necessary varibles. More... | |
| struct | SPI_Slave |
| SPI slave struct. Holds pointers to SPI module and used port. More... | |
Defines | |
| #define | SPI_BUSY 2 |
| The SPI module is busy with another transmission. | |
| #define | SPI_INTERRUPTED 1 |
| The transmission was interrupted by another master. | |
| #define | SPI_MasterInterruptTransmissionComplete(_spi) ( (_spi)->dataPacket->complete ) |
| Checks if transmission is complete. | |
| #define | SPI_MasterSSHigh(_port, _pinBM) ( (_port)->OUTSET = (_pinBM) ) |
| Releases SPI SS line(s). | |
| #define | SPI_MasterSSLow(_port, _pinBM) ( (_port)->OUTCLR = (_pinBM) ) |
| Pulls SPI SS line(s) low in order to address the slave devices. | |
| #define | SPI_MISO_bm 0x40 |
| Bit mask for the MISO pin. | |
| #define | SPI_MOSI_bm 0x20 |
| Bit mask for the MOSI pin. | |
| #define | SPI_OK 0 |
| The transmission completed successfully. | |
| #define | SPI_SCK_bm 0x80 |
| Bit mask for the SCK pin. | |
| #define | SPI_SlaveDataAvailable(_spi) ( (_spi)->module->STATUS & SPI_IF_bm ) |
| Check if new data is available. | |
| #define | SPI_SlaveReadByte(_spi) ( (_spi)->module->DATA ) |
| Read received data byte. | |
| #define | SPI_SlaveWriteByte(_spi, _data) ( (_spi)->module->DATA = (_data) ) |
| Write data byte to the SPI shift register. | |
| #define | SPI_SS_bm 0x10 |
| Bit mask for the SS pin. | |
Typedefs | |
| typedef struct SPI_DataPacket | SPI_DataPacket_t |
| SPI data packet struct. | |
| typedef struct SPI_Master | SPI_Master_t |
| SPI master struct. Holds pointer to SPI module, buffers and necessary varibles. | |
| typedef struct SPI_Slave | SPI_Slave_t |
| SPI slave struct. Holds pointers to SPI module and used port. | |
Functions | |
| void | SPI_MasterCreateDataPacket (SPI_DataPacket_t *dataPacket, const uint8_t *transmitData, uint8_t *receiveData, uint8_t bytesToTransceive, PORT_t *ssPort, uint8_t ssPinMask) |
| Create data packet. | |
| void | SPI_MasterInit (SPI_Master_t *spi, SPI_t *module, PORT_t *port, bool lsbFirst, SPI_MODE_t mode, SPI_INTLVL_t intLevel, bool clk2x, SPI_PRESCALER_t clockDivision) |
| Initialize SPI module as master. | |
| void | SPI_MasterInterruptHandler (SPI_Master_t *spi) |
| Common SPI master interrupt service routine. | |
| uint8_t | SPI_MasterInterruptTransceivePacket (SPI_Master_t *spi, SPI_DataPacket_t *dataPacket) |
| Start transmission. | |
| uint8_t | SPI_MasterTransceiveByte (SPI_Master_t *spi, uint8_t TXdata) |
| SPI mastertransceive byte. | |
| bool | SPI_MasterTransceivePacket (SPI_Master_t *spi, SPI_DataPacket_t *dataPacket) |
| SPI transceive data packet. | |
| void | SPI_SlaveInit (SPI_Slave_t *spi, SPI_t *module, PORT_t *port, bool lsbFirst, SPI_MODE_t mode, SPI_INTLVL_t intLevel) |
| Initialize SPI module as slave. | |
XMEGA SPI driver header file.
This file contains the function prototypes and enumerator definitions for various configuration parameters for the XMEGA SPI driver.
The driver is not intended for size and/or speed critical code, since most functions are just a few lines of code, and the function call overhead would decrease code performance. The driver is intended for rapid prototyping and documentation purposes for getting started with the XMEGA SPI module.
For size and/or speed critical code, it is recommended to copy the function contents directly into your application instead of making a function call.
Copyright (c) 2009 Atmel Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. The name of Atmel may not be used to endorse or promote products derived from this software without specific prior written permission.
4. This software may only be redistributed and used in connection with an Atmel AVR product.
THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Definition in file spi_driver.h.
| #define SPI_BUSY 2 |
The SPI module is busy with another transmission.
Definition at line 78 of file spi_driver.h.
Referenced by SPI_MasterInterruptTransceivePacket().
| #define SPI_INTERRUPTED 1 |
The transmission was interrupted by another master.
Definition at line 77 of file spi_driver.h.
Referenced by SPI_MasterInterruptTransceivePacket().
| #define SPI_MasterInterruptTransmissionComplete | ( | _spi | ) | ( (_spi)->dataPacket->complete ) |
Checks if transmission is complete.
| _spi | Pointer to SPI_Master_t struct instance. |
| true | The transmission is complete. |
| false | The transmission is in progress. |
Definition at line 123 of file spi_driver.h.
| #define SPI_MasterSSHigh | ( | _port, | |
| _pinBM | |||
| ) | ( (_port)->OUTSET = (_pinBM) ) |
Releases SPI SS line(s).
| _port | Pointer to the I/O port where the SS pins are located. |
| _pinBM | A bitmask selecting the pins to release. |
| NA |
Definition at line 145 of file spi_driver.h.
Referenced by SPI_MasterInterruptHandler(), SPI_MasterTransceivePacket(), and main().
| #define SPI_MasterSSLow | ( | _port, | |
| _pinBM | |||
| ) | ( (_port)->OUTCLR = (_pinBM) ) |
Pulls SPI SS line(s) low in order to address the slave devices.
| _port | Pointer to the I/O port where the SS pins are located. |
| _pinBM | A bitmask selecting the pins to pull low. |
| NA |
Definition at line 134 of file spi_driver.h.
Referenced by SPI_MasterInterruptTransceivePacket(), SPI_MasterTransceivePacket(), and main().
| #define SPI_MISO_bm 0x40 |
Bit mask for the MISO pin.
Definition at line 71 of file spi_driver.h.
Referenced by SPI_SlaveInit().
| #define SPI_MOSI_bm 0x20 |
Bit mask for the MOSI pin.
Definition at line 70 of file spi_driver.h.
Referenced by SPI_MasterInit().
| #define SPI_OK 0 |
The transmission completed successfully.
Definition at line 76 of file spi_driver.h.
Referenced by SPI_MasterInterruptTransceivePacket(), and main().
| #define SPI_SCK_bm 0x80 |
Bit mask for the SCK pin.
Definition at line 72 of file spi_driver.h.
Referenced by SPI_MasterInit().
| #define SPI_SlaveDataAvailable | ( | _spi | ) | ( (_spi)->module->STATUS & SPI_IF_bm ) |
Check if new data is available.
| _spi | Pointer to SPI_Slave_t struct instance. |
Definition at line 174 of file spi_driver.h.
Referenced by main().
| #define SPI_SlaveReadByte | ( | _spi | ) | ( (_spi)->module->DATA ) |
Read received data byte.
| _spi | Pointer to SPI_Slave_t struct instance. |
Definition at line 164 of file spi_driver.h.
| #define SPI_SlaveWriteByte | ( | _spi, | |
| _data | |||
| ) | ( (_spi)->module->DATA = (_data) ) |
Write data byte to the SPI shift register.
| _spi | Pointer to SPI_Slave_t struct instance. |
| _data | The data to write to the shift register. |
Definition at line 154 of file spi_driver.h.
| #define SPI_SS_bm 0x10 |
Bit mask for the SS pin.
Definition at line 69 of file spi_driver.h.
Referenced by SPI_MasterInterruptTransceivePacket().
| typedef struct SPI_DataPacket SPI_DataPacket_t |
SPI data packet struct.
| typedef struct SPI_Master SPI_Master_t |
SPI master struct. Holds pointer to SPI module, buffers and necessary varibles.
| typedef struct SPI_Slave SPI_Slave_t |
SPI slave struct. Holds pointers to SPI module and used port.
| void SPI_MasterCreateDataPacket | ( | SPI_DataPacket_t * | dataPacket, |
| const uint8_t * | transmitData, | ||
| uint8_t * | receiveData, | ||
| uint8_t | bytesToTransceive, | ||
| PORT_t * | ssPort, | ||
| uint8_t | ssPinMask | ||
| ) |
Create data packet.
This function prepares a data packet for transmission. Note that memory for dataPacket, transmitData and receiveData must be allocated outside this function.
| dataPacket | Pointer to data packet used for this transmission. |
| transmitData | Pointer to data to transmit. |
| receiveData | Pointer to receive buffer. |
| bytesToTransceive | The number of bytes to transmit/receive. |
| ssPort | Pointer to I/O port where the SS pin used for this transmission is located. |
| ssPinMask | Pin mask selecting the SS pin in ssPort. |
Definition at line 176 of file spi_driver.c.
References SPI_DataPacket::ssPort, SPI_DataPacket::ssPinMask, SPI_DataPacket::transmitData, SPI_DataPacket::receiveData, SPI_DataPacket::bytesToTransceive, SPI_DataPacket::bytesTransceived, and SPI_DataPacket::complete.
Referenced by main().
{
dataPacket->ssPort = ssPort;
dataPacket->ssPinMask = ssPinMask;
dataPacket->transmitData = transmitData;
dataPacket->receiveData = receiveData;
dataPacket->bytesToTransceive = bytesToTransceive;
dataPacket->bytesTransceived = 0;
dataPacket->complete = false;
}
| void SPI_MasterInit | ( | SPI_Master_t * | spi, |
| SPI_t * | module, | ||
| PORT_t * | port, | ||
| bool | lsbFirst, | ||
| SPI_MODE_t | mode, | ||
| SPI_INTLVL_t | intLevel, | ||
| bool | clk2x, | ||
| SPI_PRESCALER_t | clockDivision | ||
| ) |
Initialize SPI module as master.
This function initializes a SPI module as master. The CTRL and INTCTRL registers for the SPI module is set according to the inputs to the function. In addition, data direction for the MOSI and SCK pins is set to output.
| spi | The SPI_Master_t struct instance. |
| module | The SPI module. |
| port | The I/O port where the SPI module is connected. |
| lsbFirst | Data order will be LSB first if this is set to a non-zero value. |
| mode | SPI mode (Clock polarity and phase). |
| intLevel | SPI interrupt level. |
| clk2x | SPI double speed mode |
| clockDivision | SPI clock prescaler divison factor. |
Definition at line 90 of file spi_driver.c.
References SPI_Master::module, SPI_Master::port, SPI_Master::interrupted, SPI_Master::dataPacket, SPI_MOSI_bm, and SPI_SCK_bm.
Referenced by main().
{
spi->module = module;
spi->port = port;
spi->interrupted = false;
spi->module->CTRL = clockDivision | /* SPI prescaler. */
(clk2x ? SPI_CLK2X_bm : 0) | /* SPI Clock double. */
SPI_ENABLE_bm | /* Enable SPI module. */
(lsbFirst ? SPI_DORD_bm : 0) | /* Data order. */
SPI_MASTER_bm | /* SPI master. */
mode; /* SPI mode. */
/* Interrupt level. */
spi->module->INTCTRL = intLevel;
/* No assigned data packet. */
spi->dataPacket = NULL;
/* MOSI and SCK as output. */
spi->port->DIRSET = SPI_MOSI_bm | SPI_SCK_bm;
}
| void SPI_MasterInterruptHandler | ( | SPI_Master_t * | spi | ) |
Common SPI master interrupt service routine.
This function is called by the SPI interrupt service handlers. For each SPI module that uses this driver, the ISR should call this function with a pointer to the related SPI_Master_t struct as argument.
| spi | Pointer to the modules own SPI_Master_t struct. |
Definition at line 202 of file spi_driver.c.
References SPI_Master::dataPacket, SPI_DataPacket::bytesTransceived, SPI_Master::module, SPI_Master::interrupted, SPI_DataPacket::receiveData, dataPacket, SPI_DataPacket::bytesToTransceive, SPI_DataPacket::transmitData, SPI_DataPacket::ssPinMask, SPI_MasterSSHigh, SPI_DataPacket::ssPort, and SPI_DataPacket::complete.
Referenced by ISR().
{
uint8_t data;
uint8_t bytesTransceived = spi->dataPacket->bytesTransceived;
/* If SS pin interrupt (SS used and pulled low).
* No data received at this point. */
if ( !(spi->module->CTRL & SPI_MASTER_bm) ) {
spi->interrupted = true;
}
else { /* Data interrupt. */
/* Store received data. */
data = spi->module->DATA;
spi->dataPacket->receiveData[bytesTransceived] = data;
/* Next byte. */
bytesTransceived++;
/* If more data. */
if (bytesTransceived < spi->dataPacket->bytesToTransceive) {
/* Put data byte in transmit data register. */
data = spi->dataPacket->transmitData[bytesTransceived];
spi->module->DATA = data;
}
/* Transmission complete. */
else {
/* Release SS to slave(s). */
uint8_t ssPinMask = spi->dataPacket->ssPinMask;
SPI_MasterSSHigh(spi->dataPacket->ssPort, ssPinMask);
spi->dataPacket->complete = true;
}
}
/* Write back bytesTransceived to data packet. */
spi->dataPacket->bytesTransceived = bytesTransceived;
}
| uint8_t SPI_MasterInterruptTransceivePacket | ( | SPI_Master_t * | spi, |
| SPI_DataPacket_t * | dataPacket | ||
| ) |
Start transmission.
This function starts a SPI transmission. A data packet must be prepared for transmission first.
| spi | The SPI_Master_t struct instance. |
| dataPacket | The SPI_dataPacket_t struct instance. |
| SPI_OK | The transmission was completed successfully. |
| SPI_BUSY | The SPI module is busy. |
| SPI_INTERRUPTED | The transmission was interrupted by another master. |
Definition at line 258 of file spi_driver.c.
References SPI_Master::interrupted, SPI_Master::dataPacket, dataPacket, SPI_DataPacket::complete, SPI_BUSY, SPI_Master::port, SPI_SS_bm, SPI_INTERRUPTED, SPI_DataPacket::ssPinMask, SPI_MasterSSLow, SPI_DataPacket::ssPort, SPI_DataPacket::bytesTransceived, SPI_DataPacket::transmitData, SPI_Master::module, and SPI_OK.
Referenced by main().
{
uint8_t data;
bool interrupted = spi->interrupted;
/* If no packets sent so far. */
if (spi->dataPacket == NULL) {
spi->dataPacket = dataPacket;
}
/* If ongoing transmission. */
else if (spi->dataPacket->complete == false) {
return (SPI_BUSY);
}
/* If interrupted by other master. */
else if (interrupted) {
/* If SS released. */
if (spi->port->OUT & SPI_SS_bm) {
/* No longer interrupted. */
interrupted = false;
}
else {
return (SPI_INTERRUPTED);
}
}
/* NOT interrupted by other master.
* Start transmission. */
spi->dataPacket = dataPacket;
spi->dataPacket->complete = false;
spi->interrupted = false;
/* SS to slave(s) low.*/
uint8_t ssPinMask = spi->dataPacket->ssPinMask;
SPI_MasterSSLow(spi->dataPacket->ssPort, ssPinMask);
spi->dataPacket->bytesTransceived = 0;
/* Start sending data. */
data = spi->dataPacket->transmitData[0];
spi->module->DATA = data;
/* Successs */
return (SPI_OK);
}
| uint8_t SPI_MasterTransceiveByte | ( | SPI_Master_t * | spi, |
| uint8_t | TXdata | ||
| ) |
SPI mastertransceive byte.
This function clocks data in the DATA register to the slave, while data from the slave is clocked into the DATA register. The function does not check for ongoing access from other masters before initiating a transfer. For multimaster systems, checkers should be added to avoid bus contention.
SS line(s) must be pulled low before calling this function and released when finished.
| spi | The SPI_Master_t struct instance. |
| TXdata | Data to transmit to slave. |
Definition at line 327 of file spi_driver.c.
References SPI_Master::module.
Referenced by main().
| bool SPI_MasterTransceivePacket | ( | SPI_Master_t * | spi, |
| SPI_DataPacket_t * | dataPacket | ||
| ) |
SPI transceive data packet.
This function transceives a number of bytes contained in a data packet struct. The SS line is kept low until all bytes are transceived. The received bytes are stored in the data packet struct.
| spi | The SPI_Master_t struct instance. |
| dataPacket | The SPI_dataPacket_t struct instance. |
| true | Success |
| false | Failure |
Definition at line 357 of file spi_driver.c.
References SPI_Master::dataPacket, dataPacket, SPI_DataPacket::ssPinMask, SPI_DataPacket::ssPort, SPI_MasterSSLow, SPI_DataPacket::bytesToTransceive, SPI_DataPacket::transmitData, SPI_Master::module, SPI_DataPacket::receiveData, SPI_MasterSSHigh, SPI_DataPacket::bytesTransceived, and SPI_DataPacket::complete.
Referenced by main().
{
/* Check if data packet has been created. */
if(dataPacket == NULL) {
return false;
}
/* Assign datapacket to SPI module. */
spi->dataPacket = dataPacket;
uint8_t ssPinMask = spi->dataPacket->ssPinMask;
/* If SS signal to slave(s). */
if (spi->dataPacket->ssPort != NULL) {
/* SS to slave(s) low. */
SPI_MasterSSLow(spi->dataPacket->ssPort, ssPinMask);
}
/* Transceive bytes. */
uint8_t bytesTransceived = 0;
uint8_t bytesToTransceive = dataPacket->bytesToTransceive;
while (bytesTransceived < bytesToTransceive) {
/* Send pattern. */
uint8_t data = spi->dataPacket->transmitData[bytesTransceived];
spi->module->DATA = data;
/* Wait for transmission complete. */
while(!(spi->module->STATUS & SPI_IF_bm)) {
}
/* Read received data. */
data = spi->module->DATA;
spi->dataPacket->receiveData[bytesTransceived] = data;
bytesTransceived++;
}
/* If SS signal to slave(s). */
if (spi->dataPacket->ssPort != NULL) {
/* Release SS to slave(s). */
SPI_MasterSSHigh(spi->dataPacket->ssPort, ssPinMask);
}
/* Set variables to indicate that transmission is complete. */
spi->dataPacket->bytesTransceived = bytesTransceived;
spi->dataPacket->complete = true;
/* Report success. */
return true;
}
| void SPI_SlaveInit | ( | SPI_Slave_t * | spi, |
| SPI_t * | module, | ||
| PORT_t * | port, | ||
| bool | lsbFirst, | ||
| SPI_MODE_t | mode, | ||
| SPI_INTLVL_t | intLevel | ||
| ) |
Initialize SPI module as slave.
This function initializes a SPI module as slave. The CTRL and INTCTRL registers for the SPI module is set according to the inputs to the function. In addition, data direction for the MISO pin is set to output.
| spi | The SPI_Slave_t instance. |
| module | Pointer to the SPI module. |
| port | The I/O port where the SPI module is connected. |
| lsbFirst | Data order will be LSB first if this is set to true. |
| mode | SPI mode (Clock polarity and phase). |
| intLevel | SPI interrupt level. |
Definition at line 135 of file spi_driver.c.
References SPI_Slave::module, SPI_Slave::port, and SPI_MISO_bm.
Referenced by main().
{
/* SPI module. */
spi->module = module;
spi->port = port;
spi->module->CTRL = SPI_ENABLE_bm | /* Enable SPI module. */
(lsbFirst ? SPI_DORD_bm : 0) | /* Data order. */
mode; /* SPI mode. */
/* Interrupt level. */
spi->module->INTCTRL = intLevel;
/* MISO as output. */
spi->port->DIRSET = SPI_MISO_bm;
}