Forum: Mikrocontroller und Digitale Elektronik uart interface pic18


von Crissi (Gast)


Lesenswert?

Hallo,

ich würde gerne via PIC18LF25K50 mit eoinem UART Modul kommunizieren, 
aber es will irgendwie nicht richrig funzen.

Die UART Einstellungen sollen sein:

BAUDRATE: 115200
Data Bits: 8
Parity: None
Stop Bits: 1
Flow Control: None

Vielleicht fällt ja jemanden etwas auf.
Compiler C18 MPLAB X IDE v2.25

Beim Debuggen läuft das Programm sauber durch, aber das UART Modul 
reagiert nicht wie gewünscht.

Vielleicht fällt ja jemanden etwas auf.

Code:
1
#include <p18cxxx.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
5
/** CONFIGURATION **************************************************/
6
7
#pragma config PLLSEL   = PLL3X     // 3X PLL multiplier selected
8
#pragma config CFGPLLEN = OFF       // PLL turned on during execution
9
#pragma config CPUDIV   = NOCLKDIV  // 1:1 mode (for 48MHz CPU)
10
#pragma config LS48MHZ  = SYS48X8   // Clock div / 8 in Low Speed USB mode
11
#pragma config FOSC     = INTOSCIO  // HFINTOSC selected at powerup, no clock out
12
#pragma config PCLKEN   = OFF       // Primary oscillator driver
13
#pragma config FCMEN    = OFF       // Fail safe clock monitor
14
#pragma config IESO     = OFF       // Internal/external switchover (two speed startup)
15
#pragma config nPWRTEN  = OFF       // Power up timer
16
#pragma config BOREN    = SBORDIS   // BOR enabled
17
#pragma config nLPBOR   = ON        // Low Power BOR
18
#pragma config WDTEN    = SWON      // Watchdog Timer controlled by SWDTEN
19
#pragma config WDTPS    = 32768     // WDT postscalar
20
#pragma config PBADEN   = OFF       // Port B Digital/Analog Powerup Behavior
21
#pragma config SDOMX    = RC7       // SDO function location
22
#pragma config LVP      = OFF       // Low voltage programming
23
#pragma config MCLRE    = ON        // MCLR function enabled (RE3 disabled)
24
#pragma config STVREN   = ON        // Stack overflow reset
25
#pragma config XINST    = OFF       // Extended instruction set
26
27
/** RS 232 lines ****************************************************/
28
#define UART_TRISTx   TRISCbits.TRISC6
29
#define UART_TRISRx   TRISCbits.TRISC7
30
#define UART_Tx       PORTCbits.RC6
31
#define UART_Rx       PORTCbits.RC7
32
#define UART_ENABLE   RCSTAbits.SPEN
33
34
/** I/O pin definitions ********************************************/
35
#define INPUT_PIN 1
36
#define OUTPUT_PIN 0
37
38
39
#define CMD_TRISTx   TRISAbits.TRISA2
40
#define CMD_OUTPUT   LATAbits.LATA2
41
42
#define SWAKE_TRISTx   TRISBbits.TRISB3
43
#define SWAKE_OUTPUT   LATBbits.LATB3
44
45
46
void InitializeUSART_115200(void)
47
{
48
    unsigned char c;
49
50
    UART_TRISRx=1;              // RX -> Eingang -> geht an BT_UART_RX
51
    UART_TRISTx=0;    // TX -> Ausgang -> geht an BT_UART_TX
52
53
    // TXSTA,Transmit Status and Control Register
54
    // 0x24 = 00100100 = 36 Dez -> 8-bit Transmission, Transmit enable, BRGH = 1, also High Speed, Asynchronous Mode
55
    TXSTA = 0x24;         // TX enable BRGH=1
56
57
    // Receive Status and Control Register
58
    // 0x90 = 10010000 = 144 Dez -> RX/TX Serial Port Pins, Enables Receiver
59
    RCSTA = 0x90;         // Single Character RX
60
    SPBRG = 0x67;               // 113 Dez
61
    // Fosc = 48 MHz
62
    SPBRGH = 0x00;        // 0x0271 (625 Dez) for 48MHz -> 19200 baud
63
    // -> 115200 baud
64
    // Baud Rate Control Register
65
    // 0x08 = 00001000 = 8 Dez -> 16 Bit Baud Rate Generator (SPBRGH : SPBRG), Auto Baud Disabled
66
    BAUDCON = 0x08;       // BRG16 = 1
67
    // BRGH = 1 und BRG16 = 1 -> Baud Rate = FOSC/[4(n + 1)] mit n = value of SPBRGH and SPBRG Register Pair -> 48.000.000/[4*(625+1)] = 19200 mit n = 625
68
    // n = [(FOSC / Baud Rate)/ 4] - 1 - > n = [(48.000.000 / 115200) /4] - 1 = 103 Dez -> 0x67 -> SPBRGH = 0x00 und SPBRG = 0x67
69
    c = RCREG;                  // read
70
71
}
72
73
void putcUSART(char c)
74
{
75
    TXREG = c;
76
}
77
78
79
void UserInit(void)
80
{
81
    InitializeUSART_115200();
82
83
    SWAKE_OUTPUT = 0;
84
    SWAKE_TRISTx = OUTPUT_PIN;
85
    SWAKE_OUTPUT = 1;
86
87
    CMD_OUTPUT = 0;
88
    CMD_TRISTx = OUTPUT_PIN;
89
}
90
91
void UserInit(void)
92
{
93
    InitializeUSART_19200();
94
95
    SWAKE_OUTPUT = 0;
96
    SWAKE_TRISTx = OUTPUT_PIN;
97
    SWAKE_OUTPUT = 1;
98
99
    CMD_OUTPUT = 0;
100
    CMD_TRISTx = OUTPUT_PIN;
101
}
102
103
void InitializeSystem(void)
104
{
105
    ADCON1 |= 0x0F;                 // Default all pins to digital
106
    //Configure oscillator settings for clock settings compatible with USB
107
    //operation.  Note: Proper settings depends on USB speed (full or low).
108
109
//    OSCTUNE = 0x80; //3X PLL ratio mode selected
110
//    OSCCON = 0x70;  //Switch to 16MHz HFINTOSC
111
//    OSCCON2 = 0x10; //Enable PLL, SOSC, PRI OSC drivers turned off
112
//    while(OSCCON2bits.PLLRDY != 1);   //Wait for PLL lock
113
//    *((unsigned char*)0xFB5) = 0x90;  //Enable active clock tuning for USB operation
114
            
115
    //Configure all I/O pins for digital mode (except RA0/AN0 which has POT on demo board)
116
    ANSELA = 0x01;
117
    ANSELB = 0x00;
118
    ANSELC = 0x00;
119
120
    UserInit();
121
}
122
123
void main(void) {
124
125
126
    InitializeSystem();
127
    
128
    while(1)
129
    {
130
131
        putcUSART('K');
132
133
        putcUSART('\r');
134
135
136
    }

von Little B. (lil-b)


Lesenswert?

auf den ersten blick:

du hast zwei "userinit()"-funktionen, da wird sich der compiler 
beschweren.

aber warum dein uart nicht geht:
du überfährst gnadenlos den output buffer! warte, bis dieser wieder frei 
ist, bevor du ein neues byte hinein schreibst (entsprechendes bit im 
status register, TxEmpty oder so)

von Crissi (Gast)


Lesenswert?

Little Basdart schrieb:
> auf den ersten blick:
>
> du hast zwei "userinit()"-funktionen, da wird sich der compiler
> beschweren.

Copy Paste Fehler, aber danke

> aber warum dein uart nicht geht:
> du überfährst gnadenlos den output buffer! warte, bis dieser wieder frei
> ist, bevor du ein neues byte hinein schreibst (entsprechendes bit im
> status register, TxEmpty oder so)

das ist was dran.

in dem Beispielcode ist es wie folgt realisiert :
1
const char  buffer_command_reset[] = {'R', ',', '1', '\r'};
2
3
4
#define mTxRdyUSART()   TXSTAbits.TRMT
5
#define mDataRdyUSART() PIR1bits.RCIF
6
7
8
void send_command(char* src)
9
{
10
    char* psrc = src;
11
    while(*psrc != '\r')
12
    {
13
        if(mTxRdyUSART())
14
            putcUSART(*psrc++);
15
    }
16
    putcUSART('\r');
17
}
18
19
void main(void)
20
{
21
// siehe oben
22
send_command((char*)buffer_command_reset);
23
24
}

So wartet er automatisch bis der Output Buffer wieder frei ist.
Leider bringt das ganze nicht den erhofften Erfolg, aber vielen Dank für 
den Input

von Frank K. (fchk)


Lesenswert?

Du hast keine stabile Taktquelle. Der interne Oszillator ist keine!

Dieser PIC kann USB ohne Quarz, aber dann dient USB als stabile 
Taktquelle. USB ist hier nicht konfiguriert, also ist auch von dieser 
Richtung aus Fehlanzeige.

Schließe einen externen Quarz oder Oszillator an OSC1/OSC2 an und setze 
die Config-Words passend.

fchk

von Volker S. (vloki)


Lesenswert?

Crissi schrieb:
> Beim Debuggen läuft das Programm sauber durch, aber das UART Modul
> reagiert nicht wie gewünscht.

Was macht es denn genau ?????????????????????????

Was mir auffällt:
TX-Pin sollte nicht als Ausgang konfiguriert werden.
(Ist fast bei allen so und steht im Data sheet 17.1.1.7 - 2.)

PS: Interner Clock reicht bei mir zumindest zum Entwickeln
immer. Später brauchst du dann vielleicht was präziseres.

von Crissi (Gast)


Lesenswert?

Frank K. schrieb:
> Du hast keine stabile Taktquelle. Der interne Oszillator ist
> keine!
>
> Dieser PIC kann USB ohne Quarz, aber dann dient USB als stabile
> Taktquelle. USB ist hier nicht konfiguriert, also ist auch von dieser
> Richtung aus Fehlanzeige.
>
> Schließe einen externen Quarz oder Oszillator an OSC1/OSC2 an und setze
> die Config-Words passend.
>
> fchk

HMM,
OK. Ich arbeite mit dem RN4020 Pictail Modul von Microchip. Da ist ICSP 
etc. schon mit drauf und eben kein externer Oszillator. Würde mich 
wundern wenn man den dann selbst noch mit draufpacken müsste. Aber 
vielen Dank für den Hinweis, werde mir mal einen bestellen und mal 
ausprobieren. In dem BeispielCode...
1
    //Configure oscillator settings for clock settings compatible with USB
2
    //operation.  Note: Proper settings depends on USB speed (full or low).
3
4
    OSCTUNE = 0x80; //3X PLL ratio mode selected
5
    OSCCON = 0x70;  //Switch to 16MHz HFINTOSC
6
    OSCCON2 = 0x10; //Enable PLL, SOSC, PRI OSC drivers turned off
7
    while(OSCCON2bits.PLLRDY != 1);   //Wait for PLL lock
8
    *((unsigned char*)0xFB5) = 0x90;  //Enable active clock tuning for USB operation

dient USB ja als stabile Taktquelle. Wenn ich dies einkommentiere bringt 
das jedoch auch nicht den gewünschten Erfolg. Ich bin bis dato davon 
ausgegangen, dass diese Zeilen nur für die USB <-> UART Bridge benötigt 
werden. Danke für den Hinweis.

von Crissi (Gast)


Lesenswert?

Volker SchK schrieb:
> Crissi schrieb:
>> Beim Debuggen läuft das Programm sauber durch, aber das UART Modul
>> reagiert nicht wie gewünscht.
>
> Was macht es denn genau ?????????????????????????

Ich habe mir das gerade nochmal genauer angeschaut.
Die send Funktion sah ja wie folgt aus.
1
#define mTxRdyUSART()   TXSTAbits.TRMT
2
#define mDataRdyUSART() PIR1bits.RCIF
3
4
void send_command(char* src)
5
{
6
    char* psrc = src;
7
    while(*psrc != '\r')
8
    {
9
        if(mTxRdyUSART())                             putcUSART(*psrc++);
10
    }
11
    putcUSART('\r');
12
}


Dies funktioniert auch eigentlich, d.h. er schickt jeden einzelnen 
Character über putcUSART(*psrc++); in das TXREG1 Register. Was auffällt, 
dass das Empfangen über
1
void get_response(char* dst)
2
{
3
    char* pdst = dst;
4
5
    while(1){
6
        if(mDataRdyUSART())      // in dieser Schleife bleibt er immer hängen
7
        {
8
            *pdst = getcUSART1();
9
            if(*pdst == '\r')
10
                break;
11
            if(*pdst != '\n')
12
                pdst++;
13
        }
14
    }
15
}

nicht funktioniert. Hier bleibt er Immer in der obig gekennzeichneten 
Schleife hängen.



> Was mir auffällt:
> TX-Pin sollte nicht als Ausgang konfiguriert werden.
> (Ist fast bei allen so und steht im Data sheet 17.1.1.7 - 2.)



Habe es mir durchgelesen und im Datenblatt steht tatsächlich:
"Set RX and TX TRIS controls to 1."

Finde ich etwas verwunderlich. Im Microchip Beispiel Code ist TX 
jedenfalls auch als Ausgang konfiguriert. Ich habe beides ausprobiert.

> PS: Interner Clock reicht bei mir zumindest zum Entwickeln
> immer. Später brauchst du dann vielleicht was präziseres.

Da bin ich aber beruhigt.

von Frank K. (fchk)


Lesenswert?

Crissi schrieb:


> OK. Ich arbeite mit dem RN4020 Pictail Modul von Microchip. Da ist ICSP
> etc. schon mit drauf und eben kein externer Oszillator. Würde mich
> wundern wenn man den dann selbst noch mit draufpacken müsste. Aber
> vielen Dank für den Hinweis, werde mir mal einen bestellen und mal
> ausprobieren.

Der Onboard-PIC ist nur als USB-UART-Bridge gedacht. Ansonsten sollst Du 
das Board in ein Demoboard mit PicTail(+) einstecken und den onboard-PIC 
nicht benutzen. So ist das eigentlich gedacht.

Der hier sollte passen:
http://www.reichelt.de/Oszillatoren-SMD-Keramikgehaeuse/XO91-16-00000/3/index.html?ACTION=3&GROUPID=4004&ARTICLE=85017&OFFSET=500&WKID=0&;

100n über der Spannungsversorgung nicht vergessen. Mit 12 (PLLx4) oder 
16 (PLLx3) MHz funktioniert USB auch noch weiterhin.

> In dem BeispielCode...
> dient USB ja als stabile Taktquelle. Wenn ich dies einkommentiere bringt
> das jedoch auch nicht den gewünschten Erfolg.

... weil die USB-Peripherie nicht konfiguriert ist und keine aktive 
USB-Verbindung besteht.

fchk

von Crissi (Gast)


Lesenswert?

> Der Onboard-PIC ist nur als USB-UART-Bridge gedacht. Ansonsten sollst Du
> das Board in ein Demoboard mit PicTail(+) einstecken und den onboard-PIC
> nicht benutzen. So ist das eigentlich gedacht.

Hmm, ja Ok. Das ist eigentlich klar, aber der On Board Pic hat nun mal 
eine UART Schnittstelle und die ICSP Schnittstelle ist nun mal auch 
rausgeführt. Was kann bzw. sollte mich davon abhalten das Modul über die 
reine UART Schnittstelle des ON Board Pic18 zu konfigurieren. Wesentlich 
günstiger und meiner Meinung nach sinnvoller als sich jetzt nen 
komplettes Starterkit anzuschaffen und über den PICTAIL Konnektor zu 
konfigurieren!

Das müßte doch eigentlich genau so klappen (theoretisch)?

Danke für den Einwwand und den Oscillator Link.

von Volker S. (vloki)


Lesenswert?

Also ich sehe da kein Problem ...

von Frank K. (fchk)


Lesenswert?

Crissi schrieb:
>> Der Onboard-PIC ist nur als USB-UART-Bridge gedacht. Ansonsten sollst Du
>> das Board in ein Demoboard mit PicTail(+) einstecken und den onboard-PIC
>> nicht benutzen. So ist das eigentlich gedacht.
>
> Hmm, ja Ok. Das ist eigentlich klar, aber der On Board Pic hat nun mal
> eine UART Schnittstelle und die ICSP Schnittstelle ist nun mal auch
> rausgeführt. Was kann bzw. sollte mich davon abhalten das Modul über die
> reine UART Schnittstelle des ON Board Pic18 zu konfigurieren.

Der fehlende Oszillator bzw Quarz.

> Wesentlich
> günstiger und meiner Meinung nach sinnvoller als sich jetzt nen
> komplettes Starterkit anzuschaffen und über den PICTAIL Konnektor zu
> konfigurieren!

Natürlich, aber Microchip hat das eben anders vorgesehen.

> Das müßte doch eigentlich genau so klappen (theoretisch)?

Wenn Du den Oszillator und den Abblockkondensator für den Oszillator 
nachrüstest, dann ja. Der kommt übrigens dann an RA6, RA7 bleibt frei. 
Config Words passend setzen (Primärer Oszillator ist dann ECPLL)!

fchk

von Crissi (Gast)


Lesenswert?

Ich fasse mal zusammen:

1. das Modul über den PIC18 als USB - UART Bridge zu konfigurieren OHNE 
externen Quarz funktioniert wunderbar

2. das Modul über die reine UART Schnittstelle zu konfigurieren 
funktioniert OHNE Quarz auf keinen Fall, d.h. also wann immer der 
PIC18LF25K50 mit einem externen Modul über die UART Schnittstelle 
kommunizieren will ist ein externer Quarz nötig (ist das wirklich so?, 
kann ich da nix tricksen?)

3. ich als Laie kann nicht verstehen das 1. funktioniert aber 2. nicht

4. das RN4020 Pictail Board über einen PIC32 auf einem teuren Starterkit 
zu konfigurieren würde vermutlich tadellos funktionieren

5. das Modul über den On Board Pic nur mit externen Quarz an Pin RA6 
(einer der einzigen der am Pictail Board NICHT rausgeführt ist) und dann 
Primärer Oszillator auf ECPLL setzen

Das kommt mir merkwürdig vor. Ich weiss gar nicht wie ich auf dem 
Pictail Board mit dem Oszillator jetzt an den RA6 kommen sollte. Kann 
irgendwie kaum glauben, dass es da keine andere Möglichkeit geben kann.

von Crissi (Gast)


Lesenswert?

ich habe nochmal ausprobiert die USB UART Bridge zu nutzen, sprich das 
Modul über ein Terminal zu konfigurieren (Man kann übrigens auch einfach 
die rausgeführten TX, RX Pins und einen Pegelwandler verwenden, dann 
spart man sich die ganze USB Geschichte).

Na ja, es scheint auf jeden Fall wichtig zu sein, dass als Baudrate 
115200 mit den folgenden Einstellungen initialisiert werden.

BAUDRATE: 115200
Data Bits: 8
Parity: None
Stop Bits: 1
Flow Control: None

Andernfalls funktioniert es nicht. Kann bitte nochmal einer drüber 
gucken, ob sich hier vielleicht nicht ein Fehler eingeschlichen hat?
1
/** CONFIGURATION **************************************************/
2
...
3
#pragma config PLLSEL   = PLL3X     // 3X PLL multiplier selected
4
#pragma config CPUDIV   = NOCLKDIV  // 1:1 mode (for 48MHz CPU)
5
...
6
// -> 48 MHZ interne Oszillator Clock
7
8
void InitializeUSART_115200(void)
9
{
10
    unsigned char c;
11
12
    UART_TRISRx=1;              // RX -> Eingang -> geht an BT_UART_RX
13
    UART_TRISTx=0;    // TX -> Ausgang -> geht an BT_UART_TX
14
15
    // TXSTA,Transmit Status and Control Register
16
    // 0x24 = 00100100 = 36 Dez -> 8-bit Transmission, Transmit enable, BRGH = 1, also High Speed, Asynchronous Mode
17
    TXSTA = 0x24;         // TX enable BRGH=1
18
19
    // Receive Status and Control Register
20
    // 0x90 = 10010000 = 144 Dez -> RX/TX Serial Port Pins, Enables Receiver
21
    RCSTA = 0x90;         // Single Character RX
22
    SPBRG = 0x67;               // 113 Dez
23
    SPBRGH = 0x00;        // 0x0271 (625 Dez) for 48MHz 
24
    // -> 115200 baud
25
    // Baud Rate Control Register
26
    // 0x08 = 00001000 = 8 Dez -> 16 Bit Baud Rate Generator (SPBRGH : SPBRG), Auto Baud Disabled
27
    BAUDCON = 0x08;       // BRG16 = 1
28
    // BRGH = 1 und BRG16 = 1 -> Baud Rate = FOSC/[4(n + 1)] mit n = value of SPBRGH and SPBRG Register Pair -> 48.000.000/[4*(625+1)] = 19200 mit n = 625
29
    // n = [(FOSC / Baud Rate)/ 4] - 1 - > n = [(48.000.000 / 115200) /4] - 1 = 103 Dez -> 0x67 -> SPBRGH = 0x00 und SPBRG = 0x67
30
    c = RCREG;                  // read
31
32
}

Habe ich so die Baudrate von 115200 zumindest theoretisch richtig 
eingestellt?

Vielen Dank für die Hilfe!

von Frank K. (fchk)


Lesenswert?

Crissi schrieb:
> Ich fasse mal zusammen:
>
> 1. das Modul über den PIC18 als USB - UART Bridge zu konfigurieren OHNE
> externen Quarz funktioniert wunderbar
>
> 2. das Modul über die reine UART Schnittstelle zu konfigurieren
> funktioniert OHNE Quarz auf keinen Fall, d.h. also wann immer der
> PIC18LF25K50 mit einem externen Modul über die UART Schnittstelle
> kommunizieren will ist ein externer Quarz nötig (ist das wirklich so?,
> kann ich da nix tricksen?)
>
> 3. ich als Laie kann nicht verstehen das 1. funktioniert aber 2. nicht

Du brauchst eine stabile und genaue Taktquelle. Auf dem Chip ist nur ein 
Widerstand und ein Kondensator als RC-Schwingkreis vorhanden. Das ist 
nicht besonders genau, und wenn der Chip warm wird, ändern sich die 
Bauteilewerte und damit die Frequenz. Ein Schwingquarz ist sehr genau, 
aber er lässt sich nicht im Chip unterbringen, weil es ein mechanisches 
Bauteil ist, das tatsächlich physikalisch schwingt.

Mit einer AKTIVEN USB-Verbindung hast Du einen sehr genauen Zeitgeber, 
da der USB-Host-Chip im PC auch von einem Quarz getaktet wird (das ist 
im USB-Standard vorgeschrieben).

> 4. das RN4020 Pictail Board über einen PIC32 auf einem teuren Starterkit
> zu konfigurieren würde vermutlich tadellos funktionieren

ja

> 5. das Modul über den On Board Pic nur mit externen Quarz an Pin RA6
> (einer der einzigen der am Pictail Board NICHT rausgeführt ist) und dann
> Primärer Oszillator auf ECPLL setzen

ja
>
> Das kommt mir merkwürdig vor. Ich weiss gar nicht wie ich auf dem
> Pictail Board mit dem Oszillator jetzt an den RA6 kommen sollte. Kann
> irgendwie kaum glauben, dass es da keine andere Möglichkeit geben kann.

Beschwere Dich bei Microchip.

Du klebst den Oszillator verkehrtrum auf die Platine und gehst dann mit 
feinem Kupferlackdraht an die entsprechenden Anschlüsse. Mit dem 
passenden Werkzeug geht das. Gut, der PIC ist im QFN-Package, das ist 
dann erhöhter Schwierigkeitsgrad. :-) Ist aber auch nur ein Pin, obere 
Reihe, linkester Pin. 3V3 und GND bekommst Du wahlweise von C5 oder C6.

Oder bau Dir Deine eigene Leiterplatte. Das hätte ich eh gemacht.

fchk

von Crissi (Gast)


Lesenswert?

OK, schon einmal vielen Dank für die ausführlichen Erklärungen. Ich kann 
es zwar immer noch nicht ganz glauben, dass eine UART Kommunikation ohne 
externen Oszillator nicht funktionieren soll, aber da fehlt mir 
wahrscheinlich noch die Erfahrung.

Ich hoffe ich habe die Baudrate zumindest richtig kalkuliert.

Ich habe hier einen 32 Mhz Quarz gefunden:
http://www.farnell.com/datasheets/1782547.pdf

würde so etwas auch gehen?

von Little B. (lil-b)


Lesenswert?

schonmal die Signale auf der datenleitung gemessen?

einfach mal vom PIC aus dummy daten in einer endlosschleife schicken, am 
besten 0x55.
Mit Oszi oder LogicAnalizer hübsche Bilder anschaun, ob die Frequenz 
stimmt.
Oder mit einem Multimeter die Frequenz messen.

Ich kann mir nicht vorstellen, ein 16MHz +-1% oszillator für ein 
9600baut-uart zu ungenau sein soll.
Auf einem STM32F4 kann ich mit diesen Werten einen 4Mbaud-uart 
betreiben, ohne probleme!

von spontan (Gast)


Lesenswert?

Du kennst schon den Unterschied zwischen Quarz und Quarzoszillator?

von Little B. (lil-b)


Lesenswert?

Ich hab mir mal die Mühe gemacht und deine Oszillator Konfiguration 
zerpflückt. Mein Ergebnis: er ist nicht initialisiert!

Du initialisierst nichts in Hinblick auf den Oszillator Block in deiner 
Init-Routine, daher läuft er mit den Einstellungen der Fuses:

#pragma config PLLSEL   = PLL3X     // 3X PLL multiplier selected
#pragma config CFGPLLEN = OFF       // PLL turned on during execution
...

PLL ist also offenbar gar nicht eingeschaltet und dein prozessor taktet 
mit irgendwas, aber nicht mit 48MHz

Schalte IRCF auf 16MHz, wähle PLL_Select = 0 und es könnte evtl 
funktionieren.

Siehe hierzu kapitel 3 deines Mikrocontroller-Datenblatt

von Volker S. (vloki)


Lesenswert?

Yo, sehe ich auch so. Interner Oszillator läuft auf 1MHz per default ...
Kein Problem mit 115200 bei mir wenn man den Oszillator über das OSCCON 
vernünftig einstellt. Vergiss den externen vorerst mal !


#include <p18cxxx.h>
#include <usart.h>

/** CONFIGURATION **************************************************/

#pragma config PLLSEL   = PLL3X     // 3X PLL multiplier selected
#pragma config CFGPLLEN = OFF       // PLL turned on during execution
#pragma config CPUDIV   = NOCLKDIV  // 1:1 mode (for 48MHz CPU)
#pragma config LS48MHZ  = SYS48X8   // Clock div / 8 in Low Speed USB 
mode
#pragma config FOSC     = INTOSCIO  // HFINTOSC selected at powerup, no 
clock out
#pragma config PCLKEN   = OFF       // Primary oscillator driver
#pragma config FCMEN    = OFF       // Fail safe clock monitor
#pragma config IESO     = OFF       // Internal/external switchover (two 
speed startup)
#pragma config nPWRTEN  = OFF       // Power up timer
#pragma config BOREN    = SBORDIS   // BOR enabled
#pragma config nLPBOR   = ON        // Low Power BOR
#pragma config WDTEN    = SWON      // Watchdog Timer controlled by 
SWDTEN
#pragma config WDTPS    = 32768     // WDT postscalar
#pragma config PBADEN   = OFF       // Port B Digital/Analog Powerup 
Behavior
#pragma config SDOMX    = RC7       // SDO function location
#pragma config LVP      = OFF       // Low voltage programming
#pragma config MCLRE    = ON        // MCLR function enabled (RE3 
disabled)
#pragma config STVREN   = ON        // Stack overflow reset
#pragma config XINST    = OFF       // Extended instruction set


