2009-07-07 10:41 PM
SPI slave mode malfunctioning
2011-05-17 06:03 AM
Hi,
We are using STM8S208 SPI in slave mode. Configuration as follows: - Full Duplex - MSBFirst - CPOL: 0 - CPHA: 1 SPI configuration code:Code:
void SPI_Init(void) { /* Deinitialize the SPI peripheral registers to their default reset values */ SPI->CR1 = SPI_CR1_RESET_VALUE; SPI->CR2 = SPI_CR2_RESET_VALUE; SPI->ICR = SPI_ICR_RESET_VALUE; SPI->SR = SPI_SR_RESET_VALUE; SPI->CRCPR = SPI_CRCPR_RESET_VALUE; /* CLK_PCKENR1 is configured for gate clock for SPI in hw_Init() */ /* Clock polarity 0 when idle */ SPI->CR1 |= (u8)(SPI_CLOCKPOLARITY_LOW); /* Clock phase – the second clock transition is the first data capture edge */ SPI->CR1 |= (u8)(SPI_CLOCKPHASE_2EDGE); /* Slave mode configuration */ SPI->CR1 |= (u8)(SPI_MODE_SLAVE); /* Frame format: MSB first */ SPI->CR1 |= (u8)(SPI_FIRSTBIT_MSB); /* RX buffer not empty interrupt enable */ SPI->ICR |= (u8)(RX_BUF_NE_INT); } On the master side, we have microchip's board. The data(all input waveforms for MOSI, CLK & CS) send by the master is verified on a CRO for its autheticity & timing. As the STM8S ref manual says, the master is configured with the same settings for clock polarity and phase as done on the slave. The STM8S SPI ISR is as follows:Code:
@near @interrupt void SPI_IRQHandler(void) { if(SPI->SR & SPI_SR_RXNE) /* Check if Receive buffer not empty flag is set */ { switch(SPI->DR) { case 0x12 : GPIOH->ODR ^= GPIO_PIN_3; /* Toggle LED1 */ break; case 0x24 : GPIOH->ODR ^= GPIO_PIN_2; /* Toggle LED2 */ break; case 0x36 : GPIOH->ODR ^= GPIO_PIN_1; /* Toggle LED3 */ break; case 0x48 : GPIOH->ODR ^= GPIO_PIN_0; /* Toggle LED4 */ break; } There is a peculiar situation here. With these 4 databytes sent sequentially by the master, all LEDs glow less intermittently. However if the databytes sent are 0x24, 0xAA, 0xFF & 0x55, then only the first databyte is recognized and corresponding LED glows. All the other databytes are recognized after long durations, infact 0xFF is never recognized. Thus other LEDs don't glow often. When checked using debugger, we observe the OVR flag(& sometimes the BSY flag) is continously on. We tried differently low frequecies from SPI master(500 KHZ and 1MHz) and also put delays between successive data bytes. But this doesn't make much differnce. Please let us know what are we missing? Is there anything else that we need to take care of? Regards, -SU2011-05-17 06:03 AM
Hi Sandeep,
In full duplex communication the master impose the clock frequency. Code behavior: In the SPI slave interrupt you have some steps (switch loop) that should be done in the main file because when the SPI Master send data in continuous the SPI slave receive the first data byte in the SPI data register and then execute the interrupt, when the slave execute the interrupt an other data received in the data register but not read the OVR flag is set and the slave stop receiving data until clearing the OVR flag. Solution1: Use global variable in your code and keep only following in interrupt vector: @near @interrupt void SPI_IRQHandler(void) { data_received = SPI->DR; } Solution2: Use GPIO to synchronize between master and slave: after receiving data byte the slave set I/O to indicate that it received the data in the other side the master whiting on the I/O before sending the next byte Solution3: Clear the OVR flag when detecting an overrun interrupt; in this case you lost data Regards mozra