Forum: Mikrocontroller und Digitale Elektronik PIC24F32KA302 UART-Konfiguration


von Konstantin H. (aerokos)


Lesenswert?

Hallo!

Ich arbeite an einem Kleinen Bastelprojekt und bin auf ein Problem 
gestoßen. Die Verbindung von meiner Platine mit dem Rechner will einfach 
nicht funktionieren.

Als Ziel ist eine Datenübertragung von 8000+ bits pro Sekunde bei einer 
Baudrate von 115200 von der Platine zum Rechner. Die bits sollen im 
8-bit-Mode mit einem Stopbit ohne Parität und ohne HW-Flusskontrolle.

Zwischenziel sind funktionierende Sende- und Empfangsfunktionen bei 
einer niedrigeren Baudrate von 9600.

Ich verwende folgende Konfiguration:
1
//code protection off & write protection off (boot segment)
2
_FBS(BSS_OFF & BWRP_OFF)
3
//code protection off & write protection off (general segment)
4
_FGS(GSS0_OFF & GWRP_OFF)
5
//8MHz + PLL & internal-external switchover off (oscillator selection)
6
_FOSCSEL(FNOSC_PRIPLL & IESO_OFF)
7
//HS oscillator mode selected & 2nd osc low power, frequency range >8MHz & CLKO OFF & Both Clock Switching and Fail-safe Clock Monitor are enabled (oscillator)
8
_FOSC(POSCMOD_HS & SOSCSEL_SOSCLP & POSCFREQ_HS & OSCIOFNC_OFF & FCKSM_CSECME)
9
//WDT off & windowed WDT off(watchdog timer)
10
_FWDT(FWDTEN_OFF & WINDIS_OFF)
11
//reset pin off & standard i2c-pins & power up timer off(reset config)
12
_FPOR(MCLRE_ON & I2C1SEL_PRI & PWRTEN_OFF & BORV_V18 &  LVRCFG_OFF & BOREN_BOR0)
13
//Deep sleep WTD OFF, Deep Sleep BOR OFF(deep sleep)
14
_FDS(DSWDTEN_OFF & DSBOREN_OFF)

Diese config soll bezwecken, dass der interne clock mit 16 MHz läuft. 
(8*4)/2

Als Init-Funktion benutze ich:
1
void UART_Init(void)
2
{
3
  TRISBbits.TRISB0 = 0;        //TX-Pin Output
4
  TRISBbits.TRISB1 = 1;        //RX-Pin Input
5
6
  U2MODEbits.STSEL = 0;    //One Stop bit
7
  U2MODEbits.PDSEL = 0b00;        //8-bit data, no parity
8
  U2MODEbits.BRGH = 1;    //BRG generates 4 clocks per bit period (4x baud clock, High-Speed mode)
9
  U2MODEbits.RXINV = 0;    //No invertion
10
  U2MODEbits.ABAUD = 0;    //Baud rate measurement is disabled or completed
11
  U2MODEbits.UEN = 0b00;          //UxTX and UxRX pins are enabled and used; UxCTS and UxRTS/UxBCLK pins are controlled by port latches
12
  U2MODEbits.IREN = 0;    //IrDA encoder and decoder are disabled
13
14
        U2BRG = 25;                     //9600 Baud (0.16%) @32MHz (16MIPS)
15
16
  U2MODEbits.UARTEN = 1;          //UART2 is enabled; all UART2 pins are controlled by UART2 as defined by UEN<1:0>
17
18
  U2STAbits.UTXEN = 1;    //Transmit is enabled, UxTX pin is controlled by UARTx
19
}

Kann vllt jmd. sehen wo das Problem sein könnte?

Gruß Konstantin

von Max H. (hartl192)


Lesenswert?

Konstantin H. schrieb:
> Die Verbindung von meiner Platine mit dem Rechner will einfach
> nicht funktionieren.
Kannst du das genauer spezifizieren?

> U2BRG = 25;        //9600 Baud (0.16%) @32MHz (16MIPS)
Wie bist du auf U2BRG = 25 gekommen?
Ich komme auf:
U2BRG = 25 würde eine Baudrate von 166.7kBd entsprechen.

