FRDM-KL25Z SPI using KSDK1.2.0 for MCP23S17

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FRDM-KL25Z SPI using KSDK1.2.0 for MCP23S17

Jump to solution
1,332 Views
nelsonlobo
Contributor II

Hi,

 

Ive been trying to understand the SPI polling technique from FRDM-KL25Z(master) with my PIC18F46K22(slave). This worked flawlessly, I could detect all the packets sent over this channel. Now I thought of using my MCP23S17(I/O Expander) with the FRDM-KL25Z. Since ive already tried sending the same instructions on PIC18F and it worked well there I was assuming it would work here as well. But there was absolutely no response from the MCP module. Just to verify ive bricked the module or not i checked with PIC18F and yet again it worked just fine. Ive attached the code its a modification of the existing SPI Looping technique in Master mode available in KSDK1.2.0 examples folder.

C:\Freescale\KSDK_1.2.0\examples\frdmkl25z\driver_examples\spi\spi_polling

 

 

My code would read as follows:

 

#include <string.h>

#include "fsl_spi_master_driver.h"

#include "fsl_clock_manager.h"

#include "fsl_debug_console.h"

#include "board.h"

#include <stdio.h>

 

// MCP23S17 SPI Slave Device

#define SPI_SLAVE_ID    0x40

#define SPI_SLAVE_ADDR  0x07      // A2=0,A1=0,A0=0

#define SPI_SLAVE_WRITE 0x00

#define SPI_SLAVE_READ  0x01

 

// MCP23S17 Registers Definition for BANK=0 (default)

#define IODIRA 0x00

#define IODIRB 0x10

#define IOCONA 0x0A

#define GPPUA  0x06

#define GPPUB  0x16

#define GPIOA_Exp  0x09

#define GPIOB_Exp  0x19

 

/*******************************************************************************

* Definitions

******************************************************************************/

#define SPI_MASTER_INSTANCE          (0)                 /*! User change define to choose SPI instance */

#define TRANSFER_SIZE               (64)

#define TRANSFER_BAUDRATE           (500000U)           /*! Transfer baudrate - 500k */

#define MASTER_TRANSFER_TIMEOUT     (5000U)             /*! Transfer timeout of master - 5s */

 

 

 

/* Setup the board as a spi master */

int main (void)

{

    uint32_t spiSourceClock;

    SPI_Type * spiBaseAddr = g_spiBase[SPI_MASTER_INSTANCE];;

 

 

    /* init the hardware, this also sets up up the SPI pins for each specific SoC */

    hardware_init();

    OSA_Init();

 

 

    // Enable clock for SPI

    CLOCK_SYS_EnableSpiClock(SPI_MASTER_INSTANCE);

 

    // configure the run-time state struct with the source clock value

    spiSourceClock = CLOCK_SYS_GetSpiFreq(SPI_MASTER_INSTANCE);

 

 

    // Reset the SPI module to it's default state, which includes SPI disabled

    SPI_HAL_Init(spiBaseAddr);

 

    // Set SPI to master mode

    SPI_HAL_SetMasterSlave(spiBaseAddr, kSpiMaster);

 

    // Set slave select to GPIO output mode

    SPI_HAL_SetSlaveSelectOutputMode(spiBaseAddr, kSpiSlaveSelect_AsGpio); /*Change introduced by me since the data need to be sent 3bytes at a time, i.e. 1)SlaveID, 2)Register,3)value*/

 

    // Set the SPI pin mode to normal mode

    SPI_HAL_SetPinMode(spiBaseAddr, kSpiPinMode_Normal);

 

    Usr_SPI0_EN;     //Defined  and configured in gpio_pins.h,pin_mux.c and board.h

    Usr_SPI_ON;

 

 

    // SPI system Enable

    SPI_HAL_Enable(spiBaseAddr);

 

 

    // Configure the bus to access the provided device.

    SPI_HAL_SetBaud(spiBaseAddr, TRANSFER_BAUDRATE, spiSourceClock);

 

 

    // Setup format as same as slave

    SPI_HAL_SetDataFormat(spiBaseAddr, kSpiClockPolarity_ActiveHigh, kSpiClockPhase_FirstEdge, kSpiMsbFirst);

 

 

        // Disable module to clear the shift register

        SPI_HAL_Disable(spiBaseAddr);

        SPI_HAL_Enable(spiBaseAddr);

 

     //IOCONA register is set to 0x88

        Usr_SPI_OFF;

        SPI_HAL_WriteDataBlocking(spiBaseAddr, SPI_SLAVE_ID);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, IOCONA);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, 0x88); //Tried 0x80 as well for Address mode disbaled

        Usr_SPI_ON;

 

     //PORTA of IO-expander is set to Output mode

        Usr_SPI_OFF;

        SPI_HAL_WriteDataBlocking(spiBaseAddr,SPI_SLAVE_ID);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, IODIRA);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, 0x00);

        Usr_SPI_ON;

    

     //Set all pins of PORTA high

        Usr_SPI_OFF;

        SPI_HAL_WriteDataBlocking(spiBaseAddr, SPI_SLAVE_ID);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, GPIOA_Exp);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, 0xFF);

        Usr_SPI_ON;

 

    while(1)

    {

     }

}

 

