Как передавать и получать данные с помощью SPI с LPC1788

Я пытаюсь написать программу с использованием микроконтроллера LPC1788, и мне нужно отправлять и передавать данные в UFDC (универсальный преобразователь частоты в цифровой) по протоколу SPI. Информацию об этом можно найти здесь. Контроллер SSP моего микроконтроллера установлен как ведущий, а UFDC предположительно становится ведомым. Я могу передавать информацию по линии MOSI и видеть, как данные отображаются на осциллографе. Однако, когда я пытаюсь получить данные в строке MISO, я получаю обратно только то, что отправил по MOSI.

Вот изображение схемы.

Соответствующая часть написанного мной кода приведена ниже:

SSP_CFG_Type sspConfig;
SSP_DATA_SETUP_Type sspData;
LPC_SSP_TypeDef *SSPx = NULL;

UFDC_RESULT_T result_SSP0_FX1, result_SSP0_FX2;
UFDC_RESULT_T result_SSP1_FX1, result_SSP1_FX2;
UFDC_RESULT_T *result, *resultFX1, *resultFX2 = NULL;

uint8_t resultSign;
uint64_t resultInt, resultFract;

uint8_t SSP0resultFX1sign, SSP0resultFX2sign;
uint8_t SSP1resultFX1sign, SSP1resultFX2sign;

uint64_t SSP0resultFX1int, SSP0resultFX2int;
uint64_t SSP1resultFX1int, SSP1resultFX2int;

uint64_t SSP0resultFX1fract, SSP0resultFX2fract;
uint64_t SSP1resultFX1fract, SSP1resultFX2fract;

uint16_t getAccInstr = 0x01FF;
uint16_t setAccInstr = 0x0204;
uint16_t checkStatusInstr = 0x03FF;
uint16_t setMeasureModeInstr1 = 0x0600;
uint16_t setMeasureModeInstr2 = 0x060E;
uint16_t getBCDResultInstr = 0x07FF;
uint8_t startMeasureInstr = 0x09;

uint32_t measureInstr;

uint8_t txData[2];
uint8_t rxData[2];

uint16_t data;

sspConfig.CPHA = SSP_CPHA_FIRST;
sspConfig.CPOL = SSP_CPOL_HI;
sspConfig.ClockRate = 100000;
sspConfig.Databit = SSP_DATABIT_8;
sspConfig.Mode = SSP_MASTER_MODE;
sspConfig.FrameFormat = SSP_FRAME_SPI;

sspData.tx_data = txData;
sspData.rx_data = rxData;
sspData.length = 2;

printf("Initialising SSP0 and SSP1...\n\n");

PINSEL_ConfigPin(0, 15, 2); // SSP0_SCK
PINSEL_ConfigPin(0, 16, 2); // SSP0_SSEL
PINSEL_ConfigPin(0, 17, 2); // SSP0_MISO
PINSEL_ConfigPin(0, 18, 2); // SSP0_MOSI
PINSEL_ConfigPin(0, 6, 2); // SSP1_SCK
PINSEL_ConfigPin(0, 7, 2); // SSP1_SSEL
PINSEL_ConfigPin(0, 8, 2); // SSP1_MISO
PINSEL_ConfigPin(0, 9, 2); // SSP1_MOSI

PINSEL_SetFilter(0, 7, DISABLE);
PINSEL_SetFilter(0, 8, DISABLE);
PINSEL_SetFilter(0, 9, DISABLE);

SSP_Init(LPC_SSP0, &sspConfig);
SSP_Init(LPC_SSP1, &sspConfig);
SSP_Cmd(LPC_SSP0, ENABLE);
SSP_Cmd(LPC_SSP1, ENABLE);

printf("Reading UDFC frequency values...\n\n");
for(int i=0; i < 2; i++)
{
  if(i == 0)
  {
    SSPx = LPC_SSP0;
    resultFX1 = &result_SSP0_FX1;
    resultFX2 = &result_SSP0_FX2;
  }
  else
  {
    SSPx = LPC_SSP1;
    resultFX1 = &result_SSP1_FX1;
    resultFX2 = &result_SSP1_FX2;
  }

  // Set UFDC accuracy to 0.05%.
  SSP_SendData(SSPx, (uint8_t)(setAccInstr >> 8));
  SSP_SendData(SSPx, (uint8_t)(setAccInstr & 0xFF));

  // Check accuracy.
  while(1)
  {
    SSP_SendData(SSPx, (uint8_t)(getAccInstr >> 8));
    SSP_SendData(SSPx, (uint8_t)(getAccInstr & 0xFF));

    data = SSP_ReceiveData(SSPx);
    printf("Accuracy check 1: %i\n", data >> 8);
    printf("Accuracy check 2: %i\n", data & 0xFF);
  }
// More code follows.

Результат, который я получаю, приведен ниже:

Accuracy check 1: 0
Accuracy check 2: 0
Accuracy check 1: 0
Accuracy check 2: 255
Accuracy check 1: 0
Accuracy check 2: 2
Accuracy check 1: 0
Accuracy check 2: 4
Accuracy check 1: 0
Accuracy check 2: 1
Accuracy check 1: 0
Accuracy check 2: 255
Accuracy check 1: 0
Accuracy check 2: 1
Accuracy check 1: 0
Accuracy check 2: 255
Accuracy check 1: 0
Accuracy check 2: 1
Accuracy check 1: 0
Accuracy check 2: 255

Изменить: можно установить «включение обратной петли» с помощью контроллеров SPI, чтобы MOSI считывал входные данные из MISO и наоборот. Однако я проверил соответствующий реестр, и он отключен.


person Tagc    schedule 15.07.2013    source источник
comment
Надеюсь, что нет, я попрошу своего босса взглянуть на плату, чтобы дважды проверить, но это уже версия платы Mark II.   -  person Tagc    schedule 16.07.2013
comment
На плате два контроллера UFDC / SSP. Я тестировал оба, и у них обоих обнаружилась одна и та же проблема. Это почти наверняка проблема программного обеспечения.   -  person Tagc    schedule 16.07.2013


Ответы (2)


После отправки одного байта через SPI вы должны снова очистить один байт в регистре данных (DR).

В SPI вы всегда отправляете и получаете байт. Вы не можете просто отправить или получить байт, это всегда AND. Техническое объяснение состоит в том, что есть только одна линия часов и две линии данных (MISO и MOSI).

person stigro    schedule 25.07.2013

Я думаю, вам следует проверить получение FIFO not Empty Flag, прямо перед чтением данных с помощью этой строки кода:

while (! (LPC_SSP0-> SR & SSP_SR_RNE)); // опрос получать FIFO не пустой флаг

и при инициализации SPI вы должны очистить FIFO приема с помощью следующих строк кода:

while (LPC_SSP0->SR & SSP_SR_RNE){
    tmp = (uint32_t) SSP_ReceiveData(LPC_SSP0);
}

надеюсь, что это сработает!

person Farhad    schedule 29.09.2015