Wie sehen die Sende- und Empfangsfunktionen aus?

: Bearbeitet durch User
von Konstantin H. (aerokos)


Lesenswert?

Danke für die Antwort.

Max H. schrieb:
> Kannst du das genauer spezifizieren?

Ja. Ich habe eine Platine mit einigen LEDs und diese nutze ich als 
checkpoints für den C-Code. (Alle LEDs sind korrekt angeschlossen und 
laufen mit anderen Programmen) So kann ich verfolgen, an welcher stelle 
befindet sich das Programm. Und mir ist klar geworden, dass das Programm 
nicht ein mal in die main-fkt kommt. Meine ursprüngliche "geniale Idee" 
war die Verbindung der RX- und TX-Leitungen. Es sollte also das 
ankommen, was gesendet wurde.

Max H. schrieb:
> Wie sehen die Sende- und Empfangsfunktionen aus?
1
void delay(void) {                  //Verzögerung
2
    long i = 45535;
3
    while(i--);
4
}
5
6
void UART_zeichen_senden( char zeichen )
7
{
8
    U2TXREG = zeichen;
9
    while(U2STAbits.TRMT == 0);
10
}
11
12
void UART_zeichenkette_senden( char *str )
13
{
14
    unsigned char c;
15
    while((c = *str++))
16
    {
17
        UART_zeichen_senden(c);
18
    }
19
}
20
21
char UART2_RX_Status(void)
22
{
23
  if(U2STAbits.URXDA)      //1 = im Buffer sind Daten
24
    return 1;
25
  return 0;
26
}
27
char UART2_char_empfangen(void)
28
{
29
  return U2RXREG;
30
}
31
32
int main(int argc, char** argv) {
33
34
    char check;
35
36
    ANSA = 0x0000;          // set IOs digital
37
    ANSB = 0x0000;
38
39
    TRISBbits.TRISB13 = 0;  //LED-Ports als Ausgang
40
    TRISBbits.TRISB14 = 0;
41
    TRISBbits.TRISB15 = 0;
42
43
    LATBbits.LATB15 = 1;
44
    delay();
45
    LATBbits.LATB15 = 0;
46
    delay();
47
48
    UART_Init();
49
50
    LATBbits.LATB14 = 1;
51
    delay();
52
    LATBbits.LATB14 = 0;
53
    delay();
54
55
    while(1)
56
    {
57
        LATBbits.LATB13 = 0;
58
        LATBbits.LATB14 = 0;
59
        LATBbits.LATB15 = 0;
60
        check = '0';
61
62
        UART_zeichen_senden('1');
63
        check = UART2_char_empfangen();
64
        if (check != '0') {
65
                LATBbits.LATB13 = 1;
66
                delay();
67
                delay();
68
                delay();
69
                delay();
70
        } else {
71
        LATBbits.LATB14 = 1;
72
        LATBbits.LATB15 = 1;
73
        delay();
74
        delay();
75
        }
76
    }
77
78
79
80
    return (EXIT_SUCCESS);
81
}

Max H. schrieb:
> Wie bist du auf U2BRG = 25 gekommen?
> Ich komme auf:U2BRG = 25 würde eine Baudrate von 166.7kBd entsprechen

Danke, ich habe an dieser Stelle die falsche Formel genommen. Danke für 
die Korrektur. Jedoch auch nach dem Einsetzen des richtigen Wertes, gab 
es keine Veränderung.

von Piet (Gast)


Lesenswert?

Konstantin H. schrieb:
> Und mir ist klar geworden, dass das Programm
> nicht ein mal in die main-fkt kommt.

Wenn er nicht mal in die main() kommt,
dann ist es doch total egal, wie der UART bedient wird...?

Dann ist doch sonst irgendwas im Projekt grundlegend falsch?

von Max H. (hartl192)


Lesenswert?

Konstantin H. schrieb:
> Und mir ist klar geworden, dass das Programm
> nicht ein mal in die main-fkt kommt.
Das ist aber eine andere Baustelle als der UART. Es macht z.B: auch 
keinen Sinn ein Haus zu bauen bevor das Fundament fertig ist.

