Ich habe mich sehr bemüht, den SPI-Bus auf einem DSPIC33EP128GM604 zum Laufen zu bringen. Ich habe SPI3 als Standard-8-Bit-Master-Modul konfiguriert und einen Chip-Select-Pin festgelegt, damit ich Slave-Geräte umschalten kann.
Ich bekomme die Chip-Select-Leitung nicht richtig zum Laufen, es scheint, als ob der DSPIC nicht auf den Abschluss der Übertragung wartet, bevor er die Chip-Select-Leitung von LOW auf HIGH umschaltet. Ich habe die Erratas überprüft und nichts scheint für dieses Problem relevant zu sein. Außerdem habe ich versucht, die CS-Leitung auf einen anderen Pin zu tauschen. Ich habe auch SPI-Modul 1 ausprobiert, aber das Problem besteht weiterhin.
Hier ist mein Code:
SPI 3-Konfiguration:
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
}
SPI 3-Pin-Konfiguration:
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
Pin-Konfiguration der Chipauswahlleitung:
TRISBbits.TRISB4 = 0; //SPI3 CS is on Pin B4, set it to Output
Einfache Hauptroutine:
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
}
Aber hier ist die Ausgabe:
Aus dem Datenblatt und den Beispielcodes reicht das Receive Buffer Flag aus, um uns mitzuteilen, wann das TX-Ereignis abgeschlossen ist und der CS somit umschalten kann. Es ist etwas seltsam, warum es für diesen Chip kein Flag gibt, das uns sagt, wann das SPI-Schieberegister alle seine Daten übertragen hat. Der gesamte Beispielcode überprüft nur das Empfangspuffer-Flag.
Nach viel Kopfkratzen, Versuch und Irrtum und schließlich den Mikrochip-Foren kann ich bestätigen, dass dieser Code funktioniert :
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
}
Wenn Ihr Peripheriegerät von der Peripheral Pin Select (SPI2, SPI3 usw.) abhängt, ist es neben diesem Code wichtig, nicht nur einen SPI-Clock-Out, sondern auch einen SPI-Clock-In zu definieren, selbst wenn Sie sich im Master-Modus befinden
Was mich jedoch ziemlich verblüfft, ist, dass dieser Code (von dem ich denke, dass er dasselbe tun sollte) nicht funktioniert:
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
}
Warten Sie, bis die SPI-Übertragung abgeschlossen ist, bevor Sie die Chipauswahl mit so etwas wie deaktivieren
while(SPI3_Tx_Buf_Full); //wait till completion of transmission
Sehen Sie sich das Beispiel mit SPI1 unter http://pat.cybersites.ca/docs/PIC24F/SPI_Example1.html an
while(SPI3STATbits.SPITBF){};
Macht keinen Unterschied, wird das Flag vom Modul irgendwie falsch gesetzt?SPITBF
zeigt nur an, ob sich Bits im Puffer befinden oder nicht, nicht, ob noch gesendet wird. Versuchen Sie nach der while
hinzugefügten Anweisung while(!SPI3STATbits.SPIRBF)
zu warten, bis die Übertragung beendet ist und etwas in den Empfangspuffer gestellt wurde (auch wenn Sie nichts damit tun).SPI3_Tx_Buf_Full
sollte ein Makro sein, das das richtige Bit testet. Sie behaupten CS selbst mit PORTBbits.RB4 = 0
, also müssen Sie es auch selbst zurücknehmen. Sie müssen nur warten, bis das Peripheriegerät die Bits herausgeschoben hat. Wenn die Bibliothek es selbst NACH dem Starten einer Übertragung macht, würde das nur CPU-Zyklen verschwenden, die Sie vielleicht auf andere Weise verwenden möchten. Es kann einen eingebauten Test geben, bevor der nächste Wert in geschrieben wird WriteSPI3
. Aber das ist vor dem Starten des Peripheriegeräts, nicht danachwhile(!SPI3STATbits.SPIRBF)
: Keine Änderung, außer der Tatsache, dass der CS etwas länger behauptet wird und ich nur eine Übertragung erhalte, nach der das Bild nichts tut, so dass es bei dieser While-Anweisung eindeutig eine Schleife durchläuft.void __attribute__((interrupt,auto_psv)) _SPI3Interrupt(void) { PORTBbits.RB4 = 1; }
und setze .SISEL auf 5. Immer noch keine Änderung. Ich fange an zu denken, dass dies ein möglicher Fehler ist?void Write_SPI1 ( int16_t command ) { int16_t temp; PORTBbits.RB7 = 0; // lower the slave select line temp = SPI1BUF; // dummy read of the SPI1BUF register to clear the SPIRBF flag SPI1BUF = command; // write the data out to the SPI peripheral while( !SPI1STATbits.SPITBF ) // wait for the data to be sent out ; PORTBbits.RB7 = 1; // raise the slave select line }
void Write_SPI2 ( int16_t command ) { int16_t temp; PORTBbits.RB6 = 0; // lower the slave select line temp = SPI1BUF; // dummy read of the SPI1BUF register to clear the SPIRBF flag SPI1BUF = command; // write the data out to the SPI peripheral while( !SPI1STATbits.SPIRBF ) // wait for the data to be sent out ; PORTBbits.RB6 = 1; // raise the slave select line }
Scott Seidmann
Scott Seidmann
MAM
Scott Seidmann
MAM
Scott Seidmann
Marco van de Voort