/*********************************************************************//** * @brief SPI Read write data function * @param[in] SPIx Pointer to SPI peripheral, should be LPC_SPI * @param[in] dataCfg Pointer to a SPI_DATA_SETUP_Type structure that * contains specified information about transmit * data configuration. * @param[in] xfType Transfer type, should be: * - SPI_TRANSFER_POLLING: Polling mode * - SPI_TRANSFER_INTERRUPT: Interrupt mode * @return Actual Data length has been transferred in polling mode. * In interrupt mode, always return (0) * Return (-1) if error. * Note: This function can be used in both master and slave mode. ***********************************************************************/ int32_t SPI_ReadWrite (LPC_SPI_TypeDef *SPIx, SPI_DATA_SETUP_Type *dataCfg, \ SPI_TRANSFER_Type xfType) { uint8_t *rdata8; uint8_t *wdata8; uint16_t *rdata16; uint16_t *wdata16; uint32_t stat; uint32_t temp; uint8_t dataword; //read for empty buffer temp = SPIx->SPDR; //dummy to clear status temp = SPIx->SPSR; dataCfg->counter = 0; dataCfg->status = 0; if(SPI_GetDataSize (SPIx) == 8) dataword = 0; else dataword = 1; if (xfType == SPI_TRANSFER_POLLING){ if (dataword == 0){ rdata8 = (uint8_t *)dataCfg->rx_data; wdata8 = (uint8_t *)dataCfg->tx_data; } else { rdata16 = (uint16_t *)dataCfg->rx_data; wdata16 = (uint16_t *)dataCfg->tx_data; } while(dataCfg->counter < dataCfg->length) { // Write data to buffer if(dataCfg->tx_data == NULL){ if (dataword == 0){ SPI_SendData(SPIx, 0xFF); } else { SPI_SendData(SPIx, 0xFFFF); } } else { if (dataword == 0){ SPI_SendData(SPIx, *wdata8); wdata8++; } else { SPI_SendData(SPIx, *wdata16); wdata16++; } } // Wait for transfer complete while (!((stat = SPIx->SPSR) & SPI_SPSR_SPIF)); // Check for error if (stat & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){ // save status dataCfg->status = stat | SPI_STAT_ERROR; return (dataCfg->counter); } // Read data from SPI dat temp = (uint32_t) SPI_ReceiveData(SPIx); // Store data to destination if (dataCfg->rx_data != NULL) { if (dataword == 0){ *(rdata8) = (uint8_t) temp; rdata8++; } else { *(rdata16) = (uint16_t) temp; rdata16++; } } // Increase counter if (dataword == 0){ dataCfg->counter++; } else { dataCfg->counter += 2; } } // Return length of actual data transferred // save status dataCfg->status = stat | SPI_STAT_DONE; return (dataCfg->counter); } // Interrupt mode else { // Check if interrupt flag is already set if(SPIx->SPINT & SPI_SPINT_INTFLAG){ SPIx->SPINT = SPI_SPINT_INTFLAG; } if (dataCfg->counter < dataCfg->length){ // Write data to buffer if(dataCfg->tx_data == NULL){ if (dataword == 0){ SPI_SendData(SPIx, 0xFF); } else { SPI_SendData(SPIx, 0xFFFF); } } else { if (dataword == 0){ SPI_SendData(SPIx, (*(uint8_t *)dataCfg->tx_data)); } else { SPI_SendData(SPIx, (*(uint16_t *)dataCfg->tx_data)); } } SPI_IntCmd(SPIx, ENABLE); } else { // Save status dataCfg->status = SPI_STAT_DONE; } return (0); } }
/*********************************************************************//** * @brief SPI Interrupt used for reading and writing handler * @param None * @return None ***********************************************************************/ void SPI_IRQHandler(void) { SPI_DATA_SETUP_Type *xf_setup; uint16_t tmp; uint8_t dataword; xf_setup = &xferConfig; if(SPI_GetDataSize(LPC_SPI) == 8) dataword = 0; else dataword = 1; /* Dummy read to clear SPI interrupt flag */ SPI_ClearIntPending(LPC_SPI); // save status tmp = SPI_GetStatus(LPC_SPI); xf_setup->status = tmp; // Check for error if (tmp & (SPI_SPSR_ABRT | SPI_SPSR_MODF | SPI_SPSR_ROVR | SPI_SPSR_WCOL)){ xf_setup->status |= SPI_STAT_ERROR; // Disable Interrupt and call call-back SPI_IntCmd(LPC_SPI, DISABLE); // Set Complete Flag complete = SET; return; } /* Check SPI complete flag */ if (tmp & SPI_SPSR_SPIF){ // Read data from SPI data tmp = SPI_ReceiveData(LPC_SPI); if (xf_setup->rx_data != NULL) { if (dataword == 0){ *(uint8_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp; } else { *(uint16_t *)((uint8_t *)(xf_setup->rx_data) + xf_setup->counter) = (uint8_t) tmp; } } // Increase counter if (dataword == 0){ xf_setup->counter++; } else { xf_setup->counter += 2; } } if (xf_setup->counter < xf_setup->length){ // Write data to buffer if(xf_setup->tx_data == NULL){ if (dataword == 0){ SPI_SendData(LPC_SPI, 0xFF); } else { SPI_SendData(LPC_SPI, 0xFFFF); } } else { if (dataword == 0){ SPI_SendData(LPC_SPI, (*(uint8_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter))); } else { SPI_SendData(LPC_SPI, (*(uint16_t *)((uint8_t *)(xf_setup->tx_data) + xf_setup->counter))); } } } // No more data to send else { xf_setup->status |= SPI_STAT_DONE; // Disable Interrupt and call call-back SPI_IntCmd(LPC_SPI, DISABLE); // Set Complete Flag complete = SET; } }