ATMEGA2561 WINC1500 Проблема с SPI реализации драйвера - PullRequest
0 голосов
/ 02 апреля 2020

Я пытаюсь реализовать драйвер MLA WINC1500 для работы с MCU ATMEGA2561, и я написал свой код драйвера, и он застрял в строке "while ((SPSR & (1 << SPIF)) == 0);" в функции m2mStub_SpiTxRx. </p>

Я понятия не имею, почему это не прогрессирует. Я использую интегрированную среду разработки ImageCraft для этого проекта.

Вот его реализация

void m2mStub_SpiTxRx(uint8_t *p_txBuf,
                     uint16_t txLen,
                     uint8_t *p_rxBuf,
                     uint16_t rxLen)
{
    uint16_t byteCount;
    uint16_t i;

    // Calculate the number of clock cycles necessary, this implies a full-duplex SPI.
    byteCount = (txLen >= rxLen) ? txLen : rxLen;
    DEBUGOUTF("Calculate the number of clock cycles\n");

    DEBUGOUTF("byteCount %d", byteCount, "\n");
    DEBUGOUTF("txLen %d", txLen, "\n");
    DEBUGOUTF("rxLen %d", rxLen, "\n");

    // Read / Transmit.
    for (i = 0; i < byteCount; ++i)
    {
        // Wait for transmitter to be ready. (This is causing the entire thing to crash)
        while((SPSR & (1 << SPIF)) == 0);

        // Transmit.
        if (txLen > 0)
        {
            // Send data from the transmit buffer.
            SPDR = (*p_txBuf++);
            --txLen;
        }
        else
        {
            // No more Tx data to send, just send something to keep clock active.
            SPDR = 0x00U;
        }

        // Wait for transfer to finish.
        while((SPSR & (1 << SPIF)) == 0);

        // Send dummy data to slave, so we can read something from it.
        SPDR = 0x00U;

        // Wait for transfer to finish.
        while((SPSR & (1 << SPIF)) == 0);

        // Read or throw away data from the slave as required.
        if (rxLen > 0)
        {
            *p_rxBuf++ = SPDR;
            --rxLen;
        }
        else
        {
            // Clear the registers
            volatile uint8_t reg_clear = 0U;
            reg_clear = SPDR;
            (void)reg_clear;
        }

    }
}

1 Ответ

0 голосов
/ 02 апреля 2020

У меня недостаточно информации, чтобы сказать наверняка, но я предполагаю, что ваше SPI-соединение установлено неправильно.

В частности, я полагаю, вы забыли установить /SS в качестве вывода, так же, как эта проблема или это .

В таблице указано:

Режим мастера, когда SPI настроен как мастер (MSTR в SPCR установлено), пользователь может определить направление вывода SS.

Если SS настроен как выход, это вывод общего вывода, который не влияет на систему SPI. , Как правило, этот вывод будет управлять выводом SS ведомого SPI.

Если SS настроен как вход, он должен поддерживаться на высоком уровне, чтобы обеспечить работу главного SPI. Если на вывод SS подается периферийная схема, когда SPI сконфигурирован как ведущий, а вывод SS определен как вход, система SPI интерпретирует его как другой ведущий, выбирающий SPI в качестве ведомого и начинающий отправлять на него данные. Чтобы избежать конфликта шин, система SPI выполняет следующие действия:

  1. Бит MSTR в SPCR очищается, и система SPI становится подчиненной. В результате того, что SPI становится подчиненным, контакты MOSI и SCK становятся входами.
  2. Устанавливается флаг SPIF в SPSR, и если прерывание SPI включено, и бит I в SREG установлен, подпрограмма прерывания будет выполнена.

Таким образом, когда SPI-передача, управляемая прерыванием, используется в основном режиме, и существует вероятность того, что SS работает на низком уровне, прерывание всегда должно проверять, что бит MSTR все еще установлен. Если бит MSTR был очищен при выборе ведомого устройства, он должен быть установлен пользователем для повторного включения основного режима SPI.

Итак, вам просто нужно настроить вывод /SS в качестве выхода и установите высокий в вашем коде инициализации, это должно решить вашу проблему:

DDRB |= (1 << PB0); // Set /SS (PB0) as output
PORTB |= (1 << PB0); // Set /SS (PB0) high
...