/*******************************************************************************

* EOF

******************************************************************************/

 

Regards,

Nelson Lobo

Original Attachment has been moved to: spi_polling-.zip

Labels (1)
0 Kudos
1 Solution
903 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Dear Nelson,

Regarding your second question, If you use the SPI module of Kl25 as master and want to transfer multiple bytes using the same function so the CS pin toggles once for all the bytes, you can not use the /SS pin of master SPI to generate the output signal to select the slave SPI automatically. I suggest you connect any GPIO pin(even the /SS pin of KL25 can be configured as GPIO output function) of Kl25 to the /SS pin of slave SPI, while the SPI of KL25 is master. Before you transfer the first byte, you can clear the GPIO, then write the first byte to SPI data register, poll the SPTEF bit in SPIx_S, if the bit is set, write the second byte, then poll the SPTEF bit in SPIx_S, ...when the required byte has transfered, set the GPIO, and have a delay. In the process, you have to set the CPHA  bit so that the MISO bit is valid by the edge of SPSCK signal.

Regarding your first question, pls check if there are signals for the SPSCK, MOSI,MISO and /SS, if there is issue, pls check the SPI register in the debugger of the tools. I am not clear what your issue is now.

Hope it can help you.

BR

Xiangjun Rong

View solution in original post

3 Replies
903 Views
nelsonlobo
Contributor II

Hi,

In the attachment please do the following for pin_mux.c:

      PORT_HAL_SetMuxMode(PORTC,4u,kPortMuxAsGpio); /* PCS0 */

//      PORT_HAL_SetMuxMode(PORTC,4u,kPortMuxAlt2); /* PCS0 */

Since we will be using it as GPIO.

Also is there any way i could send multiple bytes using the same function so the CS pin toggles once for all the bytes, just as my case for MCP23S17.

If there's a better alternative to control this IO expander, Im all ears :smileywink:.

Regards,

Nelson Lobo

0 Kudos
904 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Dear Nelson,

Regarding your second question, If you use the SPI module of Kl25 as master and want to transfer multiple bytes using the same function so the CS pin toggles once for all the bytes, you can not use the /SS pin of master SPI to generate the output signal to select the slave SPI automatically. I suggest you connect any GPIO pin(even the /SS pin of KL25 can be configured as GPIO output function) of Kl25 to the /SS pin of slave SPI, while the SPI of KL25 is master. Before you transfer the first byte, you can clear the GPIO, then write the first byte to SPI data register, poll the SPTEF bit in SPIx_S, if the bit is set, write the second byte, then poll the SPTEF bit in SPIx_S, ...when the required byte has transfered, set the GPIO, and have a delay. In the process, you have to set the CPHA  bit so that the MISO bit is valid by the edge of SPSCK signal.

Regarding your first question, pls check if there are signals for the SPSCK, MOSI,MISO and /SS, if there is issue, pls check the SPI register in the debugger of the tools. I am not clear what your issue is now.

Hope it can help you.

BR

Xiangjun Rong

903 Views
nelsonlobo
Contributor II

Hi xiangjun.rong,

Based on your comments i did use delays in the appropriate  instance and now the code works just fine.

Here is the code:

#include <string.h>

#include "fsl_spi_master_driver.h"

#include "fsl_clock_manager.h"

#include "fsl_debug_console.h"

#include "board.h"

#include <stdio.h>

// MCP23S17 SPI Slave Device

#define SPI_SLAVE_ID    0x40

#define SPI_SLAVE_ADDR  0x07      // A2=0,A1=0,A0=0

#define SPI_SLAVE_WRITE 0x00

#define SPI_SLAVE_READ  0x01

// MCP23S17 Registers Definition for BANK=0 (default)

#define IODIRA 0x00

#define IODIRB 0x10

#define IOCONA 0x0A

#define GPPUA  0x06

#define GPPUB  0x16

#define GPIOA_Exp  0x09

#define GPIOB_Exp  0x19

/*******************************************************************************

* Definitions

******************************************************************************/

#define SPI_MASTER_INSTANCE          (0)                 /*! User change define to choose SPI instance */

#define TRANSFER_SIZE               (64)

#define TRANSFER_BAUDRATE           (1000000U)           /*! Transfer baudrate - 500k */

