Hallo Leute,
ich hab mal wieder ein kleines Problem.
Und zwar tut sich bei mir bei der SPI-Kommunikation nichts.
Ich möchte generell erst mal mit einem Oszi am Pin testen, ob er was
raus gibt...bisher leider nichts...und später möchte ich dann mit einem
AD-Wandler kommunizieren. (MAX11254)
Initialisiert hab ich folgendermaßen:
1
// The following code sequence shows SPI register configuration for Master mode
2
3
IFS0bits.SPI1IF=0;// Clear the Interrupt flag
4
IEC0bits.SPI1IE=0;// Disable the interrupt
5
// SPI1CON1 Register Settings
6
SPI1CON1bits.DISSCK=0;// Internal serial clock is enabled
7
SPI1CON1bits.DISSDO=0;// SDOx pin is controlled by the module
8
SPI1CON1bits.MODE16=1;// Communication is word-wide
9
SPI1CON1bits.MSTEN=1;// Master mode enabled
10
SPI1CON1bits.SMP=0;// Input data is sampled at the middle of data output time
11
SPI1CON1bits.CKE=0;// Serial output data changes on transition from Idle clock state to active clock state
12
SPI1CON1bits.CKP=0;// Idle state for clock is a low level; active state is a high level
13
14
SPI1CON1bits.PPRE=0b01;//prescale 16:1 für 5MHz
15
SPI1CON1bits.SPRE=0b111;//prescale 1:1
16
17
SPI1STATbits.SPIEN=1;// Enable SPI module
18
IFS0bits.SPI1IF=0;// Clear the Interrupt flag
19
IEC0bits.SPI1IE=1;// Enable the interrupt
Prescaler mit 16, da ich maximal 8MHz laut Datenblatt für SPI verwenden
kann. => 80MHz /16 = 5MHz
Meine Einstellungen zur Internen clock:
__builtin_write_OSCCONH(0x01);/* New Oscillator FRC w/ PLL */
7
__builtin_write_OSCCONL(0x01);/* Enable Switch */
8
9
while(OSCCONbits.COSC!=0b001);/* Wait for new Oscillator to become FRC w/ PLL */
10
while(OSCCONbits.LOCK!=1);/* Wait for Pll to Lock */
Ports wurden wie folgt Initialisiert:
CSB=RP28
DOUT=RP29
DIN=RP27
SCLK=RP16
1
ADPCFG=0xFFFF;//Alle Ports auf Digital
2
3
TRISA=0x00;//Ein- und Ausgänge festlegen
4
LATA=0x0024;//Alles auf 0 Setzen, bis auf PWM PINS
5
6
TRISB=0x7C10;//Ein- und Ausgänge festlegen
7
LATB=0x0000;//Alles auf 0 Setzen
8
9
TRISC=0xA08;//Ein- und Ausgänge festlegen
10
LATC=0x0000;//Alles auf 0 Setzen
11
12
__builtin_write_OSCCONL(OSCCON&~(1<<6));// to clear IOLOCK
13
RPINR20=0x1B;//DIN Pin festlegen
14
RPOR14=0x1D00;//DOUT Pin festlegen
15
RPOR14=0x9;//CSB Pin festlegen
16
RPOR8=0x8;//SCLK Pin festlegen
17
__builtin_write_OSCCONL(OSCCON|(1<<6));// to set IOLOCK
Das Senden dann folgendermaßen:
1
while(1)
2
{
3
//Senden
4
IFS0bits.SPI1IF=0;// Clear the Interrupt flag
5
PORTBbits.RB9=0;//CSB auf 0 setzen
6
dummy=SPI1BUF;//Dummy um Puffer zu leeren
7
SPI1BUF=0xD100;//Daten in Puffer schreiben
8
while(!SPI1STATbits.SPITBF)//Warten bis Daten gesendet
9
PORTBbits.RB9=1;//CSB auf 1 setzen
10
}
Jetzt hab ich zm einen das Problem, dass ich mit meinem Oszi nichts am
DOUT messen kann und ich außerdem, nachdem ich mein Programm im
Debug-Modus ausführe, folgende Meldung erhalte:
"Target halted due to Software Breakpoint in user code"
Ich vermute mal, dass sich das Programm in der while-Schleife
festhängt....
hat jemand Ideen?
Chris schrieb:> Jetzt hab ich zm einen das Problem, dass ich mit meinem Oszi nichts am> DOUT messen kann
Hole dir doch erstmal eine Beispielapplikation.
Z.B. Google PIC33F spi example
> und ich außerdem, nachdem ich mein Programm im> Debug-Modus ausführe, folgende Meldung erhalte:> "Target halted due to Software Breakpoint in user code"
Vermutlich passiert das was da steht. Das Programm ist auf einen
Software Breakpoint gelaufen. Woher der kommt wirst du schon rausfinden.
> Ich vermute mal, dass sich das Programm in der while-Schleife> festhängt....
Vermutlich nicht, alle Debugger die ich kenne geben dann keine Meldung
von sich. Sie führen die while Schleife aus.
Hallo Chris,
>IEC0bits.SPI1IE = 1; // Enable the interrupt
wo ist dein InterruptHandler ?
Falls du keinen hast, Interrupt NICHT anmachen. (= 0;)
Ich weiss nicht wo der int-vector default hinzeigt, könnte also auch
einen trap auslösen wenn du keinen handler hast.
Und, ohne das DB zu deiner MCU angesehen zu haben,
vorsichtshalber IMMER die ports die du als SPI benutzen möchtest auf
Input bzw Output setzen, schadet nie, auch wenn einige MCU's das ev
automatisch machen wenn das SPI modul activiert ist.
mfG
Peter
Hallo Ihr zwei,
erstmal vielen Dank für die Antworten.
Das mit dem Software Breakpoint hab ich mit dem Interrupt auf 0 weg
bekommen...
Die Ports sind als Input bzw. Output gesetzt.. aber es passiert immer
noch nichts :-(
Keiner eine Idee?
>"Kurzer Nachtrag...>also meine Clock kann ich mit 2,5MHz messen. Auch mein CSB wird>gesetzt... Aber am Dout kommt nichts raus"
Muss ich korrigieren... hab ich nur, so bald ich Frame auf 1 stelle...
Bei dem Stand, wie das Programm oben beschrieben ist, habe ich nur 4
Ausschläge der Clock....
Examples hab ich mir schon diverse angesehen, aber ich komm nicht drauf,
was noch falsch wäre.... Wäre klasse, wenn mir jemand helfen könnte,
sonst verzweifel ich hier noch!
Hallo Chris,
RPOR14 = 0x1D00; //DOUT Pin festlegen
RPOR14 = 0x9; //CSB Pin festlegen
die beiden schaust du noch mal an, denke das tut nicht so.
zusammenodern.
wobei ich zweifel hab ob es generel richtig gemapt ist.
kenne deinen chip aber nicht u mag nicht das DB hohlen zur zeit.
wenn du #include<spi.h> machst, kannst du auch die bequemlichen PPS
mapping funktionen benutzen:
zb:
PPSUnLock;
iPPSInput(IN_FN_PPS_SDI1, IN_PIN_PPS_RP14);
iPPSOutput(OUT_PIN_PPS_RP13, OUT_FN_PPS_SDO1);
iPPSOutput(OUT_PIN_PPS_RP12, OUT_FN_PPS_SCK1);
PPSLock;
sind ev gut um weniger fehler zu machen, ich mag diese syntax aber auch
nicht.
so, und dann sehe ich noch den hier
SPI1CON1bits.MODE16 = 1;
bist du sicher ?
hier mal eine spi init die ich grad auf meinem browser notebook gefunden
hab,
da hatte ich einen nRF24 dran, weiss grad nicht welcher PIC24/33 es war.
funktioniert aber immer noch, war für eine 2.4Ghz handfernbedienung mit
der ich hier vom Sofa die beleuchtung(RGB LEDs) bunt mache.
void spi_init(void) {
//printf("\nspi_init...");
// set dir and port types first
ANSB = 0; // all digital
TRISBbits.TRISB15 = 0; // *SS1 AN9 RB15
TRISBbits.TRISB13 = 0; // output SDO1/RB13 AN11
TRISBbits.TRISB14 = 1; // input SDI1/RB14 AN10
TRISBbits.TRISB12 = 0; // input SCK1/RB12 AN12
// now spi
SPI1STATbits.SPIEN = 0; // disable SPI port
SPI1STATbits.SPISIDL = 0; // Continue module operation in Idle mode
SPI1BUF = 0; // clear SPI buffer
IFS0bits.SPI1IF = 0; // clear interrupt flag
IEC0bits.SPI1IE = 0; // disable interrupt
SPI1CON1bits.DISSCK = 0; // Internal SPIx clock is enabled
SPI1CON1bits.DISSDO = 0; // SDOx pin is controlled by the module
SPI1CON1bits.MODE16 = 0; // set in 16-bit mode, clear in 8-bit mode
SPI1CON1bits.SMP = 0; // Input data sampled at middle of data
output time
SPI1CON1bits.CKP = 0; // 0 = Idle state for clock is a low level;
active state is a high level
SPI1CON1bits.CKE = 1;
// 1 = Serial output data changes on transition from active
clock state to Idle clock state
// 0 = Serial output data changes on transition from Idle
clock state to active clock state
SPI1CON1bits.MSTEN = 1; // 1 = Master mode; 0 = Slave mode
SPI1CON1bits.SPRE = 0b101; // Secondary Prescaler = 4:1
SPI1CON1bits.PPRE = 0b010; // Primary Prescaler = 4:1
SPI1CON2 = 0; // non-framed mode
// RB15 as SS for SPI slave select
#define SPI_SS_TRIS TRISBbits.TRISB15
#define SPI_SS_PORT PORTBbits.RB15
SPI_SS_PORT = 1; //
SPI_SS_TRIS = 0; // set SS as output
SPI1STATbits.SPIEN = 1; // enable SPI port, clear status
// Interrupt Controller Settings
IFS0bits.SPI1IF = 0; // Clear the Interrupt flag
IEC0bits.SPI1IE = 0; // Disable the interrupt
}
// send and receive 8bit on SPI1, blocks.
uint8_t spi_fast_shift( uint8_t data) {
SPI1BUF = data; // send it
while(!SPI1STATbits.SPIRBF); // wait for transfer to complete
return SPI1BUF;
}
achte bitte auf die spi_fast_shift(), die sendet und empfängt!
deine methode in der while(1){} ist mir sehr suspect.
mfG
Peter ;-)
So,... nachdem ich nun vo PIC alles ordnungsgemäß raus bekomme, hab ich
ein weiteres Problem -.-
Und zwar möchte ich einen MAX11254 24Bit AD-Wandler über mein SPI
auslesen. Wenn der Wandler nicht angeschlossen ist, kann ich mit dem
OSZI am DOUT schön meine einzelnen Bits messen.
So bald ich meinen AD-Wandler anschließe, habe ich an dessen DIN eine
Spannung von 3,3V anliegen. Verbinde ich nun DOUT vom µC mit DIN des
AD-Wandlers, und versuche dann meine Bits zu senden, bekomme ich keine
einzelnen Bits am Oszi zu sehen, sondern eine kontinuierliche Spannung
von ca. 0,7V. => Wenn das der Fall ist, nimmt auch die Stromaufnahme der
Schaltung zu! (um ca. 25mA)
Brauch ich an meinem SPI-BUS noch irgendwie Pullup-Widerstände? Wobei
die mir ja hier eigentlich nicht helfen, da sie ja meinen Spannungspegel
im undefinierten Zustand auf 3,3V ziehen sollten... was ich ja hier
eigentlich hab.
Ich hab auch ein Testboard für den AD-Wandler... auch hier liegen die
3,3V an, so bald die Spannungsversorgung vorhanden ist. Ich denke also,
dass ich keinen Verdrahtungsfehler gemacht habe.
Theoretisch müsste ja der PIC jetzt an seinem DOUT entweder den Pegel
auf GND ziehen, oder auf 3,3V... je nachdem wie mein Bit-Muster aussieht
oder?