LPC1788: обмен данными с UFDC-1 с помощью SPI

Я работаю с микроконтроллером LPC1788, и я пытаюсь отправлять и получать данные от UFDC-1 (универсальный преобразователь частоты в цифровой) с помощью SPI. Я могу передавать данные через 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 = 0x020A;
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_16;
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 1%.
  SSP_SendData(SSPx, setAccInstr);
  while(SSPx->SR & SSP_SR_BSY);

  // Check accuracy.
  while(1)
  {
    printf("Sending data...\n");
    SSP_SendData(SSPx, getAccInstr);

    while(SSPx->SR & SSP_SR_BSY);

    // Wait to receive back data.
    while(SSPx->SR & SSP_SR_RNE)
    {
      printf("Received data here: 0x%x\n", SSP_ReceiveData(SSPx));
    }

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

Изменить: Здесь представлены все мои строки SPI после отправки инструкции «установить точность» (0x020A). Ожидается, что данные по MISO будут здесь бессмысленными. При необходимости я могу сделать снимки для других инструкций.

Сверху донизу:

  • MISO
  • MOSI
  • SS
  • SCLK

Изменить 2: В частности, я пытаюсь установить точность UFDC-1 с помощью инструкции 0x020A. Последняя часть («0A») - это показатель точности. После этого у меня есть цикл while, в котором я пытаюсь восстановить эту точность. Команда "получить точность" - это 0x01FF, где "FF" - фиктивный байт, посланный для того, чтобы считать число точности. Поэтому, когда я отправляю «0x01FF», я ожидаю, что где-то в данных, которые я получаю от UFDC-1, снова прочитал «0A».

Изменить 3: Вот захват строк SPI, когда я отправляю команду "получить точность" в UFDC-1 в первый раз. Синяя линия (вторая сверху) - это MOSI, и она определенно дает правильную команду (0x01FF). Если это работает правильно, UFDC-1 должен отвечать через MISO с помощью «0A» (0b00001010), которое является числом точности, в то же время, когда MOSI передает «FF». Вместо этого я получаю обратно "1A", и я не верю, что "A" на самом деле исходит от UFDC-1, а только от инструкции "установить точность" (0x020A), которую я отправил ранее. Это потому, что у меня есть инструкция «получить точность», выполняемую в цикле while, и постоянное значение, которое я читаю, - «0x7F00» - ничего общего с числом точности UFDC-1.

Вот как выглядит мой результат:

Initialising SSP0 and SSP1...

Reading UDFC frequency values...

Sending data...
Received data here: 0xff00
Received data here: 0xa1a
Sending data...
Received data here: 0xff00
Sending data...
Received data here: 0x7f00
Sending data...
Received data here: 0x7f00
Sending data...
Received data here: 0x7f00
Sending data...
Received data here: 0x7f00
Sending data...
Received data here: 0x7f00
Sending data...

Изменить: оказывается, проблема связана с битами CPOL и CPHA. Они оба были изменены с 0 на 1. Это, кажется, позволяет контроллеру SPI правильно взаимодействовать с UFDC.

Остается одна проблема: SPI синхронизирует случайные данные на MISO. Например, у меня есть цикл while, в котором я не ожидаю получить ничего, кроме «0xedff». Вместо этого я получаю:

Data : 0xedff
Data : 0xffff
Data : 0xff01
Data : 0xffff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff
Data : 0xedff

person Tagc    schedule 17.07.2013    source источник
comment
Я не совсем понимаю ваш вопрос. Но я предполагаю, что вы ожидаете полученных данных в буфере, но не получаете их. Вы смотрели сигнал SPI в таблице данных UFDC-1? Я не знаю, как ваша функция обрабатывает строку выбора микросхемы. Большинство периферийных ИС SPI действительно требуют, чтобы мастер оставил микросхему выбранной для ответа на команду.   -  person Thanushan    schedule 17.07.2013
comment
Но я предполагаю, что вы ожидаете полученных данных в буфере, но не получаете их. Ага. Обновлю вопрос с уточнением. Большинство периферийных микросхем SPI требуют, чтобы мастер оставил чип выбранным для ответа на команду. Мой микроконтроллер, кажется, обрабатывает это автоматически, основываясь на данных, полученных с осциллографа. Кажется, что выбор подчиненного устройства удерживается до тех пор, пока не будет отправлена ​​вся команда.   -  person Tagc    schedule 17.07.2013
comment
Получаете ли вы ответ от UFDC-1, глядя с прицелом? Я думаю, что строка выбора чипа обрабатывается SSP_SendData () и SSP_ReceiveData. Но UFDC-1 может захотеть оставить линию на низком уровне до тех пор, пока не будет отправлен ответ, то есть не поднимать ее на высокий уровень после записи инструкции, а затем понижать ее для приема данных (только предположение).   -  person Thanushan    schedule 17.07.2013
comment
Из-за того, как я это делаю прямо сейчас, команда для получения точности и фиктивный байт для ее чтения из UFDC-1 все выполняются в пространстве одной 16-битной передачи, поэтому выбор микросхемы остается низким. в любом случае. Я сделал еще один снимок, чтобы показать, что происходит во время первой инструкции по получению точности, и обновлю свой вопрос с ее помощью.   -  person Tagc    schedule 17.07.2013
comment
Я подумал, может, мне нужно отправить первую часть инструкции (0x01), немного подождать, а затем отправить фиктивный байт (0xFF), чтобы дать UFDC-1 время для обработки? Я пробовал это, и это не сработало, но я не пробовал, удерживая нажатой кнопку выбора ведомого. Может, стоит попробовать ...   -  person Tagc    schedule 17.07.2013
comment
Просто попробовал. Хорошая новость в том, что я обнаружил и исправил ошибку в программном обеспечении драйвера ARM. Я должен как-нибудь написать им об этом по электронной почте. Плохая новость в том, что это не устранило мою проблему.   -  person Tagc    schedule 17.07.2013


Ответы (1)


SSP в LPC17xx имеют FIFO как для передачи, так и для приема. Это означает, что вы должны сопоставить свои SSP_SendData() и SSP_ReceiveData() вызовы или очистить FIFO. Вам также нужно будет отправить фиктивное значение при получении данных - обычно в качестве фиктивных используются 0x00 или 0xFF.

Библиотека делает это в SSP_ReadWrite(), который вы можете использовать вместо этого.

Более простая версия выглядела бы так:

uint16_t spi_write_read( LPC_SSP_TypeDef* SSPx, uint16_t outgoing )
{
    uint16_t incoming;

    while( !( SSPx->SR & (1 << SSP_SR_TNF ) ) ) { ; }
    SSPx->DR = outgoing;
    while( !( SSPSR & ( 1 << SSP_SR_RNE ) ) ) { ; }
    incoming = SSPx->DR;

    return incoming;
}

Эта функция может использоваться как замена как SSP_SendData(), так и SSP_ReceiveData() в вашем коде.

Последнее замечание: вы, вероятно, не хотите аппаратного выбора микросхемы, так как это может отменить выбор ведомого устройства между словами команды и ответа. Ознакомьтесь с соответствующими таблицами данных, во многих случаях это недопустимо.

person Turbo J    schedule 22.07.2013
comment
Я пробовал использовать SSP_ReadWrite (), а также вручную удерживать строку выбора чипа при передаче инструкции получения точности (я установил для нее функцию GPIO по умолчанию перед отправкой, а затем снова установил ее как аппаратный CS. Я проверил соответствующий в таблицах данных, и я не могу найти ничего о необходимости удерживать выбор чипа вручную в любом случае. - person Tagc; 23.07.2013
comment
Показать код. Необходимость в фиктивных байтах также относится к SPI_ReadWrite(). - person Turbo J; 24.07.2013
comment
Извините за поздний ответ. Я работал над чем-то другим. Коллега заставил SPI работать, изменив биты CPOL и CPHA. Я не смог найти ни одной ссылки на них в таблицах данных, поэтому меня раздражало, что они были проблемой. Осталась проблема - теперь SPI будет синхронизировать правильные данные, но он также будет синхронизировать набор случайных значений. Я постараюсь найти способ предотвратить это. - person Tagc; 01.08.2013