Relógio SPI no PIC instável

8

Estou tentando configurar o módulo MSSP de um PIC18F25K22 no modo mestre SPI. Estou observando o tempo e o relógio não permanece constante durante toda a transmissão. Uma imagem mostra isso melhor do que palavras. Diagrama de tempo do SPI

Depois que um pouco é enviado, o relógio diminui e não na mesma quantidade a cada vez. Eu não trabalhei com SPI antes, mas os diagramas que encontrei na Wikipedia e outros recursos nunca mostram isso. Também conectei um Arduino e não vi esse comportamento. Meu código é:

    #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
}

(também https://gist.github.com/stumpylog/5095250 )

Alguém já encontrou isso ou tem sugestões sobre a causa?

O que eu fiz

No final, não consegui colocar o módulo MSSP1 em funcionamento. No entanto, alterá-lo para o módulo MSSP2, exatamente o mesmo código, não exibiu esse comportamento. Não sei explicar, mas isso resolveu o problema.

Trenton Holmes
fonte
Você pode mostrar seu código para usar o SPI?
Gustavo Litovsky
1
Geralmente, o SPI (e I2C também) funcionaria com um relógio não uniforme. O SPI é síncrono. Ao mesmo tempo, parece estranho que um MSSP de hardware gere um relógio não uniforme. Quando a linha de dados (verde) está baixa, seus relógios são uniformes. Quando a linha de dados está alta, seus relógios ficam mais curtos. Por precaução, verifique as erratas do seu PIC.
Nick Alexeev
@GustavoLitovsky Adicionei o código diretamente à pergunta agora.
Trenton Holmes
@NickAlexeev Obrigado, eu dei uma olhada nisso. Nada mencionado sobre o módulo MSSP. Vou ter que verificar se meu escravo pode lidar com o tempo como está.
Trenton Holmes
Provavelmente não relacionado ao seu problema, mas não vejo código para limpar os bits ANSEL para suas portas. A Microchip fez a escolha irritante de ter os pinos como entradas analógicas por padrão, em vez de digitais.
Apalopohapa 9/03/2013

Respostas:

3

Isso é um palpite, mas você provavelmente está redefinindo algo que não deveria ter a cada byte. Coisas como o gerador de taxa de bits e a configuração periférica geral devem ser definidas apenas uma vez.

Adicionado:

Agora você diz que não conseguiu que o MSSP1 funcionasse, mas conseguiu que o MSSP2 funcionasse. Isso indica que você tem um bug em outro lugar do código que está fazendo gravações não intencionais. Acontece que está atingindo algum estado MSSP1, e é por isso que age de maneira estranha e porque o MSSP2 funciona.

Não deixe isso de lado. Mudar para o MSSP2 pode parecer ter corrigido o problema, mas, na melhor das hipóteses, você o contornou, provavelmente temporariamente. Da próxima vez que você se vincular a coisas em lugares diferentes, diferentes memórias poderão ser rabiscadas. Se você não encontrar e realmente consertar isso, este firmware será sempre esquisito. O pior caso é quando não há sintomas óbvios, fazendo o favor de deixar claro que há um problema. O problema aparecerá um ano depois, quando apenas os dados corretos forem encontrados, apenas sites de clientes, depois das 1000 em campo. CORRIGIR ESTA MANEIRA CERTA AGORA.

Olin Lathrop
fonte
2

Parece que você pode ter problemas de integridade do sinal - na cena de LA, parece que a linha do relógio falha quando a linha de dados cai. Tente garantir que os dois estejam bem isolados, e o traço ou a fiação não seja muito longa. Você também tenta diminuir a velocidade do relógio ou adicionar um pequeno filtro RC nas linhas (se as linhas forem longas, apenas um resistor em série de 220Ω pode ajudar)

Se você possui um osciloscópio, verifique as linhas com isso para garantir que a integridade do sinal seja boa. Caso contrário, tente as sugestões acima e ajuste as coisas até obter sinais de boa qualidade.

Oli Glaser
fonte