SPI Library

The SPI module is available with all ARM MCUs. mikroBasic PRO for ARM provides a library for initializing the Slave mode and initializing and comfortable work with the Master mode. The ARM can easily communicate with other devices via SPI: A/D converters, D/A converters, MAX7219, LTC1290, etc.

  Important :

Library Routines

Generic Routines

SPIx_Init

Prototype

sub procedure SPIx_Init()

Description

Configures and initializes the SPI module with default settings.

Default settings for Stellaris MCUs :

  • Master mode.
  • 8-bit data mode.
  • Serial clock set to 2 MHz.
  • Clock idle state low.
  • Serial output data changes on the first clock edge transition.

Default settings for ST MCUs :

  • Master mode.
  • 8-bit data mode.
  • Serial clock set to Peripheral clock/64.
  • Clock idle state low.
  • Serial output data changes on the first clock edge transition.
  • Slave Select output disabled.
  • Software Slave Management disabled.
Parameters

None.

Returns

Nothing.

Requires

MCU must have the SPI1 module.

Example
' Initialize the SPI1 module with default settings
SPI1_Init()
Notes
  • SPI library routines require you to specify the module you want to use. To select the desired SPI module, simply change the letter x in the routine prototype for a number from 0 to 3.
  • Number of SPI modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.
  • Switching between the SPI modules in the SPI library is done by the SPI_Set_Active function (both SPI modules have to be previously initialized).

Stellaris

  • For MCUs with alternative PORT functions on GPIO pins, SPI0_Init is set on GPIO_PORTA pins 2, 4 and 5, while the SPI1_Init is set on GPIO_PORTE pins 0, 2 and 3.

STM32

  • SPI1_Init is set on PORTA pins 5, 6 and 7,
  • SPI2_Init is set on PORTB pins 13, 14 and 15,
  • SPI3_Init is set on PORTB pins 3, 4 and 5.

SPIx_Init_Advanced

Prototype ' for Stellaris MCUs :

sub procedure SPIx_Init_Advanced(dim bit_rate_Hz as longword, dim master_slave_mode as word, dim config as word)

' for Stellaris MCUs with alternative PORT functions on GPIO pins :

sub procedure SPIx_Init_Advanced(dim bit_rate_Hz as longword, dim master_slave_mode as word, dim config as word, dim module as ^const Module_Struct)

' for ST MCUs :

sub procedure SPIx_Init_Advanced(dim clock_divider as byte, dim config as longword, dim module as ^const Module_Struct)

Description

Configures and initializes the SPI module with user defined settings.

Parameters

Parameters bit_rate_Hz, clock_divider, master_slave_mode and config determine the working mode for SPI.

Stellaris

  • The bit_rate_Hz parameter determines the SPI clock value in Hz.
  • The master_slave_mode parameter determines the working mode for SPI module.
    Master/Slave mode
    Description Predefined library const
    Master mode _SPI_MASTER
    Slave mode _SPI_SLAVE
  • The parameter config determines the data size, clock polarity and clock phase.
    This value is deriven from OR-ing the following constants :
    Data Length Size
    Description Predefined library const
    4-bit data size _SPI_4_BIT
    5-bit data size _SPI_5_BIT
    6-bit data size _SPI_6_BIT
    7-bit data size _SPI_7_BIT
    8-bit data size _SPI_8_BIT
    9-bit data size _SPI_9_BIT
    10-bit data size _SPI_10_BIT
    11-bit data size _SPI_11_BIT
    12-bit data size _SPI_12_BIT
    13-bit data size _SPI_13_BIT
    14-bit data size _SPI_14_BIT
    15-bit data size _SPI_15_BIT
    16-bit data size _SPI_16_BIT

    Clock Polarity
    Description Predefined library const
    IDLE state is Lo, ACTIVE state is Hi _SPI_CLK_IDLE_LOW
    IDLE state is Hi, ACTIVE state is Lo _SPI_CLK_IDLE_HIGH

    Clock Phase
    Description Predefined library const
    Data is sampled on the first clock edge transition _SPI_FIRST_CLK_EDGE_TRANSITION
    Data is sampled on the second clock edge transition _SPI_SECOND_CLK_EDGE_TRANSITION
  • module: appropriate module pinout, see the following table :
    SPI Module Pinouts for Stellaris
    SPI0 _GPIO_MODULE_SPI0_A245
    SPI1 _GPIO_MODULE_SPI1_E023 _GPIO_MODULE_SPI1_F245 _GPIO_MODULE_SPI1_H467

