Hi everyone,
I'm writing because I encountered a very strange problem regarding the MISO pin of an SPI communication.
I have a MKE06Z128 set up as an SPI slave and I need to do the following:
The strange thing is that as I tell the driver to send my data the result is always a loopback of the received message.
The code below is the one I used inside the interrupt, both RxFull and TxEmpty interrupts are enabled.
void SPI0_IRQHandler(void) {
uint8_t rx_data = 0x00;
uint8_t tx_data = 0x00;
if (SPI_GetStatusFlags(SPI0) & kSPI_RxBufferFullFlag) {
rx_data = SPI_ReadData(SPI0);
spi_data_buff_rx[spi_data_ptr_rx] = rx_data;
switch (SPI_S_State) {
case SPI_S_IDLE:
tx_data = rx_data; // start character
if ((rx_data == SPI_S_START_CHAR) && (spi_execute_comm == 0)) {
SPI_S_State = SPI_S_SEND_COMM;
}
break;
case SPI_S_SEND_COMM:
spi_command = rx_data;
tx_data = rx_data;
spi_data_cnt = SPI_S_DATA_DIM;
spi_data_type = SPI_S_RetrieveData(spi_command, spi_data);
SPI_S_State = SPI_S_SEND_DATA;
break;
case SPI_S_SEND_DATA:
if (spi_command & SPI_S_WRITE_MASK) {
spi_data[SPI_S_DATA_DIM - spi_data_cnt] = rx_data;
}
switch(spi_data_type) {
case 1:
tx_data = rx_data;
break;
case 2:
tx_data = spi_data[SPI_S_DATA_DIM - spi_data_cnt];
break;
case 0:
default:
tx_data = 0;
break;
}
spi_data_cnt--;
if (spi_data_cnt == 0) {
SPI_S_State = SPI_S_SEND_TERM1;
}
break;
case SPI_S_SEND_TERM1:
tx_data = SPI_S_TERM1_CHAR;
if (rx_data != SPI_S_TERM2_CHAR) {
spi_command = 0x00;
SPI_S_State = SPI_S_IDLE;
} else {
SPI_S_State = SPI_S_SEND_TERM2;
}
break;
case SPI_S_SEND_TERM2:
tx_data = SPI_S_TERM2_CHAR;
if (rx_data != SPI_S_TERM1_CHAR) {
spi_command = 0x00;
} else {
if (spi_command & SPI_S_WRITE_MASK) {
spi_execute_comm = 1;
}
}
SPI_S_State = SPI_S_IDLE;
break;
case SPI_S_MAX_STATES:
default:
SPI_S_State = SPI_S_IDLE;
break;
}
SPI_WriteData(SPI0, (uint16_t)tx_data);
spi_data_buff_tx[spi_data_ptr_rx] = tx_data;
if (SPI_S_State == SPI_S_IDLE) {
spi_data_ptr_rx = 0;
} else {
spi_data_ptr_rx++;
}
}
if (SPI_GetStatusFlags(SPI0) & kSPI_TxBufferEmptyFlag) {
SPI_WriteData(SPI0, (uint16_t)0xA5);
}
}
The following data is the one I see from the master side
[TX] - 63 01 11 12 13 14 15 16 17 18 19 1A 1B 1C 23 21 00
[RX] - A5 63 01 11 12 13 14 15 16 17 18 19 1A 1B 1C 23 21
I also checked on the oscilloscope the correct behavior of the master and slave devices and it is all set up correctly on the waveform side.
I cannot fint the source of the problem, I see that the register used for the communication is the same for Tx and Rx, but it is overwritten to transmit different data.
I'm using the SDK 2.7.0 with MCUXpresso.
Any suggestions?
Thank you in advance.
Best Regards,
Tommaso
I know this post is old and probably irrelevant but i will try to answer anyways.
void SPI0_IRQHandler(void) {
uint8_t rx_data = 0x00;
uint8_t tx_data = 0x00;
if (SPI_GetStatusFlags(SPI0) & kSPI_RxBufferFullFlag) {
rx_data = SPI_ReadData(SPI0);
[...]
switch (SPI_S_State) {
case SPI_S_IDLE:
[...]
tx_data = rx_data; // start character
[...]
break;
[...]
case SPI_S_SEND_COMM:
[...]
tx_data = rx_data;
[...]
}
Through your whole rxBufferFull Routine you are constantly setting txdata to rxdata. And at the end you call the following:
SPI_WriteData(SPI0, (uint16_t)tx_data);
This means, since RxbufferFull and TxBufferEmpty Flag are set at the same time (after 8 shifts) and you first check the RxBuffer and fill the TxBuffer at the end of the if-case. Your TxBuffer handling routine is never executed. (After SPI_WriteData(SPI0, (uint16_t)tx_data); --> TxBufferEmpty Flag is 0)
And since you fill your TxBuffer at the end of the Rx_ISR Routine with txdata = rxdata. You repeat the transmission back to the Master.
Your first byte is 0xA5 because the first time the interrupt is called is before the communication and at this point ONLY the TXBufferFull Flag is set, the RxBuffer ISR is not executed and the TxBuffer is filled with 0xA5.
FRDM-KE06 sdk has the SPI master and slave code, do you test that code, whether it works OK on your side or not?
When you want to send the data in the SPI slave, you need to write the related data to the Transmit FIFO:
void SPI_SLAVE_IRQHandler(void)
{
if ((SPI_GetStatusFlags(EXAMPLE_SPI_SLAVE) & kSPI_RxBufferFullFlag) && (rxIndex > 0U))
{
destBuff[BUFFER_SIZE - rxIndex] = SPI_ReadData(EXAMPLE_SPI_SLAVE);
rxIndex--;
}
if ((SPI_GetStatusFlags(EXAMPLE_SPI_SLAVE) & kSPI_TxBufferEmptyFlag) && (txIndex > 0U))
{
SPI_WriteData(EXAMPLE_SPI_SLAVE, (uint16_t)(srcBuff[BUFFER_SIZE - txIndex]));
txIndex--;
}
if ((rxIndex == 0U) && (txIndex == 0U))
{
slaveFinished = true;
SPI_DisableInterrupts(EXAMPLE_SPI_SLAVE, kSPI_RxFullAndModfInterruptEnable | kSPI_TxEmptyInterruptEnable);
}
SDK_ISR_EXIT_BARRIER;
}
i suggest you test the official SDK code:SDK_2.8.0_FRDM-KE06Z\boards\frdmke06z\driver_examples\spi\interrupt_b2b\slave
at first, which can be downloaded from this link:
Welcome | MCUXpresso SDK Builder
Wish it helps you!
If you still have questions about it, pelase kindly let me know.
Best Regards,
Kerry
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------