DSPI

From chipKIT
Jump to: navigation, search
DSPI
Quick Look
Hardware (External hardware)
Include DSPI.h

The DSPI library provides support for any number of hardware SPI ports.

Contents

Detailed Introduction

The Digilent SPI (DSPI) library provides an alternative interface for accessing SPI ports to the standard chipKIT SPI library (SPI). The DSPI library provides access to all hardware SPI ports supported by the board in use and provides the ability to perform buffered and interrupt driven transfers.

The DSPI library only supports operation as an SPI master device and can’t be used to access SPI devices that require the data to be shifted to the right (least significant bit first). In shifting is required the SoftSPI library can be used instead.

Wiring

SPI Wiring Diagram

The DSPI library uses hardware peripherals on the processor and therefore the MOSI (SDO), MISO (SDI), and SCK pins are defined in the Board_Defs.h for the processor you are using. A default SS value is also included in Board_Defs.h but this can be overridden with the overloaded begin(uint8_t pinT) function or setPinSelect(uint8_t pin) function. As with the other SPI libraries the MOSI, MISO and SCK pins are common across all devices and the SS pin allows the master to select the slave devices to communicate with.


SPI Pin Definitions

Label Name Definition
MOSI (SDO) Master Out Slave In Used for sending data from the master to the slave
MISO (SDI) Master In Slave Out Used for sending data from the slave to the master
SCK Serial Clock Syncronizes data transmission.
SS Slave Select A pin to signal to a chip that the master is trying to communcate with it.




Introductory Programs

PmodJSTKDspi

This demo blinks LED3 and LED4 on boards that have four LEDs, and at the same time, blinks the two LEDs on the PmodJSTK (2-axis joystick). It reads the state of the two buttons on the PmodJSTK, and turns LED1 and LED2 on and off based on the button state. The X and Y joystick position is read and placed into global variables, but not used by the demo itself.

/************************************************************************/
/*                                                                      */
/*  PmodJSTKDspi  --  Illustrate Use of DSPI Library with PmodJSTK      */
/*                                                                      */
/************************************************************************/
/*  Author: Gene Apperson                                               */
/*  Copyright 2011, Digilent Inc, All rights reserved.                  */
/************************************************************************/
/*
  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
 
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
 
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
/************************************************************************/
/*  Module Description:                                                 */
/*                                                                      */
/* This example illustrates using the Digilent DSPI library to          */
/* communicate with a PmodJSTK from a Cerebot MX4cK.                    */
/*                                                                      */
/* This demo blinks LED3 and LED4 on boards that have four LEDs, and at */
/* the same time, blinks the two LEDs on the PmodJSTK. It reads the     */
/* state of the two buttons on the PmodJSTK, and turns LED1 and LED2 on */
/* and off based on the button state. The X and Y joystick position is  */
/* read and placed into global variables, but not used by the demo      */
/* itself.                                                              */
/*                                                                      */
/************************************************************************/
/*  Revision History:                                                   */
/*                                                                      */
/*  10/27/2011(GeneApperson): Created                                   */
/*                                                                      */
/************************************************************************/
 
 
/* ------------------------------------------------------------ */
/*                Include File Definitions                      */
/* ------------------------------------------------------------ */
 
/* Pull in the DSPI library
*/
#include <DSPI.h>
 
/* ------------------------------------------------------------ */
/*                Local Type Definitions                        */
/* ------------------------------------------------------------ */
 
#define	cntBlinkInit	50000
 
/* ------------------------------------------------------------ */
/*                Global Variables                              */
/* ------------------------------------------------------------ */
 
int      cntBtnBlink;
uint8_t  fbLedPmod;
uint8_t  fbBtnPmod;
int      xcoPmod;
int      ycoPmod;
int      fLed3;
int      fLed4;
 
/* Unlike many chipKIT/Arduino libraries, the DSPI library doesn't
** automatically instantiate any interface objects. It is necessary
** to declare an instance of one of the interface objects in the
** sketch. This creates an object to talk to SPI port 0. Similarly,
** declaring a variable of type DSPI1, DSPI2, DSPI3, etc. will create
** an object to talk to DSPI port 1, 2, or 3.
*/
DSPI0    spi;
 
/* ------------------------------------------------------------ */
/*                Local Variables                               */
/* ------------------------------------------------------------ */
 
 
/* ------------------------------------------------------------ */
/*                Forward Declarations                          */
/* ------------------------------------------------------------ */
 
 
/* ------------------------------------------------------------ */
/*                Procedure Definitions                         */
/* ------------------------------------------------------------ */
/***  setup
**
**  Parameters:
**    none
**
**  Return Value:
**    none
**
**  Errors:
**    none
**
**  Description:
**    Initialize the system.
*/
 
void setup() {
    DeviceInit();
    AppInit();
}
 