STM32

  • The clock_divider parameter determines the clock for SPI module (ST specifics).
    SPI Clock
    Description Predefined library const
    Peripheral Clock/2 _SPI_FPCLK_DIV2
    Peripheral Clock/4 _SPI_FPCLK_DIV4
    Peripheral Clock/8 _SPI_FPCLK_DIV8
    Peripheral Clock/16 _SPI_FPCLK_DIV16
    Peripheral Clock/32 _SPI_FPCLK_DIV32
    Peripheral Clock/64 _SPI_FPCLK_DIV64
    Peripheral Clock/128 _SPI_FPCLK_DIV128
    Peripheral Clock/256 _SPI_FPCLK_DIV256
  • The parameter config determines the data size, clock polarity and clock phase.
    This value is deriven from OR-ing the following constants :
    Data Length Size
    Description Predefined library const
    8-bit data size _SPI_8_BIT
    16-bit data size _SPI_16_BIT

    Master/Slave mode
    Description Predefined library const
    Master mode _SPI_MASTER
    Slave mode _SPI_SLAVE

    Clock Polarity
    Description Predefined library const
    IDLE state is Lo, ACTIVE state is Hi _SPI_CLK_IDLE_LOW
    IDLE state is Hi, ACTIVE state is Lo _SPI_CLK_IDLE_HIGH

    Clock Phase
    Description Predefined library const
    Data is sampled on the first clock edge transition _SPI_FIRST_CLK_EDGE_TRANSITION
    Data is sampled on the second clock edge transition _SPI_SECOND_CLK_EDGE_TRANSITION

    Bit Sending Hierarchy
    Description Predefined library const
    Most Significant Bit (MSB) sent first _SPI_MSB_FIRST
    Least Significant Bit (MSB) sent first _SPI_LSB_FIRST

    Software Slave Management
    Description Predefined library const
    Software Slave Management Enable _SPI_SSM_ENABLE
    Software Slave Management Disable _SPI_SSM_DISABLE

    Slave Select Output
    Description Predefined library const
    Slave Select Output Enable _SPI_SS_ENABLE
    Slave Select Output Disable _SPI_SS_DISABLE

    Internal Slave Select
    Description Predefined library const
    Internal Slave Select = 0 _SPI_SSI_0
    Internal Slave Select = 1 _SPI_SSI_1
  • module: appropriate module pinout, see the following table :

    SPI Module Pinouts for ST
    SPI1 _GPIO_MODULE_SPI1_PA567 _GPIO_MODULE_SPI1_PB345
    SPI1 _GPIO_MODULE_SPI2_PB13_14_15 _GPIO_MODULE_SPI2_PD134
    SPI3 _GPIO_MODULE_SPI3_PB345 _GPIO_MODULE_SPI3_PC10_11_12
Returns

Nothing.

Requires

MCU must have the SPI module.

Example

Stellaris

' Set SPI1 to the Master Mode, data length is 16-bit, clock = 2MHz, clock IDLE state high and data transmitted at the first clock edge transition :
SPI1_Init_Advanced(2000000, _SPI_MASTER, _SPI_16_BIT OR _SPI_CLK_IDLE_HIGH, _SPI_FIRST_CLK_EDGE_TRANSITION)

' Set SPI1 to the Master Mode, data length is 16-bit, clock = 2MHz, clock IDLE state high and data transmitted at the first clock edge transition, on GPIO_PORTE :
SPI1_Init_Advanced(2000000, _SPI_MASTER, _SPI_16_BIT OR _SPI_CLK_IDLE_HIGH, _SPI_FIRST_CLK_EDGE_TRANSITION, @_GPIO_MODULE_SPI1_E023)

STM32

' Set SPI1 to the Master Mode, data length is 8-bit, clock = Peripheral/64, clock IDLE state low and data transmitted at the first clock edge transition, MSB transferred first, Slave Select Disabled :
SPI1_Init_Advanced(_SPI_FPCLK_DIV64, _SPI_MASTER OR _SPI_8_BIT OR _SPI_CLK_IDLE_LOW OR _SPI_FIRST_CLK_EDGE_TRANSITION OR _SPI_MSB_FIRST OR _SPI_SS_DISABLE OR _SPI_SSM_ENABLE OR _SPI_SSI_1, @_GPIO_MODULE_SPI1_PA567)
Notes

