DSPIC33 La línea de selección de chip SPI Master no funciona

2

He estado intentando realmente hacer que el bus SPI funcione en un DSPIC33EP128GM604. He configurado SPI3 como un módulo maestro de 8 bits estándar y he designado un pin de selección de chip para que pueda alternar dispositivos esclavos.

No consigo que la línea de selección de chip funcione correctamente, parece que el DSPIC no espera a que se complete la transmisión antes de cambiar la línea de selección de chip de LOW a HIGH. He revisado las Erratas y nada parece relevante para este problema. Además, he tratado de cambiar la línea CS a algún otro pin. También probé el módulo SPI 1, pero el problema persiste.

Aquí está mi código:

Configuración de SPI 3:

void Init_SPI3 ( void )
{
IFS5bits.SPI3IF = 0; // Clear the Interrupt flag
IEC5bits.SPI3IE = 0; // Disable the interrupt
// SPI1CON1 Register Settings
SPI3CON1bits.DISSCK = 0; // Internal serial clock is enabled
SPI3CON1bits.DISSDO = 0; // SDOx pin is controlled by the module
SPI3CON1bits.MODE16 = 0; // Communication is word-wide (16 bits)
SPI3CON1bits.SSEN = 0; //No CS
SPI3CON1bits.MSTEN = 1; // Master mode disabled
SPI3CON1bits.PPRE = 2; //Pre-scaler
SPI3CON1bits.SPRE = 8;//Pre-scaler 2
SPI3CON1bits.SMP =1; // Input data is sampled at the middle of data output time
SPI3CON1bits.CKE =0; // Serial output data changes on transition from
SPI3CON1bits.CKP = 0; // Idle state for clock is a low level;
SPI3STATbits.SPIEN = 1; // Enable SPI module
// Interrupt Controller Settings
IFS5bits.SPI3IF = 0; // Clear the Interrupt flag
IEC5bits.SPI3IE = 1; // Enable the interrupt
}

Configuración del pin SPI 3:

TRISBbits.TRISB10 = 0; //Set SPI3CLK as output
TRISBbits.TRISB11 = 0; //Set SPI3DATAOUT as output

RPOR4bits.RP42R=32;  //SPI3_CLK out
RPOR4bits.RP43R=31;  //SPI3_DATA out

Configuración de pin de línea de selección de chip:

TRISBbits.TRISB4 = 0; //SPI3 CS is on Pin B4, set it to Output

Rutina principal simple:

    while(1==1){

    PORTBbits.RB4 = 0;//Set CS line to low  
   WriteSPI3(0xaa); //This is from the peripheral library to be safe....
  PORTBbits.RB4 = 1; //Set CS line to high
                    }

Pero aquí está la salida:

    
pregunta Adil Malik

2 respuestas

1

Desde la hoja de datos y los códigos de ejemplo, el indicador de búfer de recepción es suficiente para indicarnos cuándo se completa el evento de TX y, por lo tanto, el CS puede alternar. Es un poco extraño por qué no hay una bandera para este chip que nos dice cuando el registro de cambio SPI ha transmitido todos sus datos. Todo el código de ejemplo solo verifica el indicador de búfer de recepción.

Después de un montón de rascarse la cabeza, prueba y error y finalmente los foros de microchip, puedo confirmar que este código funciona :

   uint8_t Write_SPI1(uint8_t command) { //Does work    
    SPI1BUF = command; // send data over SPI
    while(!SPI1STATbits.SPIRBF) ; //wait until SPIRBF goes high  
    return SPI1BUF; //KEY STATEMENT THAT MADE A DIFFERENCE, Return the actual data received
    }

Junto con este código, si su periférico depende de la selección de pin periférico (SPI2, SPI3, etc.), es importante definir no solo un SPI Clock Out sino también un SPI Clock In incluso si está en modo maestro

Sin embargo, lo que es bastante desconcertante para mí es que este código (que creo que debería hacer lo mismo) no funciona:

  void Write_SPI1(uint8_t command) { //Does not work, premature toggle of CS, tried this code initially....
    uint8_t garbage;
    SPI1BUF = command; // send data over SPI
    while(!SPI1STATbits.SPIRBF) ; //wait until SPIRBF goes high 
    garbage = SPI1BUF; // read dummy data, does not seem to clear the flag as expected
    }
    
respondido por el Adil Malik
0

Espere hasta que se complete la transmisión de SPI antes de anular la selección del chip con algo como

 while(SPI3_Tx_Buf_Full);  //wait till completion of transmission

Vea el ejemplo que usa SPI1 en enlace

    
respondido por el infixed

Lea otras preguntas en las etiquetas