/* ------------------------------------------------------------ */
/***  loop
**
**  Parameters:
**    none
**
**  Return Value:
**    none
**
**  Errors:
**    none
**
**  Description:
**    Main application loop.
*/
 
void loop() {
    AppTask();
}
 
/* ------------------------------------------------------------ */
/***  DeviceInit
**
**  Parameters:
**    none
**
**  Return Value:
**  none
**
**  Errors:
**  none
**
**  Description:
**    Perform basic board/device level initialization.
*/
 
void DeviceInit() {
    /* Set the LED pins to be outputs. Some boards support more
    ** than two LEDs. On those boards, also blink the additional
    ** LEDs.
    */
    pinMode(PIN_LED1, OUTPUT);
    pinMode(PIN_LED2, OUTPUT);
#if defined(PIN_LED3)
    pinMode(PIN_LED3, OUTPUT);
#endif
#if defined(PIN_LED4)
    pinMode(PIN_LED4, OUTPUT);
#endif
    /* Initialize the SPI port.
    ** Setting the SPI clock speed to 250khz will satisfy the
    ** PmodJSTK requirement of having at least 6us of delay between
    ** bytes sent.
    */
    spi.begin();
    spi.setSpeed(250000);
}
 
/* ------------------------------------------------------------ */
/***	AppInit
**
**  Parameters:
**    none
**
**  Return Value:
**    none
**
**  Errors:
**    none
**
**  Description:
**    Perform application level initialization. Call the various
**    init functions to initalize the application subsystems.
*/
 
void AppInit() {
    /* Init program state variables.
    */
    cntBtnBlink = cntBlinkInit;
    fbLedPmod = 0x01;
    fbBtnPmod = 0;
    xcoPmod = 0;
    ycoPmod = 0;
    /* Start with LED3 on and LED4 off
    */
    fLed3 = HIGH;
    fLed4 = LOW;
}
 
/* ------------------------------------------------------------ */
/***	AppTask
**
**  Parameters:
**    none
**
**  Return Value:
**    none
**
**  Errors:
**    none
**
**  Description:
**    Perform main application functions. This is called once
**    each time through the main program loop.
*/
 
void AppTask() {
    unsigned int	dwBtn;
    /* Check the state of button 1 and set LED 1 accordingly
    */
    dwBtn = fbBtnPmod & 0x01;
 
    if (dwBtn == 0) {
        digitalWrite(PIN_LED1, LOW);
    } else {
        digitalWrite(PIN_LED1, HIGH);
    }
 
    /* Check the state of button 2 and set LED 2 accordingly
    */
    dwBtn = fbBtnPmod & 0x02;
 
    if (dwBtn == 0) {
        digitalWrite(PIN_LED2, LOW);
    } else {
        digitalWrite(PIN_LED2, HIGH);
    }
 
    /* Check if it is time to blink LED3 & LED4 and update
    ** the joystick.
    */
    cntBtnBlink -= 1;
 
    if (cntBtnBlink == 0) {
#if defined(PIN_LED3)
        digitalWrite(PIN_LED3, fLed3);
        fLed3 = (fLed3 == HIGH) ? LOW : HIGH;
#endif
#if defined(PIN_LED4)
        digitalWrite(PIN_LED4, fLed4);
        fLed4 = (fLed4 == HIGH) ? LOW : HIGH;
#endif
        /* Toggle the setting for the LEDs on the joystick.
        */
        fbLedPmod ^= 0x03;
        /* Update the joystick.
        */
        ReadJoystick(fbLedPmod, &fbBtnPmod, &xcoPmod, &ycoPmod);
        cntBtnBlink = cntBlinkInit;
    }
}
 
/* ------------------------------------------------------------ */
/***  ReadJoystick
**
**  Parameters:
**    fbLed	- LED state to set
**    pfbBtn	- variable to receive button state
**    pxco	- pointer to var to receive x coordinate
**    pyco	- pointer to var to receive y coordinate
**
**  Return Value:
**    none
**
**  Errors:
**    none
**
**  Description:
**    Read the current position of the joystick and buttons.
*/
void ReadJoystick(uint8_t fbLed, uint8_t * pfbBtn, int * pxco, int * pyco) {
    uint8_t    rgbSnd[5];
    uint8_t    rgbRcv[5];
    int	     ib;
 
    /* Initialize the transmit buffer.
    */
    for (ib = 0; ib < 5; ib++) {
        rgbSnd[ib] = 0x50 + ib;
    }
 
    rgbSnd[0] = fbLedPmod + 0x80;  //first byte sent sets the LEDs
    /* Bring SS low to begin the transaction.
    */
    spi.setSelect(LOW);
    /* Wait 10us for Pmod to become ready
    */
    Delay10us();
    /* Send the data to the Pmod and get the response.
    */
    spi.transfer(5, rgbSnd, rgbRcv);
    /* Bring SS high to end the transaction.
    */
    spi.setSelect(HIGH);
    /* Set up the return values.
    */
    *pfbBtn = rgbRcv[4] >> 1;
    *pxco = (uint16_t)((rgbRcv[1] << 8) + rgbRcv[0]);
    *pyco = (uint16_t)((rgbRcv[3] << 8) + rgbRcv[2]);
}
 
