Доброго времени суток.
Возникла проблема, связанная с организацией интерфейса 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);
}