Доброго времени суток. Возникла проблема, связанная с организацией интерфейса SPI, ведущим устройством которого является микроконтроллер AT91SAM7X512. Дело в том, что все работает как надо - но, смотря осциллограмму, вижу, что в последний момент независимо от передаваемого функции SPI_Write() значения, линия MOSI устанавливается в уровень логической 1. В данном примере я передаю значение "0", но линия его передает - и сразу же в последний момент устанавливается в 1. Чего быть не должно. В чем еще может быть проблема, если вся инициализация верная, синхронизацию соответствующего периферийного устройства разрешил? Программа main.c: #include "AT91SAM7X256.h" #include <spi/spi.h> int main(void) { unsigned short data; AT91C_BASE_PMC->PMC_PCER = (1<<2); AT91C_BASE_PIOA->PIO_PPUDR = (1<<21) | (1<<22) | (1<<23) | (1<<24); AT91C_BASE_PIOA->PIO_PDR = (1<<21) | (1<<22) | (1<<23) | (1<<24); AT91C_BASE_PIOA->PIO_BSR = (1<<21) | (1<<22) | (1<<23) | (1<<24);
SPI_Configure(AT91C_BASE_SPI1, 5, 0xFF000011); SPI_ConfigureNPCS(AT91C_BASE_SPI1, 0, 0xFFFFFF02); SPI_Enable(AT91C_BASE_SPI1);
SPI_Write(AT91C_BASE_SPI1, 0, 0x00); data=SPI_Read(AT91C_BASE_SPI1);
while(1); } А содержимое spi.c (вырезал кусок): void SPI_Enable(AT91S_SPI *spi) { spi->SPI_CR = AT91C_SPI_SPIEN; }
//------------------------------------------------------------------------------ /// Disables a SPI peripheral. /// \param spi Pointer to an AT91S_SPI instance. //------------------------------------------------------------------------------ void SPI_Disable(AT91S_SPI *spi) { spi->SPI_CR = AT91C_SPI_SPIDIS; }
//------------------------------------------------------------------------------ /// Configures a SPI peripheral as specified. The configuration can be computed /// using several macros (see "SPI configuration macros") and the constants /// defined in LibV3 (AT91C_SPI_*). /// \param spi Pointer to an AT91S_SPI instance. /// \param id Peripheral ID of the SPI. /// \param configuration Value of the SPI configuration register. //------------------------------------------------------------------------------ void SPI_Configure(AT91S_SPI *spi, unsigned int id, unsigned int configuration) { AT91C_BASE_PMC->PMC_PCER = (1<<2) | (1<<id); spi->SPI_CR = AT91C_SPI_SPIDIS; // Execute a software reset of the SPI twice spi->SPI_CR = AT91C_SPI_SWRST; spi->SPI_CR = AT91C_SPI_SWRST; spi->SPI_MR = configuration; }
//------------------------------------------------------------------------------ /// Configures a chip select of a SPI peripheral. The chip select configuration /// is computed using the definition provided by the LibV3 (AT91C_SPI_*). /// \param spi Pointer to an AT91S_SPI instance. /// \param npcs Chip select to configure (1, 2, 3 or 4). /// \param configuration Desired chip select configuration. //------------------------------------------------------------------------------ void SPI_ConfigureNPCS(AT91S_SPI *spi, unsigned int npcs, unsigned int configuration) { spi->SPI_CSR[npcs] = configuration; }
//------------------------------------------------------------------------------ /// Sends data through a SPI peripheral. If the SPI is configured to use a fixed /// peripheral select, the npcs value is meaningless. Otherwise, it identifies /// the component which shall be addressed. /// \param spi Pointer to an AT91S_SPI instance. /// \param npcs Chip select of the component to address (1, 2, 3 or 4). /// \param data Word of data to send. //------------------------------------------------------------------------------ void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data) { // Discard contents of RDR register //volatile unsigned int discard = spi->SPI_RDR;
// Send data while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0); spi->SPI_TDR = data | SPI_PCS(npcs); while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0); }
|