SPI Communication in PSLab
PSLab supports communication using the Serial Peripheral Interface (SPI) protocol. The Desktop App as well as the Android App have the framework set-up to use this feature. SPI protocol is mainly used by a few sensors which can be connected to PSLab. For supporting SPI communication, the PSLab Communication library has a dedicated class defined for SPI. A brief overview of how SPI communication works and its advantages & limitations can be found here.
The class dedicated for SPI communication with numerous methods defined in them. The methods required for a particular SPI sensor may differ slightly, however, in general most sensors utilise a certain common set of methods. The set of methods that are commonly used are listed below with their functions.
In the setParameters method, the SPI parameters like Clock Polarity (CKP/CPOL), Clock Edge (CKE/CPHA), SPI modes (SMP) and other parameters like primary and secondary prescalar which are specific to the device used.
Primary Prescaler (0,1,2,3) for 64MHz clock->(64:1,16:1,4:1,1:1)
Secondary prescaler (0,1,..7)->(8:1,7:1,..1:1)
The values of CKP/CPOL and CKE/CPHA needs to set using the following convention and according to our requirements.
- At CPOL=0 the base value of the clock is zero, i.e. the idle state is 0 and active state is 1.
- For CPHA=0, data is captured on the clock’s rising edge (low→high transition) and data is changed at the falling edge (high→low transition).
- For CPHA=1, data is captured on the clock’s falling edge (high→low transition) and data is changed at the rising edge (low→high transition).
- At CPOL=1 the base value of the clock is one (inversion of CPOL=0), i.e. the idle state is 1 and active state is 0.
- For CPHA=0, data is captured on the clock’s falling edge (high→low transition) and data is changed at the rising edge (low→high transition).
- For CPHA=1, data is captured on the clock’s rising edge (low→high transition) and data is changed at the falling edge (high→low transition).
public void setParameters(int primaryPreScalar, int secondaryPreScalar, Integer CKE, Integer CKP, Integer SMP) throws IOException { if (CKE != null) this.CKE = CKE; if (CKP != null) this.CKP = CKP; if (SMP != null) this.SMP = SMP; packetHandler.sendByte(commandsProto.SPI_HEADER); packetHandler.sendByte(commandsProto.SET_SPI_PARAMETERS); packetHandler.sendByte(secondaryPreScalar | (primaryPreScalar << 3) | (this.CKE << 5) | (this.CKP << 6) | (this.SMP << 7)); packetHandler.getAcknowledgement(); }
The start method is responsible for sending the instruction to initiate the SPI communication and it takes the channel which will be used for communication as input.
public void start(int channel) throws IOException { packetHandler.sendByte(commandsProto.SPI_HEADER); packetHandler.sendByte(commandsProto.START_SPI); packetHandler.sendByte(channel); }
The setCS method is responsible for selecting the slave with which the SPI communication has to be done. This feature of SPI communication is known as Chip Select (CS) or Slave Select (SS). A master can use multiple Chip/Slave Select pins for communication whereas a slave utilises just one pin as SPI is based on single master multiple slaves principle. The capacity of PSLab is limited to two slave devices at a time.
public void setCS(String channel, int state) throws IOException { String[] chipSelect = new String[]{"CS1", "CS2"}; channel = channel.toUpperCase(); if (Arrays.asList(chipSelect).contains(channel)) { int csNum = Arrays.asList(chipSelect).indexOf(channel) + 9; packetHandler.sendByte(commandsProto.SPI_HEADER); if (state == 1) packetHandler.sendByte(commandsProto.STOP_SPI); else packetHandler.sendByte(commandsProto.START_SPI); packetHandler.sendByte(csNum); } else { Log.d(TAG, "Channel does not exist"); } }
The stop method is responsible for sending the instruction to the stop the communication with the slave.
public void stop(int channel) throws IOException { packetHandler.sendByte(commandsProto.SPI_HEADER); packetHandler.sendByte(commandsProto.STOP_SPI); packetHandler.sendByte(channel); }
PSLab SPI class has methods defined for sending either 8-bit or 16-bit data over SPI which are further classified on whether they request the acknowledgement byte (it helps to know whether the communication was successful or unsuccessful) or not.
The methods are so named send8, send16, send8_burst and send16_burst . The burst methods do not request any acknowledgement value and as a result work faster than the normal methods.
public int send16(int value) throws IOException { packetHandler.sendByte(commandsProto.SPI_HEADER); packetHandler.sendByte(commandsProto.SEND_SPI16); packetHandler.sendInt(value); int retValue = packetHandler.getInt(); packetHandler.getAcknowledgement(); return retValue; }
Resources:
- Learn more about SPI communication here https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi
- Learn more about SPI modes http://www.rosseeld.be/DRO/PIC/SPI_Timing.htm
- Comparison between I2C and SPI communication https://www.lifewire.com/g00/selecting-between-i2c-and-spi-819003?i10c.referrer=https%3A%2F%2Fwww.google.co.in%2F