/* ------------------------------------------------------------ */
/***  Delay10us
**
**  Parameters:
**    none
**
**  Return Value:
**    none
**
**  Errors:
**    none
**
**  Description:
**    Delay loop for ~10uS
*/
 
void Delay10us() {
    volatile int		cnt;
 
    for (cnt = 0; cnt < 100; cnt++) {
    }
}
 
/* ------------------------------------------------------------ */
 
/************************************************************************/


Full library usage

DGSPI

DGSPI is an Abstract base class (interface) so DSPI and SoftSPI can implement a generic interface.

Generic Interface

 
        // Initialization and setup functions.
        virtual bool        begin() = 0;
        virtual void        end() = 0;
        virtual void        setSpeed(uint32_t spd) = 0;
        virtual void        setMode(uint16_t mod) = 0;
 
        // Data transfer functions
        virtual void        setSelect(uint8_t sel) = 0;
        virtual uint8_t     transfer(uint8_t bVal) = 0;
        virtual void        transfer(uint16_t cbReq, uint8_t * pbSnd, uint8_t * pbRcv) = 0;
        virtual void        transfer(uint16_t cbReq, uint8_t * pbSnd) = 0;
        virtual void        transfer(uint16_t cbReq, uint8_t bPad, uint8_t * pbRcv) = 0;

DSPI

Parent class: DGSPI

Constants


Flags for SPI Modes

Name Value Clock Polarity
(CPOL/CKP)
Clock Edge
(CKE/NCPHA)
DSPI_MODE0 CKP = 0 CKE = 1 0 1
DSPI_MODE1 CKP = 0 CKE = 0 0 0
DSPI_MODE2 CKP = 1 CKE = 1 1 1
DSPI_MODE3 CKP = 1 CKE = 0 1 0

Flags for Bits

Name Value
DSPI_8BIT 8
DSPI_16BIT 16
DSPI_32BIT 32

Default SPI Clock Speed

Name Value
_DSPI_SPD_DEFAULT 1000000L


Public Functions


begin()

 
bool begin();

Initialize the SPI port with all default values.


begin(uint8_t pin)

 
bool begin(uint8_t pin);

Initialize the SPI port with the default values. This will set the clock rate to the default speed and the pin for SS to the specified pin


begin(uint8_t miso, uint8_t mosi))

 
bool begin(uint8_t miso, uint8_t mosi);

Defined for PIC32MX1XX, PIC32MX2XX, PIC32MZXX, and PIC32MX47X only. Initialize the SPI port with new PPS mappings.


begin(uint8_t miso, uint8_t mosi, uint8_t pin)

 
bool begin(uint8_t miso, uint8_t mosi, uint8_t pin);

Defined for PIC32MX1XX, PIC32MX2XX, PIC32MZXX, and PIC32MX47X only. Initialize the SPI port with new PPS mappings.


end()

 
void end();

Return the object to the uninitialized state and disable the SPI controller.


setSpeed(uint32_t spd)

 
void setSpeed(uint32_t spd);

This sets the SPI clock speed to the highest supported frequency that doesn't exceed the requested value. It computes the appropriate value to load into the SPI baud register based on requested clock speed and peripheral bus frequency.


unsetSpeed()

 
void unsetSpeed();

Undo the last setSpeed() call to restore the previous baud rate.


setMode(uint16_t mod)

 
void setMode(uint16_t  mod);

Set the SPI controller to the requested data mode. This should be one of the values: DSPI_MODE0, DSPI_MODE1, DSPI_MODE2, DSPI_MODE3


unsetMode()

 
void unsetMode();

Undo the last setMode call.


setPinSelect(uint8_t pin)

 
void setPinSelect(uint8_t pin);

This sets the pin used for slave select. It will make the pin be an output driving high. This pin will then be use by the setSelect method.


setTransferSize(uint8_t txsize)

 
void setTransferSize(uint8_t txsize);

Sets the transfer packet size. Options: DSPI_8BIT / DSPI_16BIT / DSPI_32BIT


setSelect(uint8_t sel)

void setSelect(uint8_t sel) { digitalWrite(pinSS, sel); };

Sets the state of the Slave Select (SS) pin. HIGH / LOW


transfer(uint32_t bVal)

uint32_t transfer(uint32_t bVal);

Send the specified byte to the SPI slave device, returning the byte received from the slave device.


transfer(uint8_t bVal)

uint8_t transfer(uint8_t bVal) { return((uint8_t) transfer((uint32_t) bVal)); }

