Часы SPI на PIC нестабильны

Я пытаюсь настроить модуль MSSP PIC18F25K22 в основной режим SPI. Я смотрю на время, и часы не остаются стабильными на протяжении всей передачи. Картинка показывает это лучше, чем слова.Временная диаграмма SPI

После отправки бита часы укорачиваются, и каждый раз не на одну и ту же величину. Я раньше не работал с SPI, но диаграммы, которые я нашел в Википедии и других ресурсах, никогда этого не показывают. Я также подключил Arduino и не видел такого поведения. Мой код:

    #pragma config FOSC = INTIO67   // Oscillator Selection bits (Internal oscillator block)
#pragma config PLLCFG = OFF     // 4X PLL Enable (Oscillator used directly)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config WDTEN = OFF      // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)
#pragma config MCLRE = EXTMCLR  // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

void main(void)
{
    OSCCON = 0b11100110;
    spi_setup();
    __delay_ms(10);
    byte temp;
    while (TRUE)
    {
        temp = spi_transfer(0x00);
        temp = spi_transfer(0x01);
        temp = spi_transfer(0x02);
        temp = spi_transfer(0x03);
        temp = spi_transfer(0x04);
        temp = spi_transfer(0x05);
        __delay_us(1);
    }
}

void spi_setup(void)
{
    SSP1STAT = 0b00000000;
    SSP1STATbits.CKE = HIGH; // data transmitted on rising edge
    SSP1CON1 = 0b00000000; // enable Master SPI mode
    SSP1CON1bits.CKP1 = LOW; //clock idle state is low
    //i2c bits, all don't matters for SPI, cleared just in case
    SSP1CON3 = 0;
    // baud rate generation
    SSP1ADD = 0; //FCLOCK = 8Mhz /2 = 2Mhz
    // configure pins for output/input as needed 
    SDI1 = INPUT;
    SDO1 = OUTPUT;
    SCK1 = OUTPUT;
    SS1 = OUTPUT;
    SSP1CON1bits.SSPEN1 = HIGH; // enable pins for serial mode
}

unsigned char spi_transfer(unsigned char data)
{
    SS1_LAT = LOW; // select slave
    PIR1bits.SSPIF = LOW;
    SSP1BUF = data;
    //while (!SSP1STATbits.BF); //wait for receive to complete
    while( !PIR1bits.SSPIF );
    SS1_LAT = HIGH; // deselect slave
    PIR1bits.SSPIF = LOW;   // clear interrupt
    return SSP1BUF; //return data from the slave
}

(также https://gist.github.com/stumpylog/5095250 )

Кто-нибудь сталкивался с этим или есть предположения относительно причины?

Что я сделал

В конце концов, мне не удалось заставить работать модуль MSSP1. Однако изменение его на модуль MSSP2, точно такой же код, не показало такого поведения. Я не могу это объяснить, но это решило проблему.

Можете ли вы показать свой код для использования SPI?
Как правило, SPI (и I2C тоже) будут работать с неравномерными часами. SPI синхронный. В то же время кажется странным, что аппаратный MSSP генерирует неравномерные часы. Когда линия данных (зеленая) имеет низкий уровень, ваши часы равномерны. Когда линия данных высока, ваши часы короче. На всякий случай проверьте опечатки для вашего PIC.
@GustavoLitovsky Сейчас я добавил код прямо в вопрос.
@NickAlexeev Спасибо, я посмотрел. Ничего не сказано о модуле MSSP. Я должен проверить, может ли мой ведомый выдержать синхронизацию как есть.
Вероятно, это не связано с вашей проблемой, но я не вижу кода для очистки битов ANSEL для ваших портов. Компания Microchip сделала досадный выбор, сделав контакты по умолчанию аналоговыми, а не цифровыми.
Как вы разместили свой код в таком вопросе? Я пытался добиться аналогичного результата с моим собственным вопросом?
@OsagieIgbeare: вы вставляете свой код в свой вопрос, выделяете все это, а затем нажимаете Control-K, что ставит четыре пробела перед каждой строкой, вызывая средство форматирования блока кода. Или вы можете просто поставить четыре пробела перед каждой строкой, прежде чем вставлять ее.

Ответы (2)

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

Добавлен:

Теперь вы говорите, что не смогли заставить работать MSSP1, но заставили работать MSSP2. Это намекает на то, что у вас есть ошибка в другом месте кода, которая выполняет непреднамеренную запись. Он попадает в какое-то состояние MSSP1, поэтому он ведет себя странно и почему MSSP2 работает.

Не отпускай это. Может показаться, что переход на MSSP2 устранил проблему, но в лучшем случае вы решили ее обойти, возможно, временно. В следующий раз, когда вы свяжетесь с вещами в других местах, на них может быть нацарапано другое воспоминание. Если вы не найдете и не исправите это, эта прошивка будет вечно глючной. Худший случай — это когда нет явных симптомов, которые помогают вам понять, что есть проблема. Проблема появится через год, когда будут обнаружены только нужные данные, только сайты клиентов, после 1000 в поле. ИСПРАВЬТЕ ЭТО ПРАВИЛЬНО СЕЙЧАС.

Похоже, у вас могут быть проблемы с целостностью сигнала - на снимке в Лос-Анджелесе видно, что линия синхронизации дает сбои при обрыве линии данных. Постарайтесь убедиться, что они хорошо изолированы, а трасса или проводка не слишком длинны. Вы также можете попробовать снизить тактовую частоту или добавить небольшой RC-фильтр на линии (если линии длинные, может помочь только последовательный резистор, скажем, 220 Ом).

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