Wie hast du das gesehen? Kann es vllt. sein dass die LED an LATB15 nur 
ein paar Taktzyklen an ist weil der Compiler dein delay wegoptimiert?

Hast du vllt. einen Debugger um das Schritt für Schritt durchzugehen?

: Bearbeitet durch User
von Klaus (Gast)


Lesenswert?

Konstantin H. schrieb:
> (Alle LEDs sind korrekt angeschlossen und
> laufen mit anderen Programmen) So kann ich verfolgen, an welcher stelle
> befindet sich das Programm. Und mir ist klar geworden, dass das Programm
> nicht ein mal in die main-fkt kommt.

Die PICs, insbesondere die PIC24 lassen sich doch prima mit einem PICKit 
3 oder einem Clone direkt debuggen. Da braucht man die LEDs garnicht, 
einfach einen Breakpoint in main und schon sieht man was abgeht.

Max H. schrieb:
> Wie hast du das gesehen? Kann es vllt. sein dass die LED an LATB15 nur
> ein paar Taktzyklen an ist weil der Compiler dein delay wegoptimiert?

Da liefert der XC16 Funktionen wie __delay_ms(), die nicht wegoptimiert 
werden

MfG Klaus

von Konstantin H. (aerokos)


Lesenswert?

Also ich bin noch mal alles durchgegangen. Das Problem liegt in dem 
config. Der PIC funktioniert mit dem Config nicht. Ohne dem config kann 
ich Problemlos die Funktionen implementieren.

Ich werde jetzt noch ein mal den config durchgehen. Wenn jemand einen 
Fehler findet, würde es mich freuen, wer er es mir mitteilen würde.

Gruß

Konstantin

von Piet (Gast)


Lesenswert?

Warum  baust du es nicht Zeile für Zeile ein, bis es nicht mehr geht?

von Chris B. (dekatz)


Lesenswert?

Konstantin H. schrieb:
> Also ich bin noch mal alles durchgegangen. Das Problem liegt in dem
> config. Der PIC funktioniert mit dem Config nicht. Ohne dem config kann
> ich Problemlos die Funktionen implementieren.
>
> Ich werde jetzt noch ein mal den config durchgehen. Wenn jemand einen
> Fehler findet, würde es mich freuen, wer er es mir mitteilen würde.
>
> Gruß
>
> Konstantin

>"_FOSC(POSCMOD_HS ........"
Wir der PIC24 mit externem Quarz betrieben?

Weil einige Posts vorher:
>"Diese config soll bezwecken, dass der interne clock mit 16 MHz läuft. "
Dann wäre die Einstellung eher etwas mit FRC bzw. FRCPLL (genaue 
Schreibweise in der *.h u.ä.).

Denn ohne Änderungen in den CONFIG-Einstellungen (also mit 
Defaultwerten)läuft der PIC mit internem Oscillator, wenn aber in der 
CONFIG "HS" eingestellt und kein Quarz angeschlossen ist, tut sich nix.

von Björn P. (bjrn_g)


Lesenswert?

@TO:

Warum muss der µC unbedingt mit 16Mhz laufen?
Machen es nicht auch 8Mhz oder gar 32Mhz? Die notwendige Genauigkeit bei 
der Baudrate sollte kein Problem darstellen.

Wie Chris B. schon schrieb, ist deine Config der Taktquelle falsch!
"HS" definiert immer einen externen Quarz.

in der Header vom CCS-Compiler lautet das notwendige Bit FRC bzw. 
FRC_PLL.

kleiner Tip:
Um die grundlegende Funktionsweise des µC zu verifizieren, hat sich eine 
blinkende LED als Status-/Life-LED als ziemlich praktisch herausgestellt 
;)
SO kannst du auch schon sehen, ob die Taktfrequenz mit deiner 
berechneten übereinstimmt.

: Bearbeitet durch User
von Konstantin H. (aerokos)


Lesenswert?

Chris B. schrieb:
> Denn ohne Änderungen in den CONFIG-Einstellungen (also mit
> Defaultwerten)läuft der PIC mit internem Oscillator, wenn aber in der
> CONFIG "HS" eingestellt und kein Quarz angeschlossen ist, tut sich nix.

Oha. Ich dachte nur der "EC" (external clock mode)auf einen externen 
Quarz zugreift?
Also dann muss der Register

Konstantin H. schrieb:
> _FOSCSEL(FNOSC_PRIPLL & IESO_OFF)

geändert werden. FNOSC_PRIPLL -> FNOSC_FRCPLL. Und der Register

Konstantin H. schrieb:
> _FOSC(POSCMOD_HS & SOSCSEL_SOSCLP & POSCFREQ_HS & OSCIOFNC_OFF &
> FCKSM_CSECME)

in _FOSC(POSCMOD_XT & SOSCSEL_SOSCLP & POSCFREQ_MS & OSCIOFNC_OFF &
  FCKSM_CSECME)

Ich werde das erstmal ausprobiren.

von Björn P. (bjrn_g)


Angehängte Dateien:

Lesenswert?

Das Datenblatt hilft dabei manchmal wesentlich weiter.
In Figure 9-1 ist die Zugehörigkeit der Fuses/ConfigBits eigentlich gut 
zu erkennen (Siehe Anhang)

Nebenbei bemerkt funktioniert dein Ansatz zur Takterzeugung nicht.
Mit der Formel (8*4)/2 suggerierst du, dass du den "Post"Scaler hinter 
der PLL einsetzen willst, was aber hardwaretechnisch nicht implementiert 
ist.

INTOSC --> POSTSCALER --> PLL

8Mhz --> :2 --> x4 --> 16MHz

EDIT:

habe den Microchip-Compiler gerade nicht zur Hand.
Wofür steht "POSCMOD_XT"?
Das scheint mir nicht passend zu sein, weil damit wieder eine externe 
Taktquelle gemeint ist.

: Bearbeitet durch User
von Konstantin H. (aerokos)


Lesenswert?

@bjrn_g und @dekatz
Vielen Dank für die sehr nützliche Tipps.

Ich habe das BRGH Register auf 0 gesetzt und die Baudrate (U2BRG) 
entsprechend der Formel auf 25 gesetzt.

Mit der config funktioniert der PIC und die Status LEDs zeigen den 
Verlauf des Programms an. Ich bin aber auf ein Programmierproblem 
gestoßen, ich werde mich erstmal dem Problem wenden. Ich muss mein 
Sende- und Empfangtestsystem nachbessern und die Platine an einen 
Rechner anschließen.

Wenn ich die RX- und TX- Leitungen kurzschließe, bekomme ich an dem RX 
dasselbe, was ich über TX sende?


Gruß

Konstantin

von Konstantin H. (aerokos)


Lesenswert?

Björn G. schrieb:
> habe den Microchip-Compiler gerade nicht zur Hand.
> Wofür steht "POSCMOD_XT"?
> Das scheint mir nicht passend zu sein, weil damit wieder eine externe
> Taktquelle gemeint ist.

LP - low power
Im LP Mode kann U2 keine 'großen' Ströme erzeugen, er muss es auch 
nicht, da dieser Mode nur für Takte bis zu 200 kHz gedacht ist. Der 
LP-Mode ist auf niedrigen Stromverbrauch hin optimiert. Typischerweise 
nutzt man dann einen 32-kHz-Uhrenquarz.

XT - normal
Im XT-Mode geht U2 schon etwas stärker an die Arbeit. Der 
Ausgangswiderstand ist niedrig genug, um Schwingungen bis zu 4 MHz 
sicher zu erzeugen.

HS - high speed
Um Frequenzen oberhalb von 4 MHz zu erzeugen, wird U2 niederohmig 
eingestellt. Das ist zwar gut für die Verarbeitungsgeschwindigkeit des 
PIC, hebt aber auch den Stromverbrauch des Oszillators um einige 
Milliampere an (typabhängig).

