Schönen Tag alle zusammen. Dies ist mein erster Eintrag in diesem Forum und schon kommen Probleme. Leider half mir dieses mal die SuFu nicht. Ich habe begonnen zu Hobbyzwecken (Synthesizer) 16bit PIC Controller zu programmieren. Ich habe bereits erfolgreich mit 8bit Typen gearbeitet. Nun ist ein für mich unerklärliches Problem aufgetreten. Ich programmiere mit MPLab X und C und brenne mit PicKit3. Ziel ist es mit SPI ein DAC anzusprechen. SPI funktioniert fast. Und hier liegt das Problem. SS und Data Output funktionieren. Am Oszilloskop kann ich die richtige Bitfolge ablesen. Nur der SPI CLK tut rein gar nichts. Ich habe ein leichtes Übersprechen (durch lange Parallele Leiterbahnen) der Data Output Leitung. Deshalb denke ich, dass der Pin nicht als Output konfiguriert ist da Hochohmig. Ich verwende den PIC pic24fj16mc101, das Pinout habe ich oben angehängt. Unten folgt der Code mit dem ich die SPI Peripherie konfiguriere. [c] #define SPI_SS_TRIS TRISBbits.TRISB4 #define SPI_SS_PORT PORTBbits.RB4 void SPI1Init(void) { //config SPI1 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 = 1; // set in 16-bit mode, clear in 8-bit mode SPI1CON1bits.SMP = 0; // Input data sampled at mid of data output time SPI1CON1bits.CKP = 1; // CKP and CKE is subject to change ... SPI1CON1bits.CKE = 1; // ... based on your communication mode. SPI1CON1bits.MSTEN = 1; // 1 = Master mode; 0 = Slave mode SPI1CON1bits.SPRE = 4; // Secondary Prescaler = 4:1 SPI1CON1bits.PPRE = 2; // Primary Prescaler = 4:1 SPI1CON2 = 0; // non-framed mode SPI_SS_TRIS = 0; // set SS as output SPI1STATbits.SPIEN = 1; // enable SPI port, clear status } [\c] Gesendet wird indem einfach ins entsprechende Register geschrieben wird. Den SS betätige ich momentan selber. Werde das dann noch ändern, ist aber nicht Teil des Problems. [c] unsigned short data = 0xAFAF; SPI1BUF = data; [\c] Das Programm macht nun folgendes. SS und SPO funktionieren. SPI CLK macht nichts. Ich habe versucht ohne das ganze SPI Zeugs den PIN RB7 (der PIN der mit dem SPI Clock belegt wird, falls SPI aktiv ist.) einfach mal über die entsprechenden TRIS und PORT Register auf High zu schalten. Für alle anderen Pins des B Registers gehts auch, nur nicht für diesen. Was ich bis jetzt ausschliessen kann: - Der SPI CLK kann nicht über remappable peripheral gemappet werden. (Laut Datasheet) Mir fehlt nun der Ansatz das Problem zu lösen. Falls also jemand bereits ein ähnliches Problem lösen konnte könntet ihr mir sehr helfen. Gruss Wipffinder
Wie werden die Pins initialisiert? Hast du auf irgend einem anderen Pin das CLK Signal? Wie werden die Pins gemappt (sicher das es richtig ist?). Richtig die configs gesetzt? Hab mir mal den Beispielcode angesehen:
1 | #include "p24fxxxx.h" |
2 | |
3 | #ifdef __PIC24FJ128GA010__ //Defined by MPLAB when using 24FJ256GB110 device |
4 | // JTAG/Code Protect/Write Protect/Clip-on Emulation mode |
5 | // Watchdog Timer/ICD pins select |
6 | _CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2) |
7 | // Disable CLK switch and CLK monitor, OSCO or Fosc/2, HS oscillator, |
8 | // Primary oscillator |
9 | _CONFIG2(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMOD_HS & FNOSC_PRIPLL) |
10 | #endif |
11 | |
12 | // RB2 as SS for SPI slave MCU |
13 | #define SPI_SS_TRIS TRISBbits.TRISB2 |
14 | #define SPI_SS_PORT PORTBbits.RB2 |
15 | |
16 | unsigned short spiBufT[]={0x00ac,0x05a0,0xa500,0}; // for demo only |
17 | unsigned short spiBufR[]={0,0,0,0}; // SPI buffer for Receiving |
18 | |
19 | void SPI1Init(void) |
20 | { |
21 | //config SPI1 |
22 | SPI1STATbits.SPIEN = 0; // disable SPI port |
23 | SPI1STATbits.SPISIDL = 0; // Continue module operation in Idle mode |
24 | |
25 | SPI1BUF = 0; // clear SPI buffer |
26 | |
27 | IFS0bits.SPI1IF = 0; // clear interrupt flag |
28 | IEC0bits.SPI1IE = 0; // disable interrupt |
29 | |
30 | SPI1CON1bits.DISSCK = 0; // Internal SPIx clock is enabled |
31 | SPI1CON1bits.DISSDO = 0; // SDOx pin is controlled by the module |
32 | SPI1CON1bits.MODE16 = 1; // set in 16-bit mode, clear in 8-bit mode |
33 | SPI1CON1bits.SMP = 0; // Input data sampled at middle of data output time |
34 | SPI1CON1bits.CKP = 1; // CKP and CKE is subject to change ... |
35 | SPI1CON1bits.CKE = 0; // ... based on your communication mode. |
36 | SPI1CON1bits.MSTEN = 1; // 1 = Master mode; 0 = Slave mode |
37 | SPI1CON1bits.SPRE = 4; // Secondary Prescaler = 4:1 |
38 | SPI1CON1bits.PPRE = 2; // Primary Prescaler = 4:1 |
39 | |
40 | SPI1CON2 = 0; // non-framed mode |
41 | |
42 | SPI_SS_PORT = 1; // |
43 | SPI_SS_TRIS = 0; // set SS as output |
44 | |
45 | SPI1STATbits.SPIEN = 1; // enable SPI port, clear status |
46 | } |
47 | |
48 | unsigned short writeSPI1( unsigned short data ) |
49 | { |
50 | SPI1BUF = data; // write to buffer for TX |
51 | while(!SPI1STATbits.SPIRBF); // wait for transfer to complete |
52 | return SPI1BUF; // read the received value |
53 | }//writeSPI1 |
54 | |
55 | int main (void) |
56 | { |
57 | unsigned short i; |
58 | |
59 | // Disable Watch Dog Timer |
60 | RCONbits.SWDTEN = 0; |
61 | // for LED |
62 | ODCAbits.ODA6 = 0; |
63 | TRISAbits.TRISA6 = 0; |
64 | |
65 | SPI1Init(); |
66 | |
67 | while (1) { |
68 | for (i=0; i<0xffff; i++); // a simple delay |
69 | |
70 | SPI_SS_PORT = 0; |
71 | spiBufR[0] = writeSPI1(spiBufT[0]); |
72 | spiBufR[1] = writeSPI1(spiBufT[1]); |
73 | spiBufR[2] = writeSPI1(spiBufT[2]); |
74 | spiBufR[3] = writeSPI1(0); |
75 | SPI_SS_PORT = 1; |
76 | |
77 | __builtin_btg((unsigned int *)&LATA, 6); |
78 | } |
79 | |
80 | return 0; |
81 | } |
:
Bearbeitet durch User
>Wie werden die Pins initialisiert? Nachdem SPIenable auf 1 gesetzt wird, funktioniert der SDO (SPI DATA OUT) und der SS bereits richtig. Ich brauche also nicht vorher die Pins über TRISx = 0x0000 als Output zu initialisieren. Nur der CLK geht halt nicht. Auch wenn ich diesen Pin vorher über das TRIS Register als Output setzte, geht der CLK nicht. >Hast du auf irgend einem anderen Pin das CLK Signal? Das CLK Signal befindet sich auf keinem anderen Pin, habe alle durchprobiert und nichts gefunden. >Wie werden die Pins gemappt (sicher das es richtig ist?). Auf die Pins die gemappet werden können, kann nur der SPI SS gemappt werden, andere SPI Peripherie ist an den vorgegebenen Pin gebunden. >Richtig die configs gesetzt? Der Code den du gepostest hast ist genau der den ich verwendet habe. Kann es sein das nach dem Reset bereits eine Peripherie standartgemäss aktiv ist? Im Pinout stehen für den Pin der SPI CLK folgende Möglichkeiten: FLTA1/SCK1/INT0/RP7/CN23/RB7 Ich kann SCK1 und RB7 nicht als Output nutzen. Ich vermute im Moment, dass es am FLTA1 liegt, aber ich begreif einfach das Datasheet nicht. Laut Datasheet The PWM Fault pins are enabled and asserted during any reset event. Refer to Section 15.2 “PWM Faults” for more information on the PWM faults. Nur leider finde ich dort nicht mehr Informationen (die ich verstehe).
Wipffinder schrieb: > Ich kann SCK1 und RB7 nicht als Output nutzen. Ich vermute im Moment, > dass es am FLTA1 liegt, aber ich begreif einfach das Datasheet nicht. Setze mal die PxFLTACON Register auf 0. Damit sollte der Pin freigegeben werden. Das Schreiben erfordert eine Unlock-Sequenz, die auf Seite 142 des Datenblatts steht. fchk
@Frank K. Genau das war das Problem, danke vielmals. Nun noch zwei Fragen: - Warum gibt es diese Unlocksequenz bzw. warum ist das Register gesperrt? - Mir funktioniert die Unlocksequenz nur mit Inlineassembler [c] asm("mov #0xabcd,w10"); asm("mov #0x4321,w11"); asm("mov #0x0000,w0"); asm("mov w10, PWM1KEY"); asm("mov w11, PWM1KEY"); asm("mov w0,P1FLTACON"); [\c] mit c gehts nicht [c] PWM1KEY = 0xABCD; PWM1KEY = 0x4321; P1FLTACON = 0x0000; [\c] Ist der Umweg über die Register w10, w11 und w0 Teil der Unlocksequenz? Dankbare Grüsse Wipffinder
Ob das wirklich mit dem Problem des TO zu tun hat, weiß ich nicht, aber in C geht's so
1 | __builtin_write_PWMSFR(&P1FLTACON, 0x0000, &PWM1KEY); |
MfG Klaus
Wipffinder schrieb: > @Frank K. > Genau das war das Problem, danke vielmals. > Nun noch zwei Fragen: > - Warum gibt es diese Unlocksequenz bzw. warum ist das Register > gesperrt? Dieser Pin ist Teil einer Hardware-Sicherheitsfunktion und soll nicht versehentlich abgeschaltet werden können, wenn das Programm Amok läuft. > [\c] nimm den / und nicht den \ > mit c gehts nicht > PWM1KEY = 0xABCD; > PWM1KEY = 0x4321; > P1FLTACON = 0x0000; Die drei Schreibzugriffe müssen innerhalb einer bestimmten Anzahl an Takten passieren, sonst wird nicht entsperrt. Das macht der C-Code nicht. Das gibts auch an anderen Stellen bei PIC24/dsPIC
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.