Hallo Leute, ich bin ganz neu bei diesem forum. Ich wollte einen Interrupt mit dem PIC18F27J13 programmieren aber ich bekomme fehlermeldungen. Ich möchte daten über SPI senden wenn ein Interrupt da ist aber davor sollten der Akkumulator Status und BSR vorher geretet werden. Das Programm habe ich wie folgt geschrieben: #define USE_OR_MASKS #include <stdio.h> #include <stdlib.h> #include <pconfig.h> #include <xc.h> #include <plib/adc.h> #include "adc.h" #include <plib/spi.h> #include "spi.h" #include <pic18f27j13.h> #pragma config CONFIG1L = 0x2C #pragma config CONFIG1H = 0x4 #pragma config CONFIG2L = 0x0A #pragma config CONFIG2H = 0xF #pragma config CONFIG3L = 0xFF #pragma config CONFIG3H = 0x8 #pragma config CONFIG4L = 0xFF #pragma config CONFIG4H = 0x3 unsigned char W_TEMP = 0x00; unsigned char STATUS_TEMP = 0x00; unsigned char BSR_TEMP = 0x00; unsigned char DATA_TO_SPI2[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void high_isr(void); /*asm(" W_TEMP SET 0h"); asm(" BSR_TEMP SET 0h"); asm(" STATUS_TEMP SET 0h"); */ #pragma code high_vector = 0x08 void interrupt_at_high_vector(void) { _asm goto high_isr _endasm } #pragma code #pragma interrupt high_isr void high_isr(void) { _asm{ MOVWF _W_TEMP MOVFF STATUS, _STATUS_TEMP MOVFF BSR, _BSR_TEMP ; } for(unsigned int n=0; n<2; ++n) { if(INTCONbits.TMR0IF && INTCONbits.TMR0IE) { getsSPI2(info, 1); INTCONbits.TMR0IF = 0; INTCONbits.TMR0IE = 0; if((info[0] & 0x60) == 0x20) { if(INTCONbits.TMR0IF && INTCONbits.TMR0IE) { WriteSPI2(DATA_TO_SPI2[(n + 2*((info & 0x18) >> 3))]); while(PIR3bits.SSP2IF != 1); INTCONbits.TMR0IF = 0; INTCONbits.TMR0IE = 0; } } } } _asm{ MOVFF _BSR_TEMP, BSR MOVF _W_TEMP, W MOVFF _STATUS_TEMP, STATUS } } Das sind die Fehlermeldungen. Build C:\interrupt for device 18F27J13 Using driver C:\Program Files\Microchip\xc8\v1.12\bin\xc8.exe Make: The target "C:\interrupt.p1" is out of date. Executing: "C:\Program Files\Microchip\xc8\v1.12\bin\xc8.exe" --pass1 C:\interrupt.c -q --chip=18F27J13 -P --runtime=default --opt=default -N-1 -D__DEBUG=1 -g --asmlist "--errformat=Error [%n] %f; %l.%c %s" "--msgformat=Advisory[%n] %s" "--warnformat=Warning [%n] %f; %l.%c %s" Warning [335] C:\interrupt.c; 36.1 unknown pragma "code" Error [195] C:\\interrupt.c; 39.1 expression syntax Error [312] C:interrupt.c; 42.1 ";" expected Warning [335] C:\interrupt.c; 44.1 unknown pragma "code" Warning [335] C:\interrupt.c; 45.1 unknown pragma "interrupt" Error [195] C:\interrupt.c; 48.1 expression syntax Error [285] C:\interrupt.c; 53.1 no identifier in declaration Warning [374] C:\interrupt.c; 53.1 missing basic type; int assumed Error [314] C:\interrupt.c; 53.1 ";" expected Warning [374] C:\interrupt.c; 53.24 missing basic type; int assumed Error [314] C:\interrupt.c; 53.24 ";" expected Error [285] C:\interrupt.c; 53.28 no identifier in declaration Warning [374] C:\interrupt.c; 53.28 missing basic type; int assumed Error [314] C:\interrupt.c; 53.28 ";" expected Warning [374] C:\interrupt.c; 58.11 missing basic type; int assumed Error [984] C:\interrupt.c; 58.11 type redeclared Error [1098] C:\interrupt.c; 58.11 conflicting declarations for variable "INTCONbits" (C:\Program Files\Microchip\xc8\v1.12\include\pic18f27j13.h:15907) (908) exit status = 1 ********** Build failed! ********** kann mir jemandem Helfen? Ich brauche dringend bitte Hilfe. Danke
Im Manual zum XC8 Compiler steht, wie man Interrupts verwendet. Ist glaube ich nicht so, wie du das gelöst hast (hab jetzt nicht nachgeschaut). In den Fehlermeldungen steht ja schon, dass er einige pragmas nicht kennt. Noch ein Tipp: Wenn du globale Variablen in Interruptfunktionen verwendest, deklariere sie als volatile.
Hallo, danke für deine Antwort hab nachgeschaut und hat viel geholfen. Aber wenn ich die variable als volatile deklariere bekomme ich folgenden Fehlermeldungen: Warning [359] C:\code.c; 63.14 illegal conversion between pointer types pointer to volatile unsigned char -> pointer to unsigned char
ich brauche glaube ich zwei interrupts: eins der mir meldet, dass der Master das read command gesendet hat weil der Master verschiedene Daten senden kann und zwar jeder Zeit, eins der das Laufen des gesamten Programms unterbricht und die daten über SPI senden. ich habe dann die interrupts so geschrieben: volatile unsigned char info[1] = { 0x00 }; volatile unsigned char data_send[4] = { 0xAB, 0x48, 0x69, 0x00}; void interrupt isrmssp2(void) { if(PIR3bits.SSP2IF && PIE3bits.SSP2IE) { getsSPI2(info, 1); if(((unsigned char)info[0] & 0x60) == 0x20) { TMR0IF = 1; TMR0IE = 1; return; } } } void interrupt isr(void) { if(TMR0IF && TMR0IE) { TMR0IF = 0; putsSPI2((unsigned char *)data_send); return; } } void main() { RCONbits.IPEN = 0; INTCONbits.PEIE = 1; INTCONbits.GIE = 1; T0CONbits.T08BIT = 0; T0CONbits.T0CS = 0; T0CONbits.PSA = 0; T0CONbits.TMR0ON = 1; INTCON2bits.INTEDG0 = 1; INTCONbits.GIE = 1; } aber wenn ich die empfangenen Daten des Masters anschaue, dann sind sie falsch. Was mache ich bitte da falsch?
Ist das dein gesamtes Programm? Ich weiss nicht was passiert, wenn das main verlassen wird. Also besser noch eine Endlosschleife einfügen. Geht er in die richtige Interruptroutine rein, wenn der Master Daten sendet? Du sagst, die Daten sind falsch. Was erwartest du und was kommt raus? Wie stellst du die empfangenden Daten dar? Es erscheint mir auch komisch, dass du das Timer0 Interrupt manuell auslöst. Evt. geht dort etwas schief. salade Poisson schrieb: > TMR0IF = 1; > TMR0IE = 1; Müsste wohl heissen: INTCONbits.TMR0IF = 1; INTCONbits.TMR0IE = 1;
Das Programm das ich geschrieben habe sieht so aus: #define USE_OR_MASKS #include <stdio.h> #include <stdlib.h> #include<pconfig.h> #include <xc.h> #include <plib/spi.h> #include "spi.h" #include <pic18f27j13.h> #include <math.h> #pragma config CONFIG1L = 0x2C #pragma config CONFIG1H = 0x4 #pragma config CONFIG2L = 0x0A #pragma config CONFIG2H = 0xF #pragma config CONFIG3H = 0x8 #pragma config CONFIG4L = 0xFF #pragma config CONFIG4H = 0x3 unsigned char count = 0x00; unsigned char data_rcv[1] = { 0x00 }; unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xAA, 0xAB, 0xCD, 0xFA, 0xBD, 0xE5 }; void Set_SPI(void) { unsigned char sync_mode_SPI = 0; unsigned char bus_mode_SPI = 0; unsigned char smp_mode_SPI = 0; RPINR21 = 7; RPINR22 = 6; RPINR23 = 8; RPOR5 = 10; ANCON1bits.PCFG8 = 1; ANCON1bits.PCFG9 = 1; TRISBbits.TRISB2 = 0; TRISBbits.TRISB3 = 1; TRISBbits.TRISB4 = 1; TRISBbits.TRISB5 = 1; sync_mode_SPI = SLV_SSON; bus_mode_SPI = MODE_01; smp_mode_SPI = SMPMID; OpenSPI2(sync_mode_SPI, bus_mode_SPI, smp_mode_SPI); } void initPIC (void) { OSCCONbits.SCS = 0b11; OSCCONbits.IRCF = 0b110; RCONbits.IPEN = 0; INTCONbits.PEIE = 1; T0CONbits.T08BIT = 1; T0CONbits.T0CS = 0; T0CONbits.PSA = 0; T0CONbits.T0PS = 0b111; INTCON2bits.INTEDG0 = 1; INTCONbits.GIE = 1; INTCONbits.GIE = 1; T0CONbits.TMR0ON = 1; PIE3bits.SSP2IE = 1; } void interrupt int(void) { if(INTCONbits.TMR0IF && INTCONbits.TMR0IE) { TMR0IF = 0; WriteSPI2(data[(unsigned int)count]); while(PIR3bits.SSP2IF != 1); if(count == 11) { count = 0; } else{ count++; } return; } } void interrupt isr(void) { if(PIR3bits.SSP2IF && PIE3bits.SSP2IE) { getsSPI2(data_rcv, 1); PIR3bits.SSP2IF = 0; if(data_rcv[0] == 0x20) { INTCONbits.TMR0IE = 1; return; } } } void main (void) { Set_SPI(); initPIC(); for(;;) { ; } } und der master bekommt immer die selbe daten. Die Funktion mit dem interrupt int funktioniert schön weil wenn ich das count incrementiere und dann data[count] am Master sende, dann bekomme ich die soll-daten aber wenn ich das wie oben schreibe dann sendet der Master immer 0xFE Er geht eigentlich nicht in die funktion isr rein. hast du ne Idee warum?
hallo, wie kann ich merken dass daten über SPI liegen? brauche ich dafür einen Interrupt zu programmieren der ausgelöst wird wenn daten über SPI liegen?
salade Poisson schrieb: > brauche ich dafür einen > Interrupt zu programmieren der ausgelöst wird wenn daten über SPI > liegen? Da gibt es irgendwo ein Bit in einem Register. Das wird gesetzt wenn Daten über die SPI angekommen sind. Ist der entsprechende Interrupt freigegeben wird er dann auch ausgelöst. Du kannst ihn aber auch sperren und per Programm abfragen. Generell ist es beim PIC alle Interrupts zu einer Adresse springen (die zweite mal weggelassen). Beim Interrupt wird dann die Funktion die dort beginnt ausgeführt. Alle freigegebenen Interrupts abzuarbeiten und die Flags zurückzusetzen ist dann dein Job.
Hallo, ich hab so ein problem: ich wollte mein temperaturmesssystem kalibirieren. ich habe es gemacht aber das problem ist wenn ich keine Daten über SPI empfange oder sende dann funktioniert die Kalibrierung, aber wenn ich daten über SPI empfange dann funktioniert die Kalibrierung nicht mehr. Ich brauche dann eine neue Kalibrierung. Die SPI beeinflusst dann mein Ergebnis. Weiß jemand der Grund dafüR
Deine Fragen oder Probleme sind wohl nur zu lösen, wenn du auch die komplette Beschaltung deines uC veröffentlichst, insbesondere die SPI Signale und alle dort angeschlossenen Komponenten. Vermutlich kommt sich was irgendwie "in die Quere". Evt. solltest du die Funktionalitäten SPI erstmal ohne Interrupt-Nutzung herstellen. Ob für SPI der Interruptfunktionalität überhaupt sinnvoll ist kann man erst sehen wenn man das komplette System sieht, und auch die Datenraten bzw. Clockraten bekannt sind. Für sporadische oder langsame (< 10 Hz) Abfrage eines Temperatursensors würde ich das nicht über Interrupt machen. Gruss
Hallo war mein Fehler. Hatte falsche Daten gesendet deshalb hatte er falsche Rechnungen durchgeführt. Meine frage ist wie kann ich mit dem Interrupt daten Auslesen und sie in einem Puffer schreiben? Ich lese Daten aus aber ich habe den Eindruck dass er Sie nicht speicher. Ich hab es wie folgt gemacht: unsigned char info[1] = { 0x00 }; unsigned char data_rcv[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; //{ 0x67, 0x68, 0x77, 0x7F, 0x00 }; unsigned char data_send[11] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void interrupt isr5(void) { if(PIR3bits.SSP2IF && PIE3bits.SSP2IE) { getsSPI2(info, 1); switch(info[0] & 0x78) { case 0x60: data_rcv[0] = info[0]; break; case 0x68: data_rcv[1] = info[0]; break; case 0x70: data_rcv[2] = info[0]; break; case 0x78: data_rcv[3] = info[0]; break; default: break; } if((( info[0] & 0x60 ) == 0x40 )) { switch(((info[0] >> 3 ) & 0x03)) { case 0x00: data[1] = data_send[0]; data[0] = data_send[1]; break; case 0x01: data[1] = data_send[2]; data[0] = data_send[3]; break; case 0x02: data[1] = data_send[4]; data[0] = data_send[5]; break; case 0x03: data[1] = data_send[6]; data[0] = data_send[7]; break; default: data[1] = data_send[8]; data[0] = data_send[9]; break; } putsSPI2(data); info[0] = 0x00; } return; } } zum sehen ob der slave die Daten empfängt hab ich folgendes main geschrieben: void main (void) { float temp = 14450.0; unsigned char nun = 0x00; unsigned char configdata[5] = { 0x00, 0x00, 0x00, 0x00, 0x00 }; Set_SPI(2); initPIC(); SSP2BUF =0; RCONbits.IPEN = 0; INTCONbits.PEIE = 1; INTCONbits.GIE = 1; PIR3bits.SSP2IF = 0; IPR3bits.SSP2IP = 1; PIE3bits.SSP2IE = 1; for(unsigned int i=0; i<4; ++i) { num = ( data_rcv[i] >> 3 ) & 0x03; switch(num) { case 0x00: temp = temp / 2; data_send[0] = ( signed int ) ( temp / 256 ); data_send[1] = ( signed int )temp%256; break; case 0x01: temp = temp / 3; data_send[2] = ( signed int ) ( temp / 256 ); data_send[3] = ( signed int ) temp%256; break; case 0x02: temp = temp / 4; data_send[4] = ( signed int ) ( temp / 256) ; data_send[5] = ( signed int ) temp%256; break; case 0x03: temp = temp / 5; data_send[7] = ( signed int )Temperature%256; break; default: temp = temp / 6; data_send[8] = ( signed int ) ( temp / 256 ); data_send[9] = ( signed int )temp%256; break; } } } }while(1) continue; } Wenn ich data mit Null initialisiere dann führt er keine Rechnung aus und er sendet nur dummi daten an Master. Aber wenn ich den mit gultigen Informationen initialisiere dann macht er die Rechnungen und er sendet die Daten an Master wenn gefordert. ich brauche die Daten vom Master auszulesen weill ich Sie Später für die Berechnung verwenden soll. Weißt du woran es liegt
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.