CROSS Technical Documentation User Manual and Technical Doc.
INFN Milano Bicocca
Loading...
Searching...
No Matches
The SPI bus

Spi for relays drivers, ADC and Pga DACS

SUMMARY:

User use of SPI



SPI communication follows the same approach adopted for I2C and CAN bus: exploitation of the CMSIS drivers. To this aim there is available a set of functions:

ARM_DRIVER_SPI Driver_SPI2 = {
SPI_GetVersion,
SPI_GetCapabilities,
SPI_Initialize, //Important for setting the calling function
SPI_Uninitialize, //Idle the SPI
SPI_PowerControl, //Switch on/off the SPI
SPI_Send, //sen data
SPI_Receive, //receive data
SPI_Transfer,
SPI_GetDataCount,
SPI_Control,
SPI_GetStatus //usefull for polling
};


So that an example of their use is the following:

extern ARM_DRIVER_SPI Driver_SPI2; // Viene inclusa la Periferica SPI2
ARM_DRIVER_SPI *SPIdrv= &Driver_SPI2; // Viene creato un puntatore a Driver_SPI2
SPIdrv->Control(SPI_control_for_DAC, SPI_DAC_SPEED); // SPI fits DAC specs at 16 bits and speed
#define SPI_DAC_SPEED
Definition: Spi.h:7
#define SPI_control_for_DAC
[ref_SPI_control_for_relay_driver]
Definition: Spi.h:13


To use the SPI first of all we need to intialize it and this is done by SPI_Inizialize() that collects a few functions between those listed above. SPI is used by the relay drivers, the ADC and the DAC of the PGA. It is therefore set according to them. As an instance, the relay drivers communicate with 8 bits, while the DAC with 16 bits. The core of SPI_Inizialize() is the setting of some bits and the clock by calling SPIdrv->Control(). The setting bits for SPIdrv->Control() are defined at SPI_control_for_relay_driver (the meaning of the bits can be verified at Bits meaning for SPI settings) with the speed spi_clock_for_relais, this is the defaul setting.
Every time we manage the realis or the DAC we need to set the SPI accordingly to the parallelism and the speed. For their setting 2 macros are defined: SPI_control_for_DAC with SPI_DAC_SPEED for the DAC and SPI_control_for_relay_driver with spi_clock_for_relais for the relais. An example for their setting is here:

SPIdrv->Control(SPI_control_for_DAC, SPI_DAC_SPEED); // SPI fits DAC specs at 16 bits and speed
SPIdrv->Control(SPI_control_for_relay_driver, spi_clock_for_relais); // SPI fits Relay driver specs at 8 bits and speed
#define spi_clock_for_relais
[ref_spi_clock_for_relais]
#define SPI_control_for_relay_driver
[ref_SPI_control_for_relay_driver]
Definition: Spi.h:10

Where SPI_control_for_relay_driver is:

#define SPI_control_for_relay_driver (ARM_SPI_MODE_MASTER | ARM_SPI_CPOL1_CPHA1 | ARM_SPI_MSB_LSB | ARM_SPI_SS_MASTER_SW | ARM_SPI_DATA_BITS(8) ) /*!< ''*/

while spi_clock_for_relais is:

#define spi_clock_for_relais (uint32_t) 400000 /*!< Clock frequency for relais driver */
Note
Pay attention: the SPI clock speed cannot be smaller than 1/255 times the core clock. As an instance, at 100 MHz core clock the smaller speed cannot be lower than 400 KHz.


Transmission and reception is done with SPIdrv->Send() and SPIdrv->Receive(), and the polling at SPIdrv->GetStatus().busy. SPIdrv->GetStatus() ia a structue:


Table GetStatus: Fields of the SPIdrv->GetStatus(). The row highlighted in red is the field we test during communication.
Data Fields
uint32_t busy: 1 Transmitter/Receiver busy flag.
uint32_t data_lost: 1 Data lost: Receive overflow / Transmit underflow (cleared on start of transfer operation)
uint32_t mode_fault: 1 Mode fault detected; optional (cleared on start of transfer operation)
uint32_t reserved: 29


We explooit the field busy, that remains "1" till the SPI operation has concluded.
The SPI_callback() is called after SPI operation has concluded, as a result of the interrupt. If necessary there is available the global evento_SPI which can be alternatively checked in polling, or to verify if a problem has occurred. evento_SPI can take the following values:

Table Interrupt Event: Values that the global evento_SPI can take. The row highlighted in red is the field we test during communication.
Parameter event Bit Description supported when ARM_SPI_CAPABILITIES
ARM_SPI_EVENT_TRANSFER_COMPLETE 1 << 0 Occurs after call to ARM_SPI_Send, ARM_SPI_Receive, or ARM_SPI_Transfer
to indicate that all the data has been transferred. The driver is ready for the next transfer operation.
ARM_SPI_EVENT_DATA_LOST 1 << 1 Occurs in slave mode when data is requested/sent by master but send/receive/transfer
operation has not been started and indicates that data is lost.
Occurs also in master mode when driver cannot transfer data fast enough.
ARM_SPI_EVENT_MODE_FAULT 1 << 2 Occurs in master mode when Slave Select is deactivated and indicates Master Mode Fault.
The driver is ready for the next transfer operation.

Here an example of use of the polled transmission with DAC:

DAC_transmission(){
SPIdrv->Control(SPI_control_for_DAC, SPI_DAC_SPEED); //Set the SPI with 16 bits
//prepare data to send
uint16_t data_to_send= ...
SPIdrv->Send ( &data_to_send ,1); //send 1 item at 16 bits
while( SPIdrv->GetStatus().busy ){} //wait end of transmission
//Function end
}

A bit more about the fw used for SPI



The functions invoked within the fw are the following:


First and only function to be used is the SPI_Inizialize():

205void SPI_Inizialize(void){
206// int32_t status;
207 SPIdrv->PowerControl (ARM_POWER_OFF); // Terminate any pending transfers, reset IRQ/DMA, power off peripheral
208 SPIdrv->Uninitialize ();
209 status = SPIdrv->Initialize (SPI_callback); // Viene inizializzata la Periferica SPI
210 status = SPIdrv->PowerControl(ARM_POWER_FULL); // Viene accesa la Periferica SPI
211
212 status = SPIdrv->Control(SPI_control_for_relay_driver,spi_clock_for_relais); //SPI initialization to relay driver by default
213// status = SPIdrv->Control (ARM_SPI_SET_BUS_SPEED, spi_clock_for_relais); //spi_clock_for_relais is our setting
214 // Viene configurata la linea SS: INACTIVE = HIGH
215 SPIdrv->Control (ARM_SPI_CONTROL_SS, ARM_SPI_SS_INACTIVE);
216}
void SPI_callback(uint32_t event)
After that the SPI ends its operations and the interrupt is generated this signal function is called ...
Definition: Spi.c:173
void SPI_Inizialize(void)
SPI is initialized here. Its ise t at 8 bits and 100 KHz, as default.
Definition: Spi.c:205



See also
That shown above is an extraction of the documentation from CMSIS drivers. For a complete reference to the SPI driver from CMSIS see the webs at Keil or ARM (in case of failure of either):


The codes for SPI is at: