Moin Leute, ich habe das Problem, dass mein Controller (PIC24EP) in eine Art Dauerschleife geht sobald ich "SPI1BUF = Wert;" ausführe. Ich verschicke am Anfang der Main per UART einen String. Dieser wird einmal verschickt, sobald ich den SPI1BUF auskommentiere. Wenn ich ihn nicht auskommentiere, verschickt mein Controller in wiederholter Schleife immer wieder den String vom Anfang der Main. Wisst ihr, woran das liegen könnte? Vielen Dank!
Das würde ich auch annehmen. Kann die SPI Routine ein Reset erzeugen? Im Grunde mache ich nur:
1 | int SPIWriteRead(int wert){ |
2 | SPI1BUF = wert; |
3 | Nop(); |
4 | while (!SPI1STATbits.SPIRBF); |
5 | return SPI1BUF; |
6 | }
|
Vielleicht solltest du deinen Code komplett posten und jemand mit PIC24 Erfahrung könnte dir weiter helfen. Gibt's einen Watchdog?
1 | #include "libpic30.h" |
2 | |
3 | #include <stdio.h> |
4 | #include <stdlib.h> |
5 | #include <stddef.h> |
6 | #include <stdbool.h> |
7 | #include "xc.h" |
8 | |
9 | #define FP 3685000
|
10 | #define BAUDRATE 9600
|
11 | #define BRGVAL (((FP/BAUDRATE)/16)-1)
|
12 | unsigned int i; |
13 | #define DELAY_105uS asm volatile ("REPEAT, #4201"); Nop(); // 105uS delay
|
14 | |
15 | int befehl = 0; |
16 | int dummy = 0; |
17 | |
18 | void InitGPIO(){ |
19 | |
20 | __builtin_write_OSCCONL(OSCCON & ~(1<<6)); |
21 | |
22 | RPOR6bits.RP56R = 0b000001; |
23 | RPINR18bits.U1RXR = 57; |
24 | |
25 | ANSELB = 0; |
26 | |
27 | //Reset
|
28 | LATBbits.LATB9 = 0; |
29 | ODCBbits.ODCB9 = 0; |
30 | TRISBbits.TRISB9 = 0; |
31 | //DIAG
|
32 | LATCbits.LATC4 = 0; |
33 | ODCCbits.ODCC4 = 0; |
34 | TRISCbits.TRISC4 = 0; |
35 | |
36 | //CS
|
37 | LATBbits.LATB0 = 0; |
38 | ODCBbits.ODCB0 = 0; |
39 | TRISBbits.TRISB0 = 0; |
40 | |
41 | __builtin_write_OSCCONL(OSCCON | (1<<6)); |
42 | |
43 | PORTBbits.RB0 = 1; |
44 | }
|
45 | |
46 | void InitSPI(){ |
47 | |
48 | /* The following code sequence shows SPI register configuration for Master mode */
|
49 | IFS0bits.SPI1IF = 0; // Clear the Interrupt flag |
50 | IEC0bits.SPI1IE = 0; // Disable the interrupt |
51 | |
52 | // SPI1CON1 Register Settings
|
53 | SPI1CON1bits.DISSCK = 0; // Internal serial clock is enabled |
54 | SPI1CON1bits.DISSDO = 0; // SDOx pin is controlled by the module |
55 | SPI1CON1bits.MODE16 = 1; // Communication is word-wide (16 bits) |
56 | SPI1CON1bits.MSTEN = 1; // Master mode enabled |
57 | SPI1CON1bits.SMP = 0; // Input data is sampled at the middle of data output time |
58 | SPI1CON1bits.CKE = 0; // Serial output data changes on transition from |
59 | |
60 | // Idle clock state to active clock state
|
61 | SPI1CON1bits.CKP = 0; // Idle state for clock is a low level; |
62 | |
63 | // active state is a high level
|
64 | SPI1STATbits.SPIEN = 1; // Enable SPI module |
65 | SPI1CON1bits.SSEN = 0; |
66 | |
67 | // Interrupt Controller Settings
|
68 | IFS0bits.SPI1IF = 0; // Clear the Interrupt flag |
69 | IEC0bits.SPI1IE = 1; // Enable the interrupt |
70 | |
71 | DELAY_105uS
|
72 | |
73 | }
|
74 | |
75 | void InitUART(){ |
76 | |
77 | U1MODEbits.STSEL = 0; // 1-Stop bit |
78 | U1MODEbits.PDSEL = 0; // No Parity, 8-Data bits |
79 | U1MODEbits.ABAUD = 0; // Auto-Baud disabled |
80 | U1MODEbits.BRGH = 0; // Standard-Speed mode |
81 | U1BRG = BRGVAL; // Baud Rate setting for 9600 |
82 | U1STAbits.UTXISEL0 = 0; // Interrupt after one TX character is transmitted |
83 | U1STAbits.UTXISEL1 = 0; |
84 | IEC0bits.U1TXIE = 1; // Enable UART TX interrupt |
85 | U1MODEbits.UARTEN = 1; // Enable UART |
86 | U1STAbits.UTXEN = 1; // Enable UART TX |
87 | /* Wait at least 105 microseconds (1/9600) before sending first char */
|
88 | |
89 | DELAY_105uS
|
90 | }
|
91 | |
92 | void UARTSendString(const char* str, const uint8_t length) { |
93 | int i = 0; |
94 | for (i=0 ; i<length && str[i]!='\0' ; i++) { |
95 | UARTSendChar(str[i]); |
96 | }
|
97 | }
|
98 | |
99 | void UARTSendChar(const char c) { |
100 | while (U1STAbits.TRMT == 0); // Wait for buffer to be empty |
101 | U1TXREG = c; |
102 | }
|
103 | |
104 | int SPIWriteRead(int wert){ |
105 | SPI1BUF = wert; |
106 | Nop(); |
107 | while (!SPI1STATbits.SPIRBF); |
108 | return SPI1BUF; |
109 | }
|
110 | |
111 | int main(void) |
112 | {
|
113 | |
114 | if(OSSCON.HFIOFS == 1) |
115 | |
116 | InitGPIO(); |
117 | InitUART(); |
118 | InitSPI(); |
119 | |
120 | |
121 | char* str = "Hello\n\r"; |
122 | UARTSendString(str,29); |
123 | |
124 | PORTBbits.RB9 = 1; |
125 | befehl = 0b1010101010111000; |
126 | |
127 | PORTBbits.RB0 = 0; |
128 | dummy = SPIWriteRead(befehl); |
129 | PORTBbits.RB0 = 1; |
130 | |
131 | while(1){ |
132 | |
133 | }
|
134 | |
135 | }
|
136 | |
137 | void __attribute__((interrupt,auto_psv)) _U1TXInterrupt(void) |
138 | {
|
139 | IFS0bits.U1TXIF = 0; // Clear TX Interrupt flag |
140 | }
|
Daniel V. schrieb: > Vielleicht solltest du deinen Code komplett posten und jemand mit > PIC24 > Erfahrung könnte dir weiter helfen. > Gibt's einen Watchdog? Ich habe keinen Watchdog implementiert.
Daniel V. schrieb: > Du hast keinen SPI InterruptHandler implementiert.... Ist das denn notwendig? Ich finde nirgends Literatur dazu. Laut ISBN: 978-3-645-65273-5 ist keiner notwendig.
PIC schrieb im Beitrag #5490543: > Ist das denn notwendig? Selbstverständlich, da du ja PIC schrieb im Beitrag #5490520: > IEC0bits.SPI1IE = 1; // Enable the interrupt im Code hast. Da hast du ja sogar im Kommentar geschrieben, daß du einen Interrupt haben willst. MfG Klaus
Klaus schrieb: > PIC schrieb im Beitrag #5490543: >> Ist das denn notwendig? > > Selbstverständlich, da du ja > > PIC schrieb im Beitrag #5490520: >> IEC0bits.SPI1IE = 1; // Enable the interrupt > > im Code hast. Da hast du ja sogar im Kommentar geschrieben, daß du einen > Interrupt haben willst. > > MfG Klaus Und ein fehlender Interrupt erzeugt mit ein Reset? Mir ist nicht ganz klar, wie ich den Interrupt programmiere. Ist es das selbe wie beim UART?
Aktivere den Interrupt einfach nicht, dann brauchst du auch keinen Handler dazu. Falls du ihn aktivierst, wir der Controller den entsprechenden Interruptvektor anspringen. Wenn da nix steht, dann gibts halt einen Reset. Ansonsten musst du ihn programmieren wie beim UART.
:
Bearbeitet durch User
Daniel V. schrieb: > Aktivere den Interrupt einfach nicht, dann brauchst du auch keinen > Handler dazu. > Falls du ihn aktivierst, wir der Controller den entsprechenden > Interruptvektor anspringen. Wenn da nix steht, dann gibts halt einen > Reset. Ah klasse! Vielen lieben Dank! Da habe ich nicht ganz zuende gedacht. Wozu wäre ein Interrupt bei einer SPI Routine notwendig?
PIC schrieb im Beitrag #5490559: > Wozu wäre ein Interrupt bei einer SPI Routine notwendig? Gegenfrage: Wozu wäre der Interrupt beim UART notwendig? Immerhin hast du einen implementiert, wenn auch etwas merkwürdig :-)
Hallo Leute, ich habe das ganze jetzt als Interrupt probiert. Leider funktionert die SPI Ansteuerung dann nicht. Wisst ihr woran das liegen könnte? Interrupt ist aktiviert. void __attribute__((interrupt,auto_psv)) _SPI1Interrupt(void) { IFS0bits.SPI1IF = 0; // Clear SPI Interrupt flag PORTBbits.RB0 = 0; SPI1BUF = 0x3D21; while (!SPI1STATbits.SPIRBF); PORTBbits.RB0 = 1; }
Felix schrieb: > Hallo Leute, > > ich habe das ganze jetzt als Interrupt probiert. Leider funktionert die > SPI Ansteuerung dann nicht. Wisst ihr woran das liegen könnte? Interrupt > ist aktiviert. > > void __attribute__((interrupt,auto_psv)) _SPI1Interrupt(void) > { > IFS0bits.SPI1IF = 0; // Clear SPI Interrupt flag > PORTBbits.RB0 = 0; > SPI1BUF = 0x3D21; > while (!SPI1STATbits.SPIRBF); > PORTBbits.RB0 = 1; > } Das da: > while (!SPI1STATbits.SPIRBF); tut man nicht.. In einer ISR sollte man niemals warten. Warum? Weil man alle niederpriorigeren Interrupts blockiert. So kann man beispielsweise ein paar Bytes bei der UART-Kommunikation verpassen. Darum ist das ganz allgemein keine gute Idee. Du möchtest vermutlich das Chipselect bedienen, oder? Da wäre es sinnvoller, das Chipselect des SPI-Modules zu verwenden. Dein Controller hat Peripheral Pin select und SS kann man auf RB0 mappen, soweit ich das gesehen habe. Du hast ein PICkit3, oder? häng mal einen Breakpoint in die ISR. Im Übrigen ist SPIRBF für den Recieve, du meinst vermutlich SPITBF?
jemand schrieb: > Das da: >> while (!SPI1STATbits.SPIRBF); > tut man nicht.. > In einer ISR sollte man niemals warten. Warum? Weil man alle > niederpriorigeren Interrupts blockiert. So kann man beispielsweise ein > paar Bytes bei der UART-Kommunikation verpassen. Darum ist das ganz > allgemein keine gute Idee. Du widersprichst Dir. "Niemals warten" ist natürlich Bullshit. Beim STM32 z.B. ist es sehr sinnvoll, im DMA Stream Interrupt nach dem Transfer Complete auf das Zurücksetzen des BSY-Flags zu warten, bevor man den SPI abschaltet. Generell sind solche Pauschalaussagen Unsinn, auch wenn hier im Forum einige sie penetrant wiederholen. Daher: Hirn einschalten!
Weihnachtsmann schrieb: > Du widersprichst Dir. "Niemals warten" ist natürlich Bullshit. > Beim STM32 z.B. ist es sehr sinnvoll, im DMA Stream Interrupt nach dem > Transfer Complete auf das Zurücksetzen des BSY-Flags zu warten, bevor > man den SPI abschaltet. In der ISR? Das ist nicht dein Ernst, oder? Wie gesagt, ein PIC24 hat priorisierte Interrupts. Du legst alle niederpriorigeren lahm. Warum, zum Henker, sollte man das wollen? Der Controller kan im Endeffekt nicht mehr reagieren. Wenn man Dinge wie Regler oder Überstromabschaltungen drin hat, geht die Schaltung hoch, nur weil man in der ISR auf ein Flag wartet. Das ist sch...schlecht. In diesem Fall gibt es mehrere besser Möglichkeiten: - Chipselect vom SPI-Modul verwenden - Den TX Interrupt so konfigurieren, dass er kommt, sobalt das Senden fertig ist Ich würde das so lösen, wenn man ein Chipselect UNBEDINGT manuell machen will: - TX-Interrupt so konfigurieren, dass er triggert, wenn er mit dem senden fertig ist (Yupp, ein PIC24 kann das) - Chipselect setzen, senden starten - In der ISR Pin rücksetzen oder SPI abschalten oder weitersenden Aber man blockiert in der ISR nicht den ganzen Controller. Auch keinen STM32.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.