SoftSPI | |
---|---|
Quick Look | |
Hardware | (External hardware) |
Include | SoftSPI.h |
The SoftSPI library provides support for any number of bit-banged software SPI ports.
The SPI protocol is a synchronous serial data protocol which contains one master (chipKIT) and one or more slave devices. It's designed for fast communication over short distances such as between two ICs on a PCB. The SoftSPI library only supports operation as an SPI master device.
The SoftSPI library allows you to specify any pin for MOSI (SDO), MISO (SDI), SCK, and SS. 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.
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. |
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.
/************************************************************************/
/* */
/* PmodJSTKSoftSpi -- Illustrate Use of SoftSPI 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 chipKIT SoftSPI library to */
/* communicate with a Digilent PmodJSTK. */
/* */
/* 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: */
/* */
/* 11/21/2011(GeneApperson): Created */
/* */
/************************************************************************/
/* ------------------------------------------------------------ */
/* Include File Definitions */
/* ------------------------------------------------------------ */
/* Pull in the SoftSPI library
*/
#include <SoftSPI.h>
/* ------------------------------------------------------------ */
/* Local Type Definitions */
/* ------------------------------------------------------------ */
#define cntBlinkInit 50000
#define SPI_PORT 1
#if (SPI_PORT == 1)
#define pinSS 24
#define pinMOSI 25
#define pinMISO 26
#define pinSCK 27
#elif (SPI_PORT == 2)
#define pinSS 32
#define pinMOSI 33
#define pinMISO 34
#define pinSCK 35
#elif (SPI_PORT == 3)
#define pinSS 40
#define pinMOSI 41
#define pinMISO 42
#define pinSCK 43
#endif
/* ------------------------------------------------------------ */
/* Global Variables */
/* ------------------------------------------------------------ */
int cntBtnBlink;
uint8_t fbLedPmod;
uint8_t fbBtnPmod;
int xcoPmod;
int ycoPmod;
int fLed3;
int fLed4;
/* Unlike many chipKIT/Arduino libraries, the SoftSPI library doesn't
** automatically instantiate any interface objects. It is necessary
** to declare an instance of one of the interface objects in the
** sketch.
*/
SoftSPI 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.
** Note: The pmodJSTK requires a delay of at least 6uS between
** bytes, so the delay is set to 6uS below.
*/
spi.begin(pinSS, pinMOSI, pinMISO, pinSCK);
spi.setSpeed(250000);
spi.setMode(SSPI_MODE0);
spi.setDirection(SSPI_SHIFT_LEFT);
spi.setDelay(6);
}
/* ------------------------------------------------------------ */
/*** 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 on the PmodJSTK 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++) {
}
}
/* ------------------------------------------------------------ */
/************************************************************************/
Name | Value | Clock Polarity (CPOL/CKP) |
Clock Phase (CPHA) |
Clock Edge (CKE/NCPHA) |
---|---|---|---|---|
SSPI_MODE0 | 0x00 | 0 | 0 | 1 |
SSPI_MODE1 | 0x04 | 0 | 1 | 0 |
SSPI_MODE2 | 0x08 | 1 | 0 | 1 |
SSPI_MODE3 | 0x0C | 1 | 1 | 0 |
Name | Value |
---|---|
SSPI_SHIFT_LEFT | 0 |
SSPI_SHIFT_RIGHT | 1 |
Name | Value |
---|---|
SSPI_SPEED_DEFAULT | 500000 |
SoftSPI();
Initialize the object before use.
SoftSPI(uint8_t pinSSt, uint8_t pinMOSIt, uint8_t pinMISOt, uint8_t pinSCKt);
bool begin(void);
Pepare the object for use. Set the pin directions, and set SS HIGH and the clock to the idle state
bool begin(uint8_t pinSSt, uint8_t pinMOSIt, uint8_t pinMISOt, uint8_t pinSCKt);
Pepare the object for use. Set the pin directions, and set SS HIGH and the clock to the idle state
void end();
Deinitialize the object. Release all of the pins, by making them all inputs.
void setSpeed(uint32_t spd);
Set the SPI clock speed to the closest supported value to the requested clock speed.
void setMode(uint16_t mod);
Set the SPI mode to the requested value. Default to mode 0 if an unsupported value is specified.
void setDirection(int dir);
Set the shift direction to the requested value. Default to shift left if an unsupported value is specified.
void setDelay(int dly);
dly max 4294
Set the interbyte delay to the specified value.
The relationship between the delay count value and the delay in microseconds has been determined experimentally to be approximately: d ~ P * (47 + 880/100 * n) where P is period of processor clock. This yields the delay count to be: n = ((80*d - 47) * 100) / 880 Note: this calculations assumes that the processor clock is 80Mhz.
void setSelect(uint8_t sel);
Set's the SS pin High / Low specified by the sel parameter.
uint8_t transfer(uint8_t bVal);
Send the specified byte to the slave and return the byte received from the slave.
void transfer(uint16_t cbReq, uint8_t * pbSnd, uint8_t * pbRcv);
void transfer(uint16_t cbReq, uint8_t * pbSnd);
Send the requested number of bytes, storing the bytes received in the specified buffer.
void transfer(uint16_t cbReq, uint8_t bPad, uint8_t * pbRcv);
This function will send the requested bytes to the SPI slave device, discarding the bytes received from the slave.