Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem configuring STM32F4 Discovery as SPI slave

Status
Not open for further replies.

flukeco

Junior Member level 1
Joined
Apr 25, 2014
Messages
16
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
180
Hi,

I'm currently trying to make SPI communication between PIC18F2580 as master and STM32F4 Discovery as slave.
The communication doesn't work, both master and slave receives 0xFF all the time.

I have it working in the opposite direction where I configure STM32F4 Discovery as master and PIC18F2580 as slave.
The working code is as follows:

STM32F4 Discovery SPI master code:
Code:
// this function initializes the SPI1 peripheral
void init_SPI1(void){
	
	GPIO_InitTypeDef GPIO_InitStruct;
	SPI_InitTypeDef SPI_InitStruct;
	
	// enable clock for used IO pins
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	/* configure pins used by SPI1
	 * PA5 = SCK
	 * PA6 = MISO
	 * PA7 = MOSI
	 */
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	// connect SPI1 pins to SPI alternate function
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

	// enable clock for used IO pins
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
	
	// enable peripheral clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	
	/* configure SPI1
	 * CPOL = 1 --> clock is high when idle
	 * CPHA = 0 --> data is sampled at the second edge
	 */
	SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
	SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
	SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide
	SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;        // clock is high when idle
	SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;      // data sampled at second edge
	SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; // set the NSS management to internal and pull internal NSS high
	SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI frequency is APB2 frequency / 4
	SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
	SPI_Init(SPI1, &SPI_InitStruct); 
	
	SPI_Cmd(SPI1, ENABLE); // enable SPI1
}

/* This funtion is used to transmit and receive data 
 * with SPI1
 * 			data --> data to be transmitted
 * 			returns received value
 */
uint8_t SPI1_send(uint8_t data){

	SPI1->DR = data; // write data to be transmitted to the SPI data register
	while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete
	while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete
	while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore
	return SPI1->DR; // return received data from SPI data register
}

int main(void) {
	init_SPI1();
	while(1){
		SPI1_send(0x00);  // transmit data
	}
}

PIC18F2580 slave code:
Code:
/*********************************************************************
*
*                             Defines
*
*********************************************************************/
#define _MASTER_MODE     0
#define _SLAVE_MODE      1

#define _SMP            0    /*  0 = Input data sampled at middle of data output time (SMP must be cleared in slave mode) */
#define _CKE            0     /* 0 = Transmit occurs on transition from idle to active clock state */
#define _CKP            1     /* 1 = Idle state for clock is a high level */
#define _SSPM_MASTER    0b0000     /* 0000 = Master mode, clock = Fosc/4 */
#define _SSPM_SLAVE     0b0101      /*  0101 = Slave mode, clock = SCK pin, SS pin disabled (can be used as I/O pin) */

void SPI_init(unsigned char mode) {
    TRISA = 0x00;               /* set all port A pins as output pins */
    ADCON1 = 0x0F;              /* set all port A pins, including SS (RA5), as digital I/O */

    if (mode == _MASTER_MODE) {
    TRISC = 0b00010000;         /* Set SCK pin (RC3) as output
                                 * SDI pin (RC4) as input
                                 * SDO pin (RC5) as output */
    } else {
    TRISC = 0b00011000;         /* Set SCK pin (RC3) as input
                                 * SDI pin (RC4) as input
                                 * SDO pin (RC5) as output */
    }

    SSPSTAT = 0b00000000;       /* Initialize SSPSTAT register to POR state */
    SSPSTATbits.SMP = _SMP;     /* Configure sample bit */
    SSPSTATbits.CKE = _CKE;     /* Configure clock select bit */

    SSPCON1 = 0b00000000;       /* Initialize SSPCON1 register to POR state */
    SSPCON1bits.CKP = _CKP;     /* Configure clock polarity select bit */
    SSPCON1bits.SSPEN = 1;      /* Enable SPI (set SCK, SDO, SDI, and SS as serial port pins)*/

    if (mode == _MASTER_MODE)
        SSPCON1bits.SSPM = _SSPM_MASTER;    /* Configure sync mode bits for master */
    else
        SSPCON1bits.SSPM = _SSPM_SLAVE;     /* Configure sync mode bits for slave */
}

unsigned char SPI_send(unsigned char data) {
    unsigned char TempVar;

    TempVar = SSPBUF;           /* Clears BF */
    PIR1bits.SSPIF = 0;         /* Clear interrupt flag */
    SSPCON1bits.WCOL = 0;	/* Clear any previous write collision */
    SSPBUF = data;              /* clock out data */
    while(!PIR1bits.SSPIF);     /* wait until transmission completed */
    PIR1bits.SSPIF = 0;         /* clear interrupt flag bit */
    return (SSPBUF);
}

int main(void) {
    SPI_init(_SLAVE_MODE);

    while (1) {
        SPI_send('A');
    }

    return (EXIT_SUCCESS);
}

The above code work fine. STM32F4 discovery (master) send 0x00 and receive 'A' while PIC18F2580 send 'A' and receive 0x00.

However, I need STM32F4 to be slave and PIC18F2580 to be master. I modify above code as follow:

Modify 1 line for STM32F4 Discovery code
Code:
              .....
	SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;     // transmit in slave mode
              .....

And modify the call to SPI_init() function to be initialized as master
Code:
    .....
    SPI_init(_MASTER_MODE);
    .....

As I mention earlier, this doesn't work as both slave and master receive 0xFF.
I don't have access to oscilloscope or logic analyzer, so the best I can do is to set breakpoint as watch the values while debugging.

I doubt that this maybe because PIC18 run at slower CPU speed (40 Mhz) while STM32F4 runs at 168 Mhz.
But why does it work in one way (STM32 as master) and not another (PIC18 as master)?
Or it is the code that cause the problem?

If you spot something wrong in the code or the concepts, please let me know.

Thank you in advance for your suggestions, any help will be highly appreciated.

Best Regards,
Pat
 

flukeco

Junior Member level 1
Joined
Apr 25, 2014
Messages
16
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
180
Anyone? please help.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top