#define MASTER_TRANSFER_TIMEOUT     (5000U)             /*! Transfer timeout of master - 5s */

void wait_tcy(unsigned int wait);

/* Setup the board as a spi master */

int main (void)

{

    uint32_t spiSourceClock;

    SPI_Type * spiBaseAddr = g_spiBase[SPI_MASTER_INSTANCE];;

    /* init the hardware, this also sets up up the SPI pins for each specific SoC */

    hardware_init();

    OSA_Init();

    // Enable clock for SPI

    CLOCK_SYS_EnableSpiClock(SPI_MASTER_INSTANCE);

    // configure the run-time state struct with the source clock value

    spiSourceClock = CLOCK_SYS_GetSpiFreq(SPI_MASTER_INSTANCE);

    // Reset the SPI module to it's default state, which includes SPI disabled

    SPI_HAL_Init(spiBaseAddr);

    // Set SPI to master mode

    SPI_HAL_SetMasterSlave(spiBaseAddr, kSpiMaster);

    // Set slave select to GPIO output mode

    SPI_HAL_SetSlaveSelectOutputMode(spiBaseAddr, kSpiSlaveSelect_AsGpio); /*Change introduced by me since the data need to be sent 3bytes at a time, i.e. 1)SlaveID, 2)Register,3)value*/

    // Set the SPI pin mode to normal mode

    SPI_HAL_SetPinMode(spiBaseAddr, kSpiPinMode_Normal);

    Usr_SPI0_EN;     //Defined  and configured in gpio_pins.h,pin_mux.c and board.h

    Usr_SPI_OFF;

    // SPI system Enable

    SPI_HAL_Enable(spiBaseAddr);

    // Configure the bus to access the provided device.

    SPI_HAL_SetBaud(spiBaseAddr, TRANSFER_BAUDRATE, spiSourceClock);

    // Setup format as same as slave

    SPI_HAL_SetDataFormat(spiBaseAddr, kSpiClockPolarity_ActiveHigh, kSpiClockPhase_FirstEdge, kSpiMsbFirst);

        // Disable module to clear the shift register

        SPI_HAL_Disable(spiBaseAddr);

        SPI_HAL_Enable(spiBaseAddr);

     //IOCONA register is set to 0x88

        Usr_SPI_ON;

        SPI_HAL_WriteDataBlocking(spiBaseAddr, SPI_SLAVE_ID);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, IOCONA);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, 0x88); //Tried 0x80 as well for Address mode disbaled

        OSA_TimeDelay(1);     //wait for 1ms

        Usr_SPI_OFF;

     //PORTA of IO-expander is set to Output mode

        Usr_SPI_ON;

        SPI_HAL_WriteDataBlocking(spiBaseAddr,SPI_SLAVE_ID);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, IODIRA);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, 0x00);

        OSA_TimeDelay(1);     //wait for 1ms

        Usr_SPI_OFF;

     //Set all pins of PORTA high

        Usr_SPI_ON;

        SPI_HAL_WriteDataBlocking(spiBaseAddr, SPI_SLAVE_ID);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, GPIOA_Exp);

        SPI_HAL_WriteDataBlocking(spiBaseAddr, 0x05);

        OSA_TimeDelay(1);     //wait for 1ms

        Usr_SPI_OFF;

    while(1)

    {

        //Set all pins of PORTA high

           Usr_SPI_ON;

           SPI_HAL_WriteDataBlocking(spiBaseAddr, SPI_SLAVE_ID);

           SPI_HAL_WriteDataBlocking(spiBaseAddr, GPIOA_Exp);

           SPI_HAL_WriteDataBlocking(spiBaseAddr, 0x05);

           OSA_TimeDelay(1);     //wait for 1ms

           Usr_SPI_OFF;

           OSA_TimeDelay(1000);     //wait for 1sec

    //Set all pins of PORTA high

   Usr_SPI_ON;

   SPI_HAL_WriteDataBlocking(spiBaseAddr, SPI_SLAVE_ID);

   SPI_HAL_WriteDataBlocking(spiBaseAddr, GPIOA_Exp);

   SPI_HAL_WriteDataBlocking(spiBaseAddr, 0x00);

   OSA_TimeDelay(1);     //wait for 1ms

   Usr_SPI_OFF;

   OSA_TimeDelay(1000);     //wait for 1sec

    }

}

void wait_tcy(unsigned int wait)

{

  do

  {

  ;

  }while(--wait!=0);

}

/*******************************************************************************

* EOF

******************************************************************************/

I did try waiting for 100 time cycles instead of 1ms which according to the datasheet should be sufficient but doesn't work always,

This isn't the case in PIC18f  controllers wherein you could toggle the GPIO to disable SPI immediately. Am i missing something???

Regards,

Nelson Lobo

0 Kudos