Попытка отправить 10-битные данные через SPI в качестве ведомого при получении Clock и Slave Select в качестве входных данных (в режиме буфера) - PullRequest
0 голосов
/ 08 июля 2019

Я пытаюсь эмулировать данные с 10-битного поворотного энкодера AEAT-6010 и отправить их на вывод MISO протокола SPI на ATtiny3217. ATtiny действуют как подчиненные устройства и получают сигналы CLK и SS в качестве входных данных для ответа путем вывода данных (значение датчика). Кодер следует протоколу SSI для отправки данных, как показано ниже:

Encoder Timing Characteristics

Проблема возникает при попытке отправить 10-битный протокол 8-битного SPI на ATtiny. Мастером протокола SPI является микросхема TMS320F2808, и с нее я получаю 11 тактовых импульсов и сигнал SS. Измеренные сигналы и данные показаны ниже:

Oscilloscope measurements

Здесь данные, которые я пытаюсь отправить, 0b10 только для тестирования. Я вижу правильные данные в строке MISO, но в середине сигнала есть три дополнительных 1. Это происходит с BUFEN=1 и BUFWR=1 в настройках SPI ATtiny, как видно из конфигурации ниже (без режима буфера три единицы идут на последних 3 битах, а первый бит (MSB) читается как а 1):

int8_t SPI_0_init()
{

    SPI0.CTRLA = 0 << SPI_CLK2X_bp    /* Enable Double Speed: disabled */
                 | 0 << SPI_DORD_bp   /* Data Order Setting: enabled */
                 | 1 << SPI_ENABLE_bp /* Enable Module: enabled */
                 | 0 << SPI_MASTER_bp /* SPI module in slave mode */
                 | SPI_PRESC_DIV4_gc; /* System Clock / 4 */

    SPI0.CTRLB = 1 << SPI_BUFEN_bp   /* Buffer Mode Enable: enabled */
                 | 1 << SPI_BUFWR_bp /* Buffer Write Mode: enabled */
                 | SPI_MODE_0_gc     /* SPI Mode 1 */
                 | 0 << SPI_SSD_bp;  /* Slave Select Disable: disabled */

    SPI0.INTCTRL = 0 << SPI_DREIE_bp    /* Data Register Empty Interrupt Enable: enabled */
                   | 1 << SPI_IE_bp     /* Interrupt Enable: enabled */
                   | 0 << SPI_RXCIE_bp  /* Receive Complete Interrupt Enable: disabled */
                   | 0 << SPI_SSIE_bp   /* Slave Select Trigger Interrupt Enable: disabled */
                   | 0 << SPI_TXCIE_bp; /* Transfer Complete Interrupt Enable: disabled */

    return 0;
}

Я подтвердил, что данные модуля SPI TMS320F2808 и ATtiny одинаковы (читай по падающему такту). Есть ли что-то, чего мне не хватает в работе буферов SPI или прерываний SPI? Я не уверен, что делать в ISR при разрешении различных прерываний (или, кроме очистки флагов). Это моя основная функция (ISR пока пуст):

int main(void)
{
    /* Initializes MCU, drivers and middleware */
    atmel_start_init();

    sei(); // Enable global interrupts

    /* Replace with your application code */
    while (1) {

        SPI_transmit(enc_data_L);

}

Где SPI_transmit() выглядит следующим образом:

void SPI_transmit(uint16_t enc_data)
{
    // Then start the transmission by assigning the data to the SPI data register
    SPI0.DATA = enc_data;
    //SPI0.DATA = enc_data_H;

    // Now wait for the data transmission to complete by periodically checking the SPI status register
    //the SPI_IF is the only interrupt flag with a function in non-buffered mode.
    while(!(SPI0.INTFLAGS & (SPI_RXCIF_bm)));
    SPI0.DATA; //Dummy read to clear flag
}

Я также попытался разделить 16-битные данные, как предложено здесь , но проблема остается и для 8-битных данных. Надеюсь, этого достаточно. Я благодарен за любые идеи!

1 Ответ

0 голосов
/ 08 июля 2019

in SPI_transmit после записи в буфер, который вы ожидаете до завершения передачи. После этого входной буфер полностью передается и теперь пуст.

  while(!(SPI0.INTFLAGS & (SPI_RXCIF_bm))); // waits until data is transmitted

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

Таким образом, вместо ожидания флага RXCIF, дождитесь флага DREIF, который будет установлен, когда буфер передачи пуст и готов к следующему байту. Вы можете просто игнорировать входящие данные, так как вы их не используете

void SPI_transmit(uint16_t enc_data)
{
    // Wait until buffer is ready to get the next data byte
    while(!(SPI0.INTFLAGS & (SPI_DREIF_bm))); 

    // Then start the transmission by assigning the data to the SPI data register
    SPI0.DATA = enc_data;

    // Don't care about read buffer
}
...