Как уменьшить время SPI для библиотеки STM32L4 HAL - PullRequest
0 голосов
/ 14 октября 2018

Я использую плату STM32L476RG и функции HAL SPI:

HAL_SPI_Transmit(&hspi2, &ReadAddr, 1, HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi2, pBuffer, 4, HAL_MAX_DELAY);

Мне нужно получить данные из буфера акселерометра с максимальной скоростью, и у меня проблема с задержкой в ​​этих функциях.Как вы можете видеть на скриншотах осциллографа, есть несколько микросекунд, в течение которых ничего не происходит.Я понятия не имею, как минимизировать разрыв передачи.

enter image description here

Я попытался использовать функцию HAL_SPI_Receive_DMA, и эта задержка была еще больше.Есть ли у вас какие-либо идеи, как решить эту проблему с помощью функций HAL или указателей на то, как я мог бы написать свою функцию SPI без этих задержек?

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Вы можете использовать HAL_SPI_TransmitReceive(&hspi2, ReadAddr, pBuffer, 1 + 4, HAL_MAX_DELAY); вместо HAL_SPI_Transmit и HAL_SPI_Receive.Это позволит избежать времени между передачей и получением.Вы также можете попробовать изменить настройки компиляции, чтобы оптимизировать скорость.Вы также можете проверить таблицу данных акселерометра, может быть, вы можете прочитать все буферы с одного кадра, что-то такое: HAL_SPI_TransmitReceive(&hspi2, ReadAddr, pBuffer, 1 + (4 * numOfSamples), HAL_MAX_DELAY);

0 голосов
/ 14 октября 2018

TL; DR Не используйте HAL, напишите свои функции передачи, используя Справочное руководство.

HAL безнадежно усложняется для срочных задач (среди прочих).Достаточно взглянуть на функцию HAL_SPI_Transmit(), это более 60 строк кода, пока не дойдет до фактического касания регистра данныхHAL сначала помечает структуру доступа к порту как занятую, даже когда многозадачной ОС не видно, проверяет параметры функции, сохраняет их в структуре hspi без видимой причины, затем продолжает выяснять, в каком режиме находится SPI и т. Д.Также нет необходимости проверять таймауты в режиме мастера SPI, потому что мастер контролирует все тайминги шины, если он не может получить байт за конечное время, то инициализация порта неверна, точка.

Без HAL все намного проще.Во-первых, выясните, что должно входить в управляющие регистры, установите CR1 и CR2 соответственно.

void SPIx_Init() {
    /* full duplex master, 8 bit transfer, default phase and polarity */
    SPIx->CR1 = SPI_CR1_MSTR | SPI_CR1_SPE | SPI_CR1_SSM | SPI_CR1_SSI;
    /* Disable receive FIFO, it'd complicate things when there is an odd number of bytes to transfer */
    SPIx->CR2 = SPI_CR2_FRXTH;
}

Эта инициализация предполагает, что выбор ведомого (NSS или CS#) обрабатывается отдельнымGPIO контакты.Если вы хотите, чтобы CS# управлялось периферийным устройством SPI, найдите в справочном руководстве Управление выводами Slave Select (NSS) .

Обратите внимание, что полнодуплексное соединение SPI не может просто передаватьили получить, он всегда делает оба одновременно.Если ведомый ожидает один командный байт и отвечает четырьмя байтами данных, это 5-байтовая передача, ведомый игнорирует последние 4 байта, мастер должен игнорировать первый.

Очень простая передачафункция будет

void SPIx_Transfer(uint8_t *outp, uint8_t *inp, int count) {
    while(count--) {
        while(!(SPIx->SR & SPI_SR_TXE))
            ;
        *(volatile uint8_t *)&SPIx->DR = *outp++;
        while(!(SPIx->SR & SPI_SR_RXNE))
            ;
        *inp++ = *(volatile uint8_t *)&SPIx->DR;
    }
}

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

Если скоростькритические, не используйте обобщенные функции, или убедитесь, что они могут быть встроены, когда вы делаете.Используйте компилятор с включенной оптимизацией по времени компоновки и оптимизируйте по скорости (вполне очевидно).

...