void main(void) {

    while(1)
    {
        while (Busy1USART()){;}
        TXREG1 = 'U';
        while (Busy1USART()){;}
        TXREG1 = 0x0D;
    }
}

void __init(void)
{
    OSCCONbits.IRCF = 0b111;    //16MHz

#define FOSC        16000000 // in a global header
#define BAUDRATE    115200   // ""
//#define SPBRG_VAL (((FOSC/BAUDRATE)+32)/64)-1   // BRG16=0, BGH=0 !
//#define SPBRG_VAL (((FOSC/BAUDRATE)+8)/16)-1    // BRG16=0, BGH=1 !
#define SPBRG_VAL (((FOSC/BAUDRATE)+2)/4)-1     // BRG16=1, BGH=1 !

    baud1USART(BAUD_IDLE_RX_PIN_STATE_HIGH &
                 BAUD_IDLE_TX_PIN_STATE_HIGH &
                 BAUD_16_BIT_RATE &
                 BAUD_WAKEUP_OFF &
                 BAUD_AUTO_OFF);

    Open1USART( USART_TX_INT_OFF & USART_RX_INT_OFF &
                USART_ASYNCH_MODE & USART_EIGHT_BIT &
                USART_CONT_RX &
                USART_BRGH_HIGH & USART_ADDEN_OFF,
                SPBRG_VAL );
}