http://sprut.de/electronic/pic/osc/index.htm#oszillator

Deswegen war ich mir sicher, dass nur der EC mode den externen 
Oscillator nutzt. Kann HS-Mode nicht duch den internal oscillator 
betrieben werden?

von Björn P. (bjrn_g)


Lesenswert?

Konstantin H. schrieb:
>
> Wenn ich die RX- und TX- Leitungen kurzschließe, bekomme ich an dem RX
> dasselbe, was ich über TX sende?

Natürlich ginge das, aber kannst du die Platine nicht an einen PC 
anschließen und dauerhaft irgendwas raus senden?
Macht sich leichter, weil du mit dem Feedback (TX auf RX) auch von außen 
irgendwie erkennbar machen müsstest, das und was angekommen ist. (eine 
LED eignet sich da natürlich nur bedingt)

von Konstantin H. (aerokos)


Lesenswert?

Björn G. schrieb:
> Nebenbei bemerkt funktioniert dein Ansatz zur Takterzeugung nicht.
> Mit der Formel (8*4)/2 suggerierst du, dass du den "Post"Scaler hinter
> der PLL einsetzen willst, was aber hardwaretechnisch nicht implementiert
> ist.

Mathematisch gesehen ist die Formel korrekt. Ich habe in diesem Fall nur 
zusammengefasst, denn 32/2 ist dasselbe wie 4*4.

von Björn P. (bjrn_g)


Lesenswert?

Konstantin H. schrieb:
> Mathematisch gesehen ist die Formel korrekt. Ich habe in diesem Fall nur
> zusammengefasst, denn 32/2 ist dasselbe wie 4*4.

Ja ich weiß xD
Wusste auch das dieses Statement noch kommt. War auch nur eine 
Anmerkung.

Btw steht bei Sprut auch:

"externe Taktquelle (LP, XT, HS, EC)
Steht ein externes Takt-Signal zur Verfügung, so wird es im Mode LP, XT 
oder HS direkt an das Pin OSC1 angeschlossen (CLKIN). Der Inverter U1 
speist dieses Signal dann in den PIC ein, während der Ausgang OSC2 
unbenutzt bleibt. An ihm ließe sich aber bei Bedarf der Takt abgreifen 
(CLKOUT).
Als externe Taktquellen eignen sich z.B. Quarzoszillatoren.

Einige Typen (16F62x) unterstützen den EC (external clock)-Mode. Auch in 
diesem Mode kann ein externer Takt direkt an OSC1 angelegt werden. Das 
OSC2-Pin wird dann allerdings nicht als Taktausgang (CLKOUT) verwendet, 
sondern kann als I/O-Pin genutzt werden."

Diese 4 Konfigurationen sind demnach nur bei externen Taktquellen 
nutzbar.

von Konstantin H. (aerokos)


Lesenswert?

Björn G. schrieb:
> Diese 4 Konfigurationen sind demnach nur bei externen Taktquellen
> nutzbar.

Stimmt. Das heißt, der Register FOSC muss default gelassen werden?

von Björn P. (bjrn_g)


Lesenswert?

Konstantin H. schrieb:
> Stimmt. Das heißt, der Register FOSC muss default gelassen werden?

Jain... Ich würde die Configbits immer vollständig im Code einstellen.
Per default ist natürlich der interne Oszillator aktiviert (sofern 
vorhanden).

Kleine Anekdote, warum ich die Bits immer im Code einstelle:

Zu Zeiten von MPLab 8 und PIC18/PIC16 habe ich die ConfigBits immer in 
MPLab selbst eingestellt. Sie waren demnach zwar Projektgebunden, aber 
nicht Codegebunden. Hatte dann manchmal aufm Laptop weitergearbeitet -> 
quasi C-File kopiert -> neues Projekt erstellt -> C-File eingefügt -> 
nichts lief mehr^^

von Klaus (Gast)


Lesenswert?

Björn G. schrieb:
> Jain... Ich würde die Configbits immer vollständig im Code einstellen.

voll ACK, wer weiß, was da vom letzten Versuch noch drinnsteht

MfG Klaus

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.