SPI library routines require you to specify the module you want to use. To select the desired SPI module, simply change the letter x in the routine prototype for a number from 0 to 3.

Number of SPI modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

For available working modes for a specific MCU please read the appropriate datasheet.

SPIx_Read

Prototype

sub function SPIx_Read(dim buffer as longword) as word

Description

Reads one word from the SPI bus.

Parameters
  • buffer: dummy data for clock generation (see device Datasheet for SPI modules implementation details)
Returns

Received data.

Requires

Routine requires at least one SPI module.

Used SPI module must be initialized before using this function. See the SPIx_Init and SPIx_Init_Advanced routines.

Example
' read a word from the SPI bus 
dim take, buffer as word
...
take = SPI1_Read(buffer)
Notes

SPI library routines require you to specify the module you want to use. To select the desired SPI module, simply change the letter x in the routine prototype for a number from 0 to 3.

Number of SPI modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

SPIx_Write

Prototype

sub procedure SPIx_Write(dim data_out as word/b>)

Description

Writes one word via the SPI bus.

Parameters
  • data_out: data to be sent
Returns

Nothing.

Requires

Routine requires at least one SPI module.

Used SPI module must be initialized before using this function. See the SPIx_Init and SPIx_Init_Advanced routines.

Example
' write a word to the SPI bus
dim data_out as word
...
SPI1_Write(data_out)
Notes

SPI library routines require you to specify the module you want to use. To select the desired SPI module, simply change the letter x in the routine prototype for a number from 0 to 3.

Number of SPI modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

SPI_Set_Active

Prototype

sub procedure SPI_Set_Active(dim read_ptr as ^TSpi_Rd_Ptr, dim write_ptr as ^TSpi_Wr_Ptr)

Description

Sets the active SPI module which will be used by the SPIx_Read and SPIx_Write routines.

Parameters

Parameters :

Returns

Nothing.

Requires

Routine is available only for MCUs with multiple SPI modules.

Used SPI module must be initialized before using this function. See the SPIx_Init and SPIx_Init_Advanced routines.

Example
SPI_Set_Active(@SPI1_Read, @SPI1_Write) ' Sets the SPI1 module active
Notes

Number of SPI modules per MCU differs from chip to chip. Please, read the appropriate datasheet before utilizing this library.

SPI_Read

Prototype

sub function SPI_Read(dim buffer as word) as longword

Description

Reads one word or byte from the SPI bus.

This is a generic routine which uses the active SPI module previously activated by the SPI_Set_Active routine.

Parameters
  • buffer: dummy data for clock generation (see device Datasheet for SPI modules implementation details)
Returns

Received data.

Requires

Routine requires at least one SPI module.

Used SPI module must be initialized before using this function. See the SPIx_Init and SPIx_Init_Advanced routines.

Example
' read a word from the SPI bus 
dim take, buffer as word
...
take = SPI_Read(buffer)
Notes

None.

SPI_Write

Prototype

sub procedure SPI_Write(dim data_out as word)

Description

Writes one word or byte via the SPI bus.

This is a generic routine which uses the active SPI module previously activated by the SPI_Set_Active routine.

Parameters
  • data_out: data to be sent
Returns

Nothing.

Requires

Routine requires at least one SPI module.

Used SPI module must be initialized before using this function. See the SPIx_Init and SPIx_Init_Advanced routines.

Example
' write a word to the SPI bus
dim data_out as word
...
SPI_Write(data_out)
Notes

None.

Library Example

The code demonstrates how to use SPI library functions for communication between SPI module of the MCU and MCP4921 DAC chip.

Stellaris

program DAC

' DAC module connections
dim Chip_Select as sbit at GPIO_PORTA_DATA.B1
' End DAC module connections

dim value as word

sub procedure InitMain()
  ' Set RB0 and RB1 pins as input
  GPIO_Digital_Input(@GPIO_PORTB, _GPIO_PINMASK_0 or _GPIO_PINMASK_1)
  GPIO_Digital_Output(@GPIO_PORTA, _GPIO_PINMASK_1)      ' Set CS# pin as Output
  Chip_Select = 1                                       ' Deselect DAC
  SPI0_Init()                                            ' Initialize SPI2 module