Send the specified byte to the SPI slave device, returning the byte received from the slave device.


transfer(uint16_t cbReq, uint8_t * pbSnd, uint8_t * pbRcv)

void transfer(uint16_t cbReq, uint8_t * pbSnd, uint8_t * pbRcv);

This function will send the requested bytes to the SPI slave device, simultaneously saving the bytes received from the slave device.


- cbReq - number of bytes to transfer

- pbSnd - pointer to buffer to bytes to send

- pbRcv - pointer to hold received bytes


transfer(uint16_t cbReq, uint8_t * pbSnd)

void transfer(uint16_t cbReq, uint8_t * pbSnd);

This function will send the requested bytes to the SPI slave device, discarding the bytes received from the slave.


- cbReq - number of bytes to transfer

- pbSnd - pointer to buffer to bytes to send


transfer(uint16_t cbReq, uint8_t bPad, uint8_t * pbRcv)

void transfer(uint16_t cbReq, uint8_t bPad, uint8_t * pbRcv);

This function will receive the specified number of bytes from the slave. The given pad byte will be sent to the slave to cause the received bytes to be sent.


-cbReq - number of bytes to receive from the slave

-bPad - pad byte to send to slave

-pbRcv - buffer to hold received bytes


enableInterruptTransfer()

 
void enableInterruptTransfer();

Sets up the interrupt controller and enables interrupts for this SPI port.


disableInterruptTransfer()

void disableInterruptTransfer();

Turns off SPI interrupts for this SPI port.


intTransfer(uint16_t cbReq, uint8_t * pbSnd, uint8_t * pbRcv)

void intTransfer(uint16_t cbReq, uint8_t * pbSnd, uint8_t * pbRcv);

This function will set up and begin an interrupt driven transfer where the received bytes are stored into a receive buffer.


- cbReq - number of bytes to transfer

- pbSnd - pointer to buffer to bytes to send

- pbRcv - pointer to hold received bytes


intTransfer(uint16_t cbReq, uint8_t * pbSnd)

void intTransfer(uint16_t cbReq, uint8_t * pbSnd);

This function will set up and begin an interrupt driven transfer where the received bytes are discarded.

- cbReq - number of bytes to transfer

- pbSnd - pointer to buffer to bytes to send


intTransfer(uint16_t cbReq, uint8_t bPadT, uint8_t * pbRcv)

void intTransfer(uint16_t cbReq, uint8_t bPadT, uint8_t * pbRcv);

This function will set up and begin an interrupt driven transfer where there is no transmit buffer but the returned bytes are stored. The given pad byte is sent to the slave to cause the returned bytes to be sent by the slave.


-cbReq - number of bytes to receive from the slave

-bPad - pad byte to send to slave

-pbRcv - buffer to hold received bytes


cancelIntTransfer()

void cancelIntTransfer();

This will cancel an interrupt driven transfer. It is still the caller's responsibility to drive SS high to release the slave device.


transCount()

uint16_t transCount() { return cbCur; };

Count of bytes left to transfer


isOverflow()

int isOverflow() { return fRov; };

Overrun error interrupt triggered.


clearOverflow()

void clearOverflow() { fRov = 0; };

Clear the receive overflow error flag.


DSPI0

Parent class: DSPI

Available only if NUM_DSI_PORTS is greater than 1.


Public Functions


enableInterruptTransfer()

void enableInterruptTransfer();

Sets up the interrupt controller and enables interrupts for this SPI port.


disableInterruptTransfer()

void disableInterruptTransfer();

Turns off SPI interrupts for this SPI port.


DSPI1

Parent class: DSPI

Available only if NUM_DSI_PORTS is greater than 1.


Public Functions


enableInterruptTransfer()

void enableInterruptTransfer();

Sets up the interrupt controller and enables interrupts for this SPI port.


disableInterruptTransfer()

void disableInterruptTransfer();

Turns off SPI interrupts for this SPI port.


DSPI2

Parent class: DSPI

Available only if NUM_DSI_PORTS is greater than 2.


Public Functions


enableInterruptTransfer()

void enableInterruptTransfer();

Sets up the interrupt controller and enables interrupts for this SPI port.


disableInterruptTransfer()

void disableInterruptTransfer();

Turns off SPI interrupts for this SPI port.


DSPI3

Parent class: DSPI

Available only if NUM_DSI_PORTS is greater than 3.


Public Functions


enableInterruptTransfer()

void enableInterruptTransfer();

Sets up the interrupt controller and enables interrupts for this SPI port.


disableInterruptTransfer()

void disableInterruptTransfer();

Turns off SPI interrupts for this SPI port.


External Links

https://github.com/chipKIT32/chipKIT-core/tree/master/pic32/libraries/DSPI] - The github repository for the chipKIT DSPI Library.