Правильное использование SPI с ISR

Мой Arduino должен сделать:

  1. Запустите ISR как можно больше раз/ как можно быстрее.
  2. Время от времени получаю данные по I2C.
  3. Вывод данных по SPI в ISR.

Мой вопрос касается SPI и ISR. Документация о SPI, которую я нашел, была довольно скудной.

SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
SPI.usingInterrupt(255);
SPI.begin();

void isr_function()
        SPI.transfer(data);
        pulse_latch();
};

Правильно ли это использовать SPI в моем случае? Может ли это быть быстрее?

, 👍1

Обсуждение

Библиотечная функция SPI; передача блокируется. Если вам действительно нужны дополнительные циклы процессора, вы можете отправлять данные между вызовами ISR. Аппаратное обеспечение SPI может отправлять данные, пока процессор делает что-то полезное, вместо того, чтобы ждать завершения передачи SPI. Затем вы должны зафиксировать данные в начале (следующего) ISR., @Gerben

PS Вы не можете запустить SPI на частоте 16 МГц на Nano. Максимальная скорость-F_CPU/2, если я правильно помню, что будет 8 МГц, @Gerben

Если вам нужно быстро передать много данных через SPI, гораздо удобнее использовать micro с периферийным устройством SPI, поддерживающим DMA. Скорее всего, ардуино на базе ARM будут соответствовать всем требованиям., @bobflux


1 ответ


1

На самом деле довольно легко просто использовать периферийное устройство SPI без использования библиотек arduino. Прикрепленные функции могут быть использованы для отправки нескольких байтов через SPI одним вызовом: (Предполагая, что ATMEGA328)

#include <avr/io.h>
#include <avr/interrupt.h>

static unsigned char spiCnt, *userBufr;

/* Вызовите эту функцию во время настройки */
void SpiInit (void)
    {
    PPR &= ~0x04;   // Убедитесь, что SPI имеет питание
    DDRB |= 4; // Убедитесь, что сигнал SS на бите PORTB 2 выведен
    SPCR = 0x50; // Включить SPI, максимальная скорость CLK
    }

/* Call this function to initiate the multi-byte send */
void SpiWrite (void *data, unsigned char bytCnt)
    {
    /* Сохранить информацию о месседже вызывающего абонента */
    userBufr = data;
    spiCnt = bytCnt;

    /* Включить устройство SPI, отправить первый байт */
    SPCR |= 0x40; // Включить SPI
    SPDR = *userBufr++; // Отправить первый байт
    SPCR |= 0x80; // Включить прерывания
    }

/* Позвоните по этому номеру, чтобы убедиться, что сообщение закончено. */
int SpiIsDone (void)
    {
    /* Ненулевое значение по завершении операции */
    return ( ! (SPCR & 0x80));
    }

/* Stay out of this one */
ISR (SPI_STC_vect)
    {
    /* Проверьте оставшееся количество байтов для отправки. */
    if (--spiCnt)
        SPDR = *userBufr++;     // Отправить следующий байт

    /* Операция завершена, отключите SPI */
    else
        SPCR &= ~0x80;  // Отключить прерывания для SPI
    }
,