end sub

' DAC increments (0..4095) --> output voltage (0..Vref)
sub procedure DAC_Output(dim valueDAC as word)
dim temp as byte
  Chip_Select = 0                          ' Select DAC chip

  ' Send High Byte
  temp = word(valueDAC >> 8) and 0x0F      ' Store valueDAC[11..8] to temp[3..0]
  temp = temp or 0x30                      ' Define DAC setting, see MCP4921 datasheet
  SPI0_Write(temp)                         ' Send high byte via SPI

  ' Send Low Byte
  temp = valueDAC                          ' Store valueDAC[7..0] to temp[7..0]
  SPI0_Write(temp)                         ' Send low byte via SPI

  Chip_Select = 1                          ' Deselect DAC chip
end sub

main:

  InitMain()                               ' Perform main initialization

  value = 2048                             ' When program starts, DAC gives
                                           '   the output in the mid-range

  InitMain()                               ' Perform main initialization

  value = 2048                             ' When program starts, DAC gives
                                           '   the output in the mid-range

  while ( TRUE )                           ' Endless loop
    if ((GPIO_PORTB_DATA.B0) and (value < 4095)) then ' If RB0 button is pressed
      Inc(value)                           '   increment value
    else
      if ((GPIO_PORTB_DATA.B1) and (value > 0)) then  ' If RB1 button is pressed
        Dec(value)                         '   decrement value
      end if
    end if

    DAC_Output(value)                      ' Send value to DAC chip
    Delay_ms(1)                            ' Slow down key repeat pace
  wend
end.

STM32

program DAC

' DAC module connections
dim Chip_Select as sbit at GPIOB_ODR.B1
' End DAC module connections

dim value as word

sub procedure InitMain()
  ' Set RC6 and RC7 pins as input
  GPIO_Digital_Input(@GPIOC_BASE,  _GPIO_PINMASK_6 or _GPIO_PINMASK_7)
  GPIO_Digital_Output(@GPIOB_BASE, _GPIO_PINMASK_1)     ' Set CS# pin as Output
  Chip_Select = 1                                       ' Deselect DAC

  ' Use SPI1 module at PORTB[3:5]
  SPI1_Init_Advanced(_SPI_FPCLK_DIV4, _SPI_MASTER or _SPI_8_BIT or
                     _SPI_CLK_IDLE_LOW or _SPI_FIRST_CLK_EDGE_TRANSITION or
                     _SPI_MSB_FIRST or _SPI_SS_DISABLE or _SPI_SSM_ENABLE or _SPI_SSI_1,
                     @_GPIO_MODULE_SPI1_PB345)

  GPIO_Alternate_Function_Enable(@_GPIO_MODULE_SWJ_JTAGDISABLE)
end sub

' DAC increments (0..4095) --> output voltage (0..Vref)
sub procedure DAC_Output(dim valueDAC as word)
dim temp as byte
  Chip_Select = 0                          ' Select DAC chip

  ' Send High Byte
  temp = word(valueDAC >> 8) and 0x0F      ' Store valueDAC[11..8] to temp[3..0]
  temp = temp or 0x30                      ' Define DAC setting, see MCP4921 datasheet
  SPI1_Write(temp)                         ' Send high byte via SPI

  ' Send Low Byte
  temp = valueDAC                          ' Store valueDAC[7..0] to temp[7..0]
  SPI1_Write(temp)                         ' Send low byte via SPI

  Chip_Select = 1                          ' Deselect DAC chip
end sub

main:

  InitMain()                               ' Perform main initialization

  value = 2048                             ' When program starts, DAC gives
                                           '   the output in the mid-range

  InitMain()                               ' Perform main initialization

  value = 2048                             ' When program starts, DAC gives
                                           '   the output in the mid-range

  while ( TRUE )                           ' Endless loop
    if ((GPIOC_IDR.B7) and (value < 4095)) then ' If RC7 button is pressed
      Inc(value)                                '   increment value
    else
      if ((GPIOC_IDR.B6) and (value > 0)) then  ' If RC button is pressed
        Dec(value)                              '   decrement value
      end if
    end if

    DAC_Output(value)                      ' Send value to DAC chip
    Delay_ms(1)                            ' Slow down key repeat pace
  wend
end.
Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code