/** @ingroup spi_function @brief Send an array of bytes to to the SPI bus. @note Can only be used if SPI_USE_BUFFER are enabled in spi_iha_defs.h @see spi_iha_defs.h for SPI_USE_BUFFER setup. @return SPI_OK: OK byte send to SPI bus or put in tx_buffer.\n SPI_NO_ROOM_IN_TX_BUFFER: Buffer full no data send\n SPI_ILLEGAL_INSTANCE: instance is null. @param spi to send to. @param *buf pointer to buffer to be send. @param len no of bytes to send. */ uint8_t spi_send_bytes(spi_p spi, uint8_t buf[], uint8_t len) { uint8_t result = SPI_OK; uint32_t value; uint8_t tmp = 0; if (spi == NULL) { return SPI_ILLEGAL_INSTANCE; } // Select correct instance if (_this != spi ) { _select_instance(spi); } // Critical section { // disable interrupt spi_disable_interrupt(_spi_base, SPI_IDR_TDRE | SPI_IDR_RDRF); // Check if buffer is free if (len > fifo_get_free_size(spi->_spi_tx_fifo_desc)) { result = SPI_NO_ROOM_IN_TX_BUFFER; } else { // If SPI in idle send the first byte if (!_spi_active) { _spi_active = 1; // Send first byte value = SPI_TDR_TD(buf[0]) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin)); if (len == 1) { // It was last byte value |= SPI_TDR_LASTXFER; } // Send byte _spi_base->SPI_TDR = value; //spi_enable_interrupt(_spi_base, SPI_IER_TDRE); tmp = 1; } // Put in the tx buffer for (uint8_t i = tmp; i < len; i++) { value = SPI_TDR_TD(buf[i]) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin)); if (i == len-1) { // It was last byte value |= SPI_TDR_LASTXFER; } if ( fifo_push_uint32(spi->_spi_tx_fifo_desc, value) == FIFO_ERROR_OVERFLOW ) { result = SPI_NO_ROOM_IN_TX_BUFFER; } } } // restore interrupt state spi_enable_interrupt(_spi_base, SPI_IER_TDRE | SPI_IER_RDRF); } return result; }
// ============================================================================= // 功能:SPI片选使能,使片选有效,若控制器有具体的配置片选寄存器,可直接返回 // 参数:Reg,本模块内即SPI寄存器基址 // cs,片选线 // 返回:无 // 说明:SPI控制器上只引出了一个CS,若需要接多个CS,则必须应用程序自己控制CS // ============================================================================= static bool_t __SPI_BusCsActive(tagSpiReg *Reg, u8 cs) { // s_ChipSelect = cs; Reg->SPI_TDR |= SPI_TDR_PCS(cs); Reg->SPI_MR &= ~SPI_MR_PCS(0x0F); Reg->SPI_MR |= SPI_MR_PCS(cs); return true; }
uint8_t spi_send_byte(spi_p spi, uint8_t byte, uint8_t last_byte) { uint8_t result = SPI_OK; uint32_t value; if (spi == NULL) { return SPI_ILLEGAL_INSTANCE; } // Select correct instance if (_this != spi ) { _select_instance(spi); } // Critical section { // disable interrupt spi_disable_interrupt(_spi_base, SPI_IDR_TDRE | SPI_IDR_RDRF); value = SPI_TDR_TD(byte) | SPI_TDR_PCS(spi_get_pcs(spi->_cs_pin)); if (last_byte) { value |= SPI_TDR_LASTXFER; } // If SPI in idle send the byte if (!_spi_active) { _spi_active = 1; // Send byte _spi_base->SPI_TDR = value; } else { // Put in the TX buffer if ( fifo_push_uint32(spi->_spi_tx_fifo_desc, value) == FIFO_ERROR_UNDERFLOW ) result = SPI_NO_ROOM_IN_TX_BUFFER; } // Enable interrupt spi_enable_interrupt(_spi_base, SPI_IER_TDRE | SPI_IER_RDRF); } return result; }