我的开发环境MPLAB X v5.50,XC32版本为v2.40,用Harmony生成了一个SPI的程序。
生成的SPI读写函数如下:
// *****************************************************************************
/* Function:
bool SERCOM6_SPI_WriteRead (void* pTransmitData, size_t txSize
void* pReceiveData, size_t rxSize);
Summary:
Write and Read data on SERCOM SERCOM6 SPI peripheral.
Description:
This function transmits "txSize" number of bytes and receives "rxSize"
number of bytes on SERCOM SERCOM6 SPI module. Data pointed by pTransmitData is
transmitted and received data is saved in the location pointed by
pReceiveData. The function will transfer the maximum of "txSize" or "rxSize"
data units towards completion.
When "Interrupt Mode" option is unchecked in MHC, this function will be
blocking in nature. In this mode, the function will not return until all
the requested data is transferred. The function returns true after
transferring all the data. This indicates that the operation has been
completed.
When "Interrupt Mode" option is selected in MHC, the function will be
non-blocking in nature. The function returns immediately. The data transfer
process continues in the peripheral interrupt. The application specified
transmit and receive buffer are ownerd by the library until the data
transfer is complete and should not be modified by the application till the
transfer is complete. Only one transfer is allowed at any time. The
Application can use a callback function or a polling function to check for
completion of the transfer. If a callback is required, this should be
registered prior to calling the SERCOM6_SPI_WriteRead() function. The
application can use the SERCOM6_SPI_IsBusy() to poll for completion.
Remarks:
Refer plib_sercom6_spi.h file for more information.
*/
bool SERCOM6_SPI_WriteRead (void* pTransmitData, size_t txSize, void* pReceiveData, size_t rxSize)
{
bool isRequestAccepted = false;
uint32_t dummyData = 0U;
/* Verify the request */
if((((txSize > 0U) && (pTransmitData != NULL)) || ((rxSize > 0U) && (pReceiveData != NULL))) && (sercom6SPIObj.transferIsBusy == false))
{
if((SERCOM6_REGS->SPIM.SERCOM_CTRLB & SERCOM_SPIM_CTRLB_CHSIZE_Msk) == (uint32_t)SPI_DATA_BITS_9)
{
/* For 9-bit transmission, the txSize and rxSize must be an even number. */
if(((txSize > 0U) && ((txSize & 0x01U) != 0U)) || ((rxSize > 0U) && ((rxSize & 0x01U) != 0U)))
{
return isRequestAccepted;
}
}
isRequestAccepted = true;
sercom6SPIObj.txBuffer = pTransmitData;
sercom6SPIObj.rxBuffer = pReceiveData;
sercom6SPIObj.rxCount = 0U;
sercom6SPIObj.txCount = 0U;
sercom6SPIObj.dummySize = 0U;
if(pTransmitData != NULL)
{
sercom6SPIObj.txSize = txSize;
}
else
{
sercom6SPIObj.txSize = 0U;
}
if(pReceiveData != NULL)
{
sercom6SPIObj.rxSize = rxSize;
}
else
{
sercom6SPIObj.rxSize = 0U;
}
sercom6SPIObj.transferIsBusy = true;
/* Flush out any unread data in SPI read buffer */
while((SERCOM6_REGS->SPIM.SERCOM_INTFLAG & SERCOM_SPIM_INTFLAG_RXC_Msk) == SERCOM_SPIM_INTFLAG_RXC_Msk)
{
dummyData = SERCOM6_REGS->SPIM.SERCOM_DATA;
(void)dummyData;
}
SERCOM6_REGS->SPIM.SERCOM_STATUS |= SERCOM_SPIM_STATUS_BUFOVF_Msk;
SERCOM6_REGS->SPIM.SERCOM_INTFLAG |= (uint8_t)SERCOM_SPIM_INTFLAG_ERROR_Msk;
if(sercom6SPIObj.rxSize > sercom6SPIObj.txSize)
{
sercom6SPIObj.dummySize = sercom6SPIObj.rxSize - sercom6SPIObj.txSize;
}
/* Start the first write here itself, rest will happen in ISR context */
if((SERCOM6_REGS->SPIM.SERCOM_CTRLB & SERCOM_SPIM_CTRLB_CHSIZE_Msk) == (uint32_t)SPI_DATA_BITS_8)
{
if(sercom6SPIObj.txCount < sercom6SPIObj.txSize)
{
SERCOM6_REGS->SPIM.SERCOM_DATA = *((uint8_t*)sercom6SPIObj.txBuffer);
sercom6SPIObj.txCount++;
}
else if(sercom6SPIObj.dummySize > 0U)
{
SERCOM6_REGS->SPIM.SERCOM_DATA = 0xFFU;
sercom6SPIObj.dummySize--;
}
else
{
/* Do nothing */
}
}
else
{
sercom6SPIObj.txSize >>= 1U;
sercom6SPIObj.dummySize >>= 1U;
sercom6SPIObj.rxSize >>= 1U;
if(sercom6SPIObj.txCount < sercom6SPIObj.txSize)
{
SERCOM6_REGS->SPIM.SERCOM_DATA = *((uint16_t*)sercom6SPIObj.txBuffer) & SERCOM_SPIM_DATA_Msk;
sercom6SPIObj.txCount++;
}
else if(sercom6SPIObj.dummySize > 0U)
{
SERCOM6_REGS->SPIM.SERCOM_DATA = 0xFFFFU & SERCOM_SPIM_DATA_Msk;
sercom6SPIObj.dummySize--;
}
else
{
/* Do nothing */
}
}
if(rxSize > 0U)
{
/* Enable ReceiveComplete */
SERCOM6_REGS->SPIM.SERCOM_INTENSET = (uint8_t)SERCOM_SPIM_INTENSET_RXC_Msk;
}
else
{
/* Enable the DataRegisterEmpty */
SERCOM6_REGS->SPIM.SERCOM_INTENSET = (uint8_t)SERCOM_SPIM_INTENSET_DRE_Msk;
}
}
return isRequestAccepted;
}
我不知道它搞得这么复杂,弄得我不知道怎么调用了。
下面还有:
bool SERCOM6_SPI_Write(void* pTransmitData, size_t txSize)
{
return SERCOM6_SPI_WriteRead(pTransmitData, txSize, NULL, 0U);
}
bool SERCOM6_SPI_Read(void* pReceiveData, size_t rxSize)
{
return SERCOM6_SPI_WriteRead(NULL, 0U, pReceiveData, rxSize);
}
|