Hi, ====NUR INFO============================= ich habe mir gerade die IDE "MPLAB X" installiert und den Hi-Tech C Pro Compiler dazu. Nun Kann ich es einfach nicht abwarten, bis mein "PIC-Einsteiger" Buch da ist und wollte einiges schon Mal in Code bringen. Dazu habe ich als erstes folgenden Beitrag gelesen: http://www.mikrocontroller.net/articles/PIC_Codebeispiele (welcher übrigends nur über google nicht aber hier direkt zu finden ist!?!?) Danach selbstverständlich das Datenblatt zu meinem "PIC16F193X" www.mouser.com/ds/2/268/41364A-75942.pdf Nun habe ich die pic16f1936.h betrachtet, in der steht, dass diese nicht direkt eingebunden werden soll, sondern lieber #include "htc.h" ====PROBLEM======================================= 1. Nun finde ich in den Headern jedoch nicht wirklich den Pfad, der zu der pic16f1936.h führt. Wodurch ein OPTION = 0b11000100; nicht wirklich erkannt wird. 2. Ich bin es von AVR-Studio gewohnt hier Bitshiftign alla (1<< foo) zu benutzen. Doch ich finde keine DEFINE foos ;) 3. Könnt ihr mir zu folgenden Pseudocode für die Register etwas weiterhelfen? Ich meine, vergessene Befehle einfügen und mir die ?? eleminieren? 3.1 Hier der Pseudokram: /****************************************************************** PIC16F193X @ 8MHz ---v--- (Reset) <- RE3|1 28|RB7 -> DIP8 x <- RA0|2 27|RB6 -> DIP7 SPEED <- RA1|3 26|RB5 -> PWM1 DIP6 <- RA2|4 25|RB4 -> DIP5 x <- RA3|5 24|RB3 -> DIP4 x <- RA4|6 23|RB2 -> DIP3 x <- RA5|7 22|RB1 -> DIP2 GND <- VSS|8 21|RB0 -> DIP1 Quartz <- RA7|9 20|VDD ->+5V Quartz <- RA6|10 19|VSS -> GND x <- RC0|11 18|RC7 -> DMX RX PWM3 <- RC1|12 17|RC6 -> x PWM2 <- RC2|13 16|RC5 -> x x <- RC3|14 15|RC4 -> x ------- */ //TODO: //APFCON 0bx1xxxxxx -> CCP3 auf RB5 (0bx0xxxxxx RC6) //APFCON |= (1<<CCP3SEL) //APFCON 0bxxxxxxx0 -> CCP2 auf Rc1 (0bxxxxxxx1 RB3) //BANKSEL PORTA??? //BANKSEL ANSELA??? 0bxx000000 "als Analogen PIN behandeln" deaktivieren //BANKSEL TRISA??? //LATx ??? //TRISA 0bxxxxx11x DIP6+SPEED = Eingang //TRISB 0b11101111 DIPs = Eingang PWM1 = Ausgang //TRISC 0b1xxxx00x DMX RX = Eingang PWM2+3 = Ausgang //WPUB 0b111x1111 Pullups EIN, Nötig? da WPUEN?? //OSCCON 0bx11101x 8Mhz mit internem Oszillator //OPTION_REG 0b0x0x0111 WPUEN = EIN, Timer0 vom internen ocr, mit Prescaler = EIN und 1:256 //PIC-Datenblatt-Kapitel_19: //CCPXCON 0b????11xx PWM aktivieren //CCPXCON 0b??BBxxxx two LSbs of the PWM duty cycle //CCPRxL 0bBBBBBBBB eight MSbs of the PWM duty cycle //CCPTMRS0 0b00000000 CCP1-4 sollen alle den Timer2 nutzen (01:Timer4, 10:Timer6) //CCPTMRS1 0bxxxxxx00 CCP5 Timer2 //PRx //TxCON //CCPRxL //CCPxCON //STRXSYNC = 0 (sofort zwischen Port und PWM wechseln = nicht warten bis PWM vollständig) // //----RS232--- //RCSTA CREN = 1 Empfänger einschalten //TXSTA SYNC = 0 //RCSTA SPEN = 1 //RCREG??? //RCSTA 0b10x1xxxx //BAUDCON 0bxxxxxxx1 Automatische Erkennung EIN // Ich könnte auch einige Denkanstöße zu den Problemen gebrauchen. Auch weil mein Englisch nicht ausgereit hat, um die Funktionen von LATx laut Datenblatt zu begreifen. Danke Oekel
D a v i d K. schrieb: > Nun habe ich die pic16f1936.h betrachtet, in der steht, dass diese nicht > direkt eingebunden werden soll, sondern lieber > #include "htc.h" Ich verwende nicht den HiTech, sondern den alten Microchip C18 Compiler, bei dem einige Sachen anders sind. Vielleicht kann ich Dir trotzdem helfen. > ====PROBLEM======================================= > 1. Nun finde ich in den Headern jedoch nicht wirklich den Pfad, der zu > der pic16f1936.h führt. > Wodurch ein OPTION = 0b11000100; > nicht wirklich erkannt wird. Normal stellst Du im MPLAB den Prozessortyp ein. Der wird dann als Argument an den Compiler übergeben. Im .c mache ich ein #include <pconfig.h> In pconfig.h stehen dann viele, viele Präprozessoranweisungen der Form #if defined(__18F2450) || defined(__18F4450) #define SW_I2C_IO_V2 #endif So werden die nötigen Registerdefinitionen usw eingebunden. Das müßte bei Dir ähnlich funktionieren. > 2. Ich bin es von AVR-Studio gewohnt hier Bitshiftign alla (1<< foo) zu > benutzen. Doch ich finde keine DEFINE foos ;) Stimmt. Findest Du nicht. Aber so etwas vielleicht: extern volatile near unsigned char PSTR1CON; extern volatile near union { struct { unsigned STRA:1; unsigned STRB:1; unsigned STRC:1; unsigned STRD:1; unsigned STRSYNC:1; unsigned :1; unsigned CMPL:2; }; struct { unsigned :6; unsigned CMPL0:1; unsigned CMPL1:1; }; } PSTR1CONbits; Microchip arbeitet nicht mit #defines sondern mit Unions und Bitfeldern. #defines sind ja nicht typsicher, weil die ja am Compiler vorbei laufen. Unions und Structs sind typsicher, das checkt der Compiler. Du kannst also nicht nur sagen: PSTR1CON &= ~CMPLMASK; sondern auch PSTR1CONbits.CMPL=0; > Ich könnte auch einige Denkanstöße zu den Problemen gebrauchen. Auch > weil mein Englisch nicht ausgereit hat, um die Funktionen von LATx laut > Datenblatt zu begreifen. AVR DDR <-> PIC TRIS AVR PIN <-> PIC PORT AVR PORT <-> PIC LAT Beachte, dass die Polarität von DDR bzw TRIS bei PIC genau invertiert gegenüber AVR ist. Bei AVR ist 0 Input, 1 Output. Bei PIC liest Du 0 (Null) als O (Ohh) wie Output, die 1 (Eins) liest Du als I (Ihh) für Input. Nach einem Reset stehen die TRIS-Bits alle auf 1. Beachte auch, dass nicht alle PIC10/12/16 LAT-Register haben. Bei denen, die keine haben, musst Du halt auf PORT schreiben, dabei aber bei Read-Modify-Write aufpassen, weil Du beim Zurücklesen ja nicht das Output-Latch, sondern den Pinzustand liest. Ab PIC18 hast Du immer LAT-Register. Außerdem hat PIC18 Erweiterungen, die es C-Compilern einfacher machen, guten Code zu generieren. Da ich eh keine absoluten Lowend-Anwendungen habe, nehme ich nichts kleineres als PIC18. fchk
Moin, Moin, schau mal bei www.sprut.de vorbei. Da steht vieles in deutscher Sprache. Der Bootloader dort ist in C gemacht und kann Dir als Beispiel dienen. Viel Spaß beim basteln.
Mario schrieb: > Der Bootloader dort ist in C gemacht und kann Dir als Beispiel dienen. Sorry, ich stell mich Mal wieder richtig dumm an, denn ich finde KEINEN Beispielcode in C. Alles ASM Gruß Oekel
D a v i d K. schrieb: > ich finde KEINEN > Beispielcode in C. Alles ASM http://www.sprut.de/electronic/pic/c/c.html
Hi, die Bsp. haben mich etwas weiter gebracht, doch wenn ich mir Quelltext und Header-Datei so anschaue bleiben ein paar Fragen übrig die wohl sehr Compilerspezifisch sind. Daher bitte ich noch Mal die Leute, welche ebenfalls MPLAB und den Hi-Tech C Compiler verwenden mir etwas auf die Sprünge zu helfen. (Alle anderen dürfen natürlich auch, doch ich befürchte dass es nicht allgemeingültig ist) Außer 4. ;) ========Frage 1 ========== Nehmen wir ein Register wie das TxCON, welches ich wie folgt beschreibe: //T1CON Timer 1 TMR1ON = 1; //einschalten nT1SYNC = 1; //nicht mit ext. Takt syncronisieren T1OSCEN = ?; T1CKPS0 = 0; //Prescaler T1CKPS1 = 0; TMR1CS0 = 0;// Timer1 clock source is instruction clock (FOSC/4) TMR1CS1 = 0; Ist dies bereits die einzige Möglichkeit auf das Register zuzugreifen? In der picxx.h wird ja folgendes definiert: ==================CODE================================= volatile union { struct { ........ unsigned TMR1CS0 : 1; unsigned TMR1CS1 : 1; }; struct { unsigned : 4; unsigned T1CKPS : 2; unsigned TMR1CS : 2; }; } T1CONbits @ 0x018; ====================================================== Müsste ich daher nicht auch T1CON.TMR1CS0 = 0; schreiben dürfen? ========Frage 2 ========== Wie schreibe ich etwas in das untere struct? Häufig gibt es dort diese zusammengefassten Bits und ich würde gerne: TMR1CS = 3; // für 0b11 oder direkt: TMR1CS = 0b11; schreiben. Kann/darf ich dies irgendwie? "TMR1CS" wird bereits als unbekannt in der IDE angemarkert. ========Frage 3 ========== "T1CON" kennt er ebenfalls nicht, daher fällt ein T1CON = 0xFF; wohl auch flach!? (========Frage 4 ==========) Kann mir einer die Funktion von dem Bit T1OSCEN erklären? Datenblatt S169: T1OSCEN:LP Oscillator Enable Control bit 1= Dedicated Timer1 oscillator circuit enabled 0= Dedicated Timer1 oscillator circuit disabled ========Frage 5 ========== BANKSEL PORTA Wird dieser Befehl überflüssig in Hi-Tech C? (========Frage 6 ==========) //Main Interrupt Service Routine (ISR) void interrupt ISR() { //Check if it is TMR0 Overflow ISR if(TMR0IE && TMR0IF) { //TODO} Wieso muss ich noch TMR0IE abfragen? Wenn der entsprechnde Interrupt im Register nicht eingeschaltet ist, wird dieser doch auch nie im ISR landen, oder? Ist diese Unterscheidung die einzig mögliche oder kann ich die ISRs auch irgendwie anders trennen? (siehe AVR= separate Funktionsaufrufe mit Vektor) Grüße Oekel
4: Habe jetzt kein DB von 16F193x zur Hand, aber: Timer 1 kann mit einem separaten Low-Power-Oscillator (mit externen Quarz) betrieben werden und in dieser Configuration läuft Timer1 weiter, auch wenn der Controller im SLEEP-Mode ist. Genaues ->> Datenblatt deines Controllers 5: Nein, um Banking und Paging kümmert sich der Compiler. 6: TMR0IE muss man nicht unbedingt unbedingt abfragen, TMR0IF dagegen schon (jedenfalls wenn mehr als 1 Interruptquelle freigeschaltet ist). Die PIC16Fxxxx habe nur eine Interruptvector, die PIC18Fxxxx 2 Vectoren (High/low Priority) und ab PIC24 hat eigentliches jedes Hardwaremodul seinen eigenen Vector(en) und mehrer Prioritätstufen
http://www.gooligum.com.au/tutorials/midrange/PIC_Mid_C_2.pdf http://www.gooligum.com.au/tutorials/midrange/PIC_Mid_C_3.pdf Gruss
D a v i d K. schrieb: > ========Frage 1 ========== > Müsste ich daher nicht auch T1CON.TMR1CS0 = 0; schreiben dürfen? PORTA = 255; PORTAbits.RA0 = 0; LATA = 255; LATAbits = 255; gibt zumindest keine Compilerfehler. LATAbits.LATB0 = 0 Funktioniert so nicht. Ich kann jedoch nicht erkennen, ob dies nur bei der Headerdatei von meinem PIC so ist (also ob diese auch noch für andere gleich geschrieben wurde) oder ob es generell nicht gehen soll. Das struct endet jedenfalls mit: =========================================== // Register: LATB volatile unsigned char LATB @ 0x10D; // bit and bitfield definitions volatile bit LATB0 @ ((unsigned)&LATB*8)+0; ...... #ifndef _LIB_BUILD volatile union { struct { ...... unsigned LATB7 : 1; }; } LATBbits @ 0x10D; #endif =========================================== Grüße David
D a v i d K. schrieb: > PORTA = 255; ist direkt das Register. Normalerweise schreibst Du aber nicht auf PORT, sondern auf LAT, es sei denn, der Controller hat kein LAT. Ein Lehrer würde hier also "sachlich falsch" drunter schreiben. > PORTAbits.RA0 = 0; Ist nur Bit 0. > LATA = 255; Ist direkt das LAT Register von Port A > LATAbits = 255; ist Unsinn. > LATAbits.LATB0 = 0 > Funktioniert so nicht. Schon klar. LATAbits.LATA0 = 0; wäre korrekt. Oder LATBbits.LATB0 = 0; für Port B. fchk
Frank K. schrieb: > sondern auf LAT, es sei denn, der Controller hat kein LAT. Was ich versuche rauszufinden ;) Da die Pic16F193x.h jedoch LAT-Structs aufweißt bin ich verunsichert. > LATAbits.LATA0 = 0; wäre korrekt. > Oder LATBbits.LATB0 = 0; für Port B. Sorry, es ging auch mit richtiger Rechtschreibung zeitweise nicht, weswegen ich dachte, dass dieser PIC vielleicht keine LATs hat (s.o.) Nach einem Neustart von der MPLAB IDE geht es jedoch. if (!LATAbits.LATA0) //also ein Zugriff ist auch erlaubt? Oder dann lieber über den Port direkt? Ich sehe zwar den Sinn des IVA-Prinzips doch in diversen Tutorials kommt dann häufig etwas wie "beim lesen ist es egal..." Egal ist aber keine Richtlinie ;) Grüße Oekel PS: Der Code läuft ja auch ohne Compilerfehler durch, nur möchte ich später nicht in diverse bekannte Fallen tappen.
D a v i d K. schrieb: > doch in diversen Tutorials kommt dann häufig etwas wie "beim lesen ist > > es egal..." Nein es ist nicht egal, genaugenommen das Gegenteil. O-Ton Datenblatt: "A write operation to the LATx register has the same affect as a write to the corresponding PORTx register. A read of the LATx register reads of the values held in the I/O PORT latches, while a read of the PORTx register reads the actual I/O pin value." Sagt eindeutig das ein Schreiben auf LATx denselben Effekt hat wie ein Schreiben auf PORTx. Lesen von LATx liefert den dort hineingeschriebene Zustand und Lesen von PORTx liefert der Zustand des PIN - was nicht identisch mit dem LATx Inhalt sein muss.
Du wirst eventuell in Probleme reinlaufen, wenn Du sowas wie PORTA |= 0x80; schreibst. Dabei wird PORTA (also der Pinzustand) gelesen, verodert und das Ergebnis ins Output Latch geschrieben. Das ist dann sicher nicht das, was Du im Sinn hattest. Bie LATA |= 0x80; wird das Output Latch gelesen, die Veroderung gemacht und das Ergebnis wieder ins Output Latch zurückgeschrieben. Wegen dieser kleinen Fallen merke Dir: Schreibzugriffe auf LAT Lesezugriffe auf PORT (zum Ermitteln des Pinzustandes) Da fällt jeder mal drauf rein, genauso wie die Falle, das nach dem Reset die Analogfunktionen von entsprechen belegten Pins aktiv sind und die entsprechenden Pins erst durch Schreiben auf ADCONx auf Digital umgeschaltet werden müssen, weil sich sonst nix tut. Das ist auch ein beliebter Anfängerfehler. fchk
Hi, ich werde gerade beim Debug total verwirrt. Laut aktuellem Value beim Breakpoint hat mein PORTA = 0b10000000 Ich habe jedoch von außen RA0 auf High gesetzt und nicht RA7. Oder bringe ich da etwas durcheinander, was meine Portzuweisung zu überdenken gilt? Laut Datenblatt ist bei den Port-Registern doch das erste (==linke) Bit das MSB und das letzte (==rechte) das LSB. Also "0b76543210" Sollte dies nun bei den Port-Bytes genau andersherum sein? Also "0b01234567" Oder wird es immer von links nach rechts (LSB -->MSB) gelesen und ich habe mich durch das FIFO meines DMX-Krams einfach nur durcheinander bringen lassen? Grüße Oekel
Nein, Bit 0 ist auch bei PIC immer das niederwertigste (rechteste), und Bit 7 ist das MSB. Code zeigen! Benutzt Du irgendwelche analogen Eingänge? Wenn nicht, musst Du als erstes ANSELA auf 0 setzen, um den Port als digitalen Port benutzen zu können. Siehe mein letztes Posting. Und: Datenblatt lesen hilft. Wirklich. fchk
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.