I have 2xFRDM-KEAZ128Q80, one used as SPI master, one used as SPI Slave. I want to simulate 24bit SPI communication, but I find that different power-on sequence results in different SO outputing SPI bytes' sequence.
I have no idea about what's wrong. How can I ensure the right SO output sequence?
KEA DEMO Board: FRDM-KEAZ128Q80,
Test Device: Logic Analyzer LA1010
IDE: CW11
SPI Port : master port connect to same slave port (PTG4-4, 5-5, 6-6, 7-7)
SPI Master Port:SPI1 , PTG_4_5_6_7
SPI Slave Port:SPI1 , PTG_4_5_6_7
I have uploaded the demo code to attachments.
Main SPI Master Code:
void SPIMaster_Task()
{
uint8_t i = 0;
for(i = 0; i < SPI1_TX_DATA_SIZE; i++)
{
gu8SPI1_TxBuff[i] = 0x55 + i;
}
// control cs manually
GPIO_PinClear(GPIO_PTG7); //enable cs
SPI_TransferWait(SPI1,gu8SPI1_RxBuff,gu8SPI1_TxBuff,SPI1_TX_DATA_SIZE); // size=3
GPIO_PinSet(GPIO_PTG7); //diable cs
}
Main SPI Slave Code:
void SPISlave_Task()
{
uint32_t i = 0;
gu8SPI1_TxBuff[0] = 0x55;
gu8SPI1_TxBuff[1] = 0x80;
gu8SPI1_TxBuff[2] = 0xAA;
for(i = 0; i < SPI1_TX_DATA_SIZE; i++)
{
while(!SPI_IsSPRF(SPI1)){rxIntCnt ++;};
gu8SPI1_RxBuff[i] = SPI_ReadDataReg(SPI1);
while(!SPI_IsSPTEF(SPI1)){txIntCnt ++;};
SPI_WriteDataReg(SPI1,gu8SPI1_TxBuff[i]);
}
}
Result:
Right SO sequence should be 0x55 0x80 0xAA.
1.Master Power-on first:
1) error: 0xAA 0x55 0x80
2)error: 0xAA 0x55 0x80
2. SPI poweron first
1)error: 0x80 0xAA 0x55
2)right: 0x55 0x80 0xAA
Hi Martin Zhang,
Slave code need to do the modification.
Please change it like this:
void SPISlave_Task()
{
uint32_t i = 0;
gu8SPI1_TxBuff[0] = 0x55;
gu8SPI1_TxBuff[1] = 0x80;
gu8SPI1_TxBuff[2] = 0xAA;
for(i = 0; i < SPI1_TX_DATA_SIZE; i++)
{
while(!SPI_IsSPTEF(SPI1)){txIntCnt ++;};
SPI_WriteDataReg(SPI1,gu8SPI1_TxBuff[i]);
while(!SPI_IsSPRF(SPI1)){rxIntCnt ++;};
gu8SPI1_RxBuff[i] = SPI_ReadDataReg(SPI1);
}
}
Just send the according data to the buffer at first.
It means the slave need to prepare the code, flush the FIFO with the data which you need.
Otherwise, when the master SCK input, then the slave send out fifo still not prepared, it will have the problem.
Besides, about the power on sequence, your slave must need to power on at first, otherwise, it will also have problem.
Just let the slave prepared OK, then wait the Master SCK.
Please try it again.
If you still have question about it, please kindly let me know.
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Kerry,
Thanks you.
I have solve the problems.
The problem, CS abnormal 0->1->0 , results from forgeting to connect Logic Analyzer's GND to Slave &Master board.
But wrong SPI bytes sequence stiil exists. For example, I want to send 0x55 0x80 0xAA by MISO, but it sends 0xAA 0x55 0x80 actually.
I think it relates to SPI tx buffer & data register 's rule. I find out I can load 2 bytes into TX buffer register before reading any data from RX buffer register, if I use interrupt.
A valid way is restricting the Tx and Rx sequence to TX&RX buffer.
Key Point:
1. Use Tx&Rx interrupts, do not disable.
2. Should be load 1 byte to Tx buffer for wating for Tx first.
2. When Tx finish loading 1 byte, pls to change to waiting for Rx 1byte.
e.g. Main Code
typedef enum
{
SPI_BYTES_STATUS_HEADER_BEGIN,
SPI_BYTES_STATUS_HEADER_END,
SPI_BYTES_STATUS_SECOND_BEGIN,
SPI_BYTES_STATUS_SECOND_END,
SPI_BYTES_STATUS_TAIL_BEGIN,
SPI_BYTES_STATUS_TAIL_END
}SPI_BYTES_STATUS_Type;
volatile SPI_BYTES_STATUS_Type spiBytesStatus = SPI_BYTES_STATUS_HEADER_BEGIN;
void SPISlave_CallBack()
{
if(SPI_IsSPRF(SPI1))
{// Rx full
switch(spiBytesStatus)
{
case SPI_BYTES_STATUS_HEADER_END:
gu8SPI1_RxBuff[0] = SPI_ReadDataReg(SPI1);
spiBytesStatus = SPI_BYTES_STATUS_SECOND_BEGIN;
break;
case SPI_BYTES_STATUS_SECOND_END:
gu8SPI1_RxBuff[1] = SPI_ReadDataReg(SPI1);
spiBytesStatus = SPI_BYTES_STATUS_TAIL_BEGIN;
break;
case SPI_BYTES_STATUS_TAIL_END:
gu8SPI1_RxBuff[2] = SPI_ReadDataReg(SPI1);
spiBytesStatus = SPI_BYTES_STATUS_HEADER_BEGIN;
u32SPI1_RxFrameCnt ++;
break;
}
u32SPI1_RxCnt ++;
}
if(SPI_IsSPTEF(SPI1))
{// Tx empty
switch(spiBytesStatus)
{
case SPI_BYTES_STATUS_HEADER_BEGIN:
SPI_WriteDataReg(SPI1, gu8SPI1_TxBuff[0]);
spiBytesStatus = SPI_BYTES_STATUS_HEADER_END;
break;
case SPI_BYTES_STATUS_SECOND_BEGIN:
SPI_WriteDataReg(SPI1, gu8SPI1_TxBuff[1]);
spiBytesStatus = SPI_BYTES_STATUS_SECOND_END;
break;
case SPI_BYTES_STATUS_TAIL_BEGIN:
SPI_WriteDataReg(SPI1, gu8SPI1_TxBuff[2]);
spiBytesStatus = SPI_BYTES_STATUS_TAIL_END;
u32SPI1_TxFrameCnt ++;
break;
}
u32SPI1_TxCnt ++;
}
}
main()
{
while(1)
{
//void SPISlave_Task(){
gu8SPI1_TxBuff[0] = 0x55;
gu8SPI1_TxBuff[1] = 0x80;
gu8SPI1_TxBuff[2] = 0xAA;
//}
}
}
Hi Martin,
Thanks for your updated information and the solutions sharing.
If you still have the problems about it, just let me know.
Have a great day,
Kerry
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Kerry,
Thanks for your reply.
I change the slave's code and then try to power on slave first.
It seems that it does not work. But I find the CS(SPI Enable) is innormal, that is, the CS line will change to high level about 100ns sometimes and the go back to low level. Maybe it result in my SPI Slave frame's bytes absence and then error byte sequence.
The bytes absense does not happen every time.
Do you have met the same problem?
I doubt my connection is not very reliable by 4 dupont lines between two FRDM-KEA128Q80 evbs. I do not know whether there is a better method to recognize a SPI frame head & tail on Slave. So the master will ignore the invalid frame, and there is no other effect on next SPI frame.
Result
4 different results.
1) error sequence: 0xAA 0x55 0x80
2) error: 1 byte absence, CS 0~1 keep 100ns
3) error: 2 byte absence, CS 0~1 keep 100ns/every time
4) error: 2 byte absence, CS 0~1 keep 100ns/every time