Forum: Projekte & Code PIC Register setzen


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

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

von Frank K. (fchk)


Lesenswert?

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

von Mario (Gast)


Lesenswert?

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.

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

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

von Der Rächer der Transistormorde (Gast)


Lesenswert?

D a v i d K. schrieb:
> ich finde KEINEN
> Beispielcode in C. Alles ASM

http://www.sprut.de/electronic/pic/c/c.html

von DerDateiWühler (Gast)


Lesenswert?

Siehe die ersten beiden Suchergebnisse:

http://l m g t f y.com/?q=PIC+C

von DerDateiWühler (Gast)


Lesenswert?


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

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

von Chris B. (dekatz)


Lesenswert?

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

von Erich (Gast)


Lesenswert?


von D a v i d K. (oekel) Benutzerseite


Lesenswert?

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

von Frank K. (fchk)


Lesenswert?

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

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

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.

von Chris B. (dekatz)


Lesenswert?

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.

von Frank K. (fchk)


Lesenswert?

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

von D a v i d K. (oekel) Benutzerseite


Lesenswert?

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

von Frank K. (fchk)


Lesenswert?

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
Noch kein Account? Hier anmelden.