인피니언 MCU인 TC275를 이용하여 SPI 예제코드를 포팅해서
동작해 보도록 하겠습니다.
지금 쓰는 글은 2편입니다 ㅎ
따라서 1편글을 읽고 오셔야 이해가 되실 겁니다.
1편글의 링크를 아래와 같이 전달 드립니다.
https://embeddedchallenge.tistory.com/444
이제 Slave 쪽을 포팅할게요!
IFX_INTERRUPT(SPI1_TxHandler, 0, ISR_PRIORITY_QSPI1_TX);
IFX_INTERRUPT(SPI1_RxHandler, 0, ISR_PRIORITY_QSPI1_RX);
IFX_INTERRUPT(SPI1_ErHandler, 0, ISR_PRIORITY_QSPI1_ER);
void SPI1_TxHandler(void)
{
IfxCpu_enableInterrupts();
IfxQspi_SpiSlave_isrTransmit(&g_QspiCpu.drivers.spiSlave);
}
void SPI1_RxHandler(void)
{
IfxCpu_enableInterrupts();
IfxQspi_SpiSlave_isrReceive(&g_QspiCpu.drivers.spiSlave);
}
void SPI1_ErHandler(void)
{
IfxCpu_enableInterrupts();
IfxQspi_SpiSlave_isrError(&g_QspiCpu.drivers.spiSlave);
}
static void Driver_Spi1_Init(void)
{
IfxQspi_SpiSlave_Config spiSlaveConfig;
int i;
/* create module config */
IfxQspi_SpiSlave_initModuleConfig(&spiSlaveConfig, &MODULE_QSPI1);
/* set the maximum baudrate */
spiSlaveConfig.base.maximumBaudrate = 10000000;
/* ISR priorities and interrupt target */
spiSlaveConfig.base.txPriority = ISR_PRIORITY_QSPI1_TX;
spiSlaveConfig.base.rxPriority = ISR_PRIORITY_QSPI1_RX;
spiSlaveConfig.base.erPriority = ISR_PRIORITY_QSPI1_ER;
spiSlaveConfig.base.isrProvider = (IfxSrc_Tos)IfxCpu_getCoreIndex();
/* pin configuration */
const IfxQspi_SpiSlave_Pins slavePins = {&IfxQspi1_SCLKA_P10_2_IN, /* SCLK Pin */
IfxPort_InputMode_pullDown,
&IfxQspi1_MTSRA_P10_3_IN, IfxPort_InputMode_pullDown, /* MTSR Pin */
&IfxQspi1_MRST_P10_1_OUT, IfxPort_OutputMode_pushPull, /* MRST Pin */
&IfxQspi1_SLSIA_P11_10_IN, IfxPort_InputMode_pullDown, /* SLSI Pin */
IfxPort_PadDriver_cmosAutomotiveSpeed3 /* pad driver mode */
};
spiSlaveConfig.pins = &slavePins;
/* initialize module */
IfxQspi_SpiSlave_initModule(&g_QspiCpu.drivers.spiSlave, &spiSlaveConfig);
/* init tx buffer area */
for (i = 0; i < SPI_BUFFER_SIZE; i++)
{
g_QspiCpu.qspiBuffer.spi1TxBuffer[i] = (uint8)(i + 100);
g_QspiCpu.qspiBuffer.spi1RxBuffer[i] = (uint8)(0);
}
}
void Driver_Spi_Init(void)
{
/* disable interrupts */
boolean interruptState = IfxCpu_disableInterrupts();
Driver_Spi1_Init();
/* enable interrupts again */
IfxCpu_restoreInterrupts(interruptState);
}
void Driver_Spi_SlaveTest(void)
{
uint32 size = SPI_BUFFER_SIZE;
/* Slave transfer */
while (IfxQspi_SpiSlave_getStatus(&g_QspiCpu.drivers.spiSlave) == SpiIf_Status_busy)
{}
IfxQspi_SpiSlave_exchange(&g_QspiCpu.drivers.spiSlave, &g_QspiCpu.qspiBuffer.spi1TxBuffer[0],
&g_QspiCpu.qspiBuffer.spi1RxBuffer[0], SPI_BUFFER_SIZE);
#if 0
/* wait until slave received all data */
while (IfxQspi_SpiSlave_getStatus(&g_QspiCpu.drivers.spiSlave) == SpiIf_Status_busy)
{}
#endif
}
Slave 입장에서는
Clock 부분이 SCLK의 핀은 input입니다.
이 SCLK는 Master MCU가 만들어 주어서 Slave쪽으로 주기 때문입니다.
CS핀도 역시 Master MCU가 만들어 주기 때문에 Input입니다.
MOSI(MTSR)핀도 Input이고
오직
MISO(MRST)핀만이 Output입니다.
해당 내용은 기본적인 내용이며 아래 글에서 확인하실 수 있습니다.
https://embeddedchallenge.tistory.com/58
그렇다면 Master SPI 설정과 정 반대라는 사실을 아실 수 있을 것입니다.
&IfxQspi1_SCLKA_P10_2_IN, /* SCLK Pin */
&IfxQspi1_MTSRA_P10_3_IN, IfxPort_InputMode_pullDown, /* MTSR Pin */
&IfxQspi1_MRST_P10_1_OUT, IfxPort_OutputMode_pushPull, /* MRST Pin */
&IfxQspi1_SLSIA_P11_10_IN, IfxPort_InputMode_pullDown, /* SLSI Pin */
그리고 Test Code는 아래와 같이 만들었습니다.
void Driver_Spi_SlaveTest(void)
{
uint32 size = SPI_BUFFER_SIZE;
/* Slave transfer */
while (IfxQspi_SpiSlave_getStatus(&g_QspiCpu.drivers.spiSlave) == SpiIf_Status_busy)
{}
IfxQspi_SpiSlave_exchange(&g_QspiCpu.drivers.spiSlave, &g_QspiCpu.qspiBuffer.spi1TxBuffer[0],
&g_QspiCpu.qspiBuffer.spi1RxBuffer[0], SPI_BUFFER_SIZE);
}
위의 코드는 Slave가 보내려는 값을
미리 Tx 버퍼에 채우고 있는 것을 확인하실 수 있습니다.
그리고 Master가 SCK라인을 통해서 Clock을 날리면
그 Clock에 맞추어(동기화되어) 지금 채워진 버퍼를
그대로 날리는 구조로 되어 있다는 것을 알 수 있습니다.
이제 두개의 보드를 한번 연결해 보도록 하게요!!
위의 위치한 보드가 Slave 입니다.
아래 위치한 보드가 Master 입니다.
두개의 보드가 SPI모듈핀을 통해서 연결이 되어 있습니다.
이제 Master에서 SCK라인을 통해 Clock을 날리게 되면
Slave는 아래와 같이 값을 Master MCU쪽으로 주게될 것입니다.
/* init tx buffer area */
for (i = 0; i < SPI_BUFFER_SIZE; i++)
{
g_QspiCpu.qspiBuffer.spi1TxBuffer[i] = (uint8)(i + 100);
g_QspiCpu.qspiBuffer.spi1RxBuffer[i] = (uint8)(0);
}
TxBuffer는 총 10개의 값을 날리고 있습니다.
100, 101 ... 109
이것을 16진수로 변경하면
0x64 ... 0x6D입니다.
그러면 한번 Logic Analyzer를 이용해서 계측을 해보도록 하겠습니다.
역시 예상대로 동작하는 것을 확인 할 수 있습니다.
채널3번이 Slave에서 Master쪽으로 보내는 데이터 입니다.
Slave에 채워진 버퍼가 SCK를 받으면 바로 뱉어내고 있는 것을 볼 수 있습니다.
이제 한번 디버거를 이용해서 확인해 보도록 하겠습니다.
Slave도 Master가 보낸 데이터를 잘 받은 것을 확인 할 수 있습니다.
현재 작업한 코드는 아래 링크에서 다운로드 가능하니 참고해 주세요.
https://cafe.naver.com/binaryembedded/141
실제로 SPI는 MCU와 MCU끼리 통신을 하는데 사용하지는 않습니다.
MCU와 IC끼리 통신을 하는데 사용하는데
그 예제를 아래와 같이 구현하여 동작시켜 보았으니 참고해 보시면 좋을 것 같습니다.
https://embeddedchallenge.tistory.com/442
https://embeddedchallenge.tistory.com/443
이상으로 금일 포스팅을 마치도록 하겠습니다.
'Embedded SW > Embedded SW Introduction' 카테고리의 다른 글
CAN 구현 및 동작 수행 1편 (TC275 MCU 예제코드 포팅) (1) | 2022.09.13 |
---|---|
SPI를 설계할때 꼭 알아야할 핵심 사항 정리(TC275 MCU) (0) | 2022.09.12 |
SPI 예제 코드를 포팅, 동작 확인 1편 (T275 인피니언 MCU) (0) | 2022.09.12 |
Digital-to-Analog Converter (Pmod DA4)를 SPI를 이용하여 동작 2편 (TC275 MCU) (0) | 2022.09.11 |
Digital-to-Analog Converter (Pmod DA4)를 SPI를 이용하여 동작 1편 (TC275 MCU) (0) | 2022.09.11 |
댓글