von Crissi (Gast)


Lesenswert?

Schon mal vielen Dank für den ganzen Input,

Gerade den Fehler mit den Config Bits hätte ich alleine nie gefunden.

Habe die Baudrate (115200) mal mit dem Oszi an der TX Leitung 
verifiziert. Das kommt ziemlich genau hin. Vielen Dank dafür an Volker.

Jetzt antwortet mein Modul noch nicht (anders als wenn ich es direkt 
über die serielle Leitung via Putty anspreche).

Woran das liegt muss ich noch rausbekommen.
Ich werde berichten.

Schönen Dank an ALLE!

von vloki (Gast)


Lesenswert?

In meinem Beispielcode fehlt die digital Input Einstellung für RX, weil 
ich nur TX testen wollte ...

von Frank K. (fchk)


Lesenswert?

Crissi schrieb:
> OK, schon einmal vielen Dank für die ausführlichen Erklärungen. Ich kann
> es zwar immer noch nicht ganz glauben, dass eine UART Kommunikation ohne
> externen Oszillator nicht funktionieren soll, aber da fehlt mir
> wahrscheinlich noch die Erfahrung.
>
> Ich hoffe ich habe die Baudrate zumindest richtig kalkuliert.
>
> Ich habe hier einen 32 Mhz Quarz gefunden:
> http://www.farnell.com/datasheets/1782547.pdf

Du brauchst entweder 12 oder 16 MHz oder aber 48 MHz. Nur dann 
funktioniert USB weiterhin. 48 MHz würde ich sein lassen, also bleiben 
12 oder 16 MHz. Und ein Oszillator schwingt zuverlässiger an als ein 
Quarz insbesondere bei Fädelbeschaltung.

Der Standard sagt, dass bei UART die Baudrate um ±3% abweichen darf.

fchk

von Frank K. (fchk)


Lesenswert?

Frank K. schrieb:

>> Ich habe hier einen 32 Mhz Quarz gefunden:
>> http://www.farnell.com/datasheets/1782547.pdf

PS: Wer lesen kann, ist im Vorteil. Das sind 32kHz, nicht 32 MHz. Ein 
Uhrenquarz.

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.