String-Ausgabe über UART funktioniert nicht bei PIC 18F

Gast #3066055
Lesenswert?

Hallo zusammen,

ich beschäftige mich jetzt seit einigen Tagen mit PIC-Prozessoren, 
wesentlich mehr Erfahrung habe ich mit den ATMega's von Atmel.

Es ist nicht möglich, mehrere Zeichen über die UART-Schnittstelle an ein 
Terminalprogramm zu senden. Es kommt immer nur das erste und das letzte 
Zeichen an (Wenn ich "MICROCHIP." senden will, kommt nur "M.").
Senden per String über die Funktion "UART_Zeile_senden" geht überhaupt 
nicht, da kommt am PC gar nix an.

Ich tüftel nun schon einige Tage und studiere das Datenblatt und 
Internetseiten rauf und runter, aber ich komm nicht drauf...

Ich verwende MPLAB x IDE v 1.60, einen PIC 18F258, einen MAX232, und 
HTERM 0.8.1

Danke ;)

Christian


main.c:
1
#pragma config OSC = HS         // 14,7456 MHz
2
#pragma config PWRT = ON        // Power-On-Timer
3
#pragma config WDT = OFF        // Watchdog off
4

5
#include <delays.h>
6
#include <p18f258.h>
7
#include "myports.h"            // Ein- und Ausgänge
8
#include "myuart.h"             // UART-Schnittstelle
9

10
int main(void)
11
{
12
    // Ausgänge initialisieren
13
    Ausgaenge_Init();
14

15
    // Eingänge initialisieren
16
    Eingaenge_Init();
17

18
    // UART initialisieren
19
    UART_Init();
20

21
    // Ausgang C4 auf High
22
    Set_LED_gruen(1);
23

24
    // Hauptschleife
25
    while(1)
26
    {
27
        // Ausgang C3 auf high
28
        Set_LED_rot(1);
29

30
        // Warten
31
        Delay10KTCYx(64);
32

33
        // Ausgang C3 auf low
34
        Set_LED_rot(0);
35

36
        // Warten
37
        Delay10KTCYx(255);
38

39
        // UART Test
40
        UART_Zeichen_senden('M');
41
        UART_Zeichen_senden('I');
42
        UART_Zeichen_senden('C');
43
        UART_Zeichen_senden('R');
44
        UART_Zeichen_senden('O');
45
        UART_Zeichen_senden('C');
46
        UART_Zeichen_senden('H');
47
        UART_Zeichen_senden('I');
48
        UART_Zeichen_senden('P');
49
        UART_Zeichen_senden('.');
50

51
        UART_Zeile_senden("TECHNOLOGY.");
52
   }
53

54
   return 0;
55
}

myuart.h:
1
// Bitdefinitionen
2
#define SPEN 7
3
#define TX9  6
4
#define TXEN 5
5
#define SYNC 4
6
#define BRGH 2
7
#define TRMT 1
8
#define TXIF 4
9

10
// UART initialisieren
11
void UART_Init(void)
12
{
13
    SPBRG = 3;                   // Baud Rate Generator Register, 57600 bd
14
    TXSTA &= ~(1<<BRGH);         // High Speed Aus
15
    TXSTA &= ~(1<<SYNC);         // Asynchroner Modus
16
    TXSTA &= ~(1<<TX9);          // 8-bit-Übertragung
17
    TXSTA |=  (1<<TXEN);         // Transmit Enable
18
    RCSTA |=  (1<<SPEN);         // RX und TX Pins aktivieren
19
}
20

21
void UART_Zeichen_senden(unsigned char zeichen)
22
{
23
    // Zeichen in den Ausgabepuffer schreiben
24
    TXREG = zeichen;
25

26
    // Warten, bis das Zeichen gesendet wurde
27
    while( (PIR1 & (TXIF)) );
28
}
29

30
void UART_Zeile_senden(char *zeile)
31
{
32
    // Solange senden, bis Stringende erreicht
33
    while(*zeile)
34
    {
35
        // Einzelnes Zeichen senden
36
        UART_Zeichen_senden(*zeile);
37

38
        // Nächstes Zeichen
39
        *zeile++;
40
    }
41
}
Gast #3066090
Lesenswert?

Danke für diese fixe Antwort. Manchmal kann's so einfach sein... Hab das 
1<< übersehen...

Klappt aber leider nicht ganz.

so:
1
    while( (PIR1 & (1 << TXIF)) );

sendet er gar nix. Terminalfenster bleibt leer.

und so:
1
    while( !(PIR1 & (1 << TXIF)) );

funktioniert's zwar teilweise, aber mit dem oben angegebenen Quellcode 
kommt nur "MCOHP." im Terminalfenster an.

Irgendwie vergisst der da die Hälfte, aber ich weiß nicht warum

:-(

Christian
Gast #3066111
Lesenswert?

Hier mal der aktuelle Code meiner Funktion:

1
void UART_Zeichen_senden(unsigned char zeichen)
2
{
3
    // Zeichen in den Ausgabepuffer schreiben
4
    TXREG = zeichen;
5

6
    // Warten, bis das Zeichen gesendet wurde
7
    while(PIR1bits.TXIF==0);
8

9
    // Flag löschen
10
    PIR1bits.TXIF=0;
11
}

Das ergibt als Ausgabe: "MCOHP."

Sieht ganz so aus, als würde er jedes zweite Zeichen weglassen.

Christian
Gast #3066136
Lesenswert?

Ich glaub ich geb's auf mit den PIC's, und kehre doch wieder zu den 
ATMegas zurück, die ich schon 3 Jahre "kenne" :-)

Mit dem Code:
1
void UART_Zeichen_senden(unsigned char zeichen)
2
{
3
    TXREG = zeichen;    // Zeichen in den Ausgabepuffer schreiben
4
    while(!TRMT);
5
}

kommt:

M(

großes M und ne Klammer dahinter, warum auch immer...

Christian
Gast #3066203
Lesenswert?

>ein syntax error vom compiler

Komplette Fehlermeldung posten.
Welcher Compiler?

Und wieso definiert du den ganzen Kram hier neu?

myuart.h:

// Bitdefinitionen
#define SPEN 7
#define TX9  6
#define TXEN 5
#define SYNC 4
#define BRGH 2
#define TRMT 1
#define TXIF 4

Das steht mit Sicherheit irgendwo in einer Headerdatei vom Compiler.
Gast #3066235
Lesenswert?

ok hier die Meldung:

Error: syntax error

in Zeile:

while(!TXSTAbits.TRMT);   // Loop til TXREG empty

Die Definitionen deswegen, weil der Compiler die Bits nicht kennt, und 
rot unterstreicht. Ich hab mir auch noch nicht die Mühe gemacht, die 
entsprechende Headerdatei zu suchen und einzubinden.

Christian
Gast #3066313
Lesenswert?

holger schrieb:
> TXSTAbits.BRGH = 0;

holger schrieb:
>>weil der Compiler die Bits nicht kennt
>
> Welcher Compiler?
>
> Was passiert wenn du diese Zeile
>
>     TXSTA &= ~(1<<BRGH);         // High Speed Aus
>
> so schreibst
>
>     TXSTAbits.BRGH = 0;         // High Speed Aus

Compiler: C18 (v3.45) [C:\Program Files\Microchip\mplabc18\v3.45\bin]

Da passiert: myuart.h:19:Error: syntax error



Rufus Τ. Firefly schrieb:
> void UART_Zeile_senden(char *zeile)
> {
>     // Solange senden, bis Stringende erreicht
>     while(*zeile)
>     {
>         // Einzelnes Zeichen senden
>         UART_Zeichen_senden(*zeile);
>
>         // Nächstes Zeichen
>         *zeile++;  // <--- ?
>     }
> }
>
> In der gekennzeichneten Zeile:
>
> Was genau wird da inkrementiert?
> Und was soll inkrementiert werden?

oh, der Stern muss da weg ;-)

Christian
Gast #3066343
Lesenswert?

Für nen PIC16F887 hab ich das wie folgt gemacht. Vielleicht hilfts ja.
1
void UART_Send(uint8_t Byte)
2
{
3
    uint8_t byteSend = 0;
4
    
5
    do {
6
      if(TXIF){
7
        TXREG = Byte;
8
        byteSend = 1;
9
      
10
      }else{
11
        while( !TRMT );
12
      }   
13
    } while (byteSend == 0);
14

15
    
16
}
Gast #3066366
Lesenswert?

Hier mal die aktuelle Version der "myuart.h"
1
#include <p18f258.h>
2

3
// Bitdefinitionen
4
#define SPEN 7
5
#define TX9  6
6
#define TXEN 5
7
#define SYNC 4
8
// #define BRGH 2
9
#define TRMT 1
10

11
// UART initialisieren
12
void UART_Init(void)
13
{
14
    SPBRG = 3;                   // Baud Rate Generator Register, 57600 bd
15
    TXSTAbits.BRGH = 0;          // High Speed Aus
16
    TXSTA &= ~(1<<SYNC);         // Asynchroner Modus
17
    TXSTA &= ~(1<<TX9);          // 8-bit-Übertragung
18
    TXSTA |=  (1<<TXEN);         // Transmit Enable
19
    RCSTA |=  (1<<SPEN);         // RX und TX Pins aktivieren
20
}
21

22
void UART_Zeichen_senden(unsigned char zeichen)
23
{
24
    TXREG = zeichen;
25
    while(!TRMT);
26
}
27

28
void UART_Zeile_senden(char *zeile)
29
{
30
    // Solange senden, bis Stringende erreicht
31
    while(*zeile)
32
    {
33
        // Einzelnes Zeichen senden
34
        UART_Zeichen_senden(*zeile);
35

36
        // Nächstes Zeichen
37
        zeile++;
38
    }
39
}

Die aktuelle Ausgabe im Terminalprogramm:

M(
Gast #3066373
Lesenswert?

Jetzt nimmst du mal das:

void UART_Zeichen_senden(unsigned char zeichen)
{
 while(!TXSTAbits.TRMT);   // Loop til TXREG empty
 TXREG = zeichen;    //Send data
}

Und entfernst das

#define TRMT 1



>Erklärbär doch mal wieso das nicht gehen soll.

Weil

 while(!TRMT);

mit seinem define mit Sicherheit nicht auf TXSTA zugreift.
Gast #3067029
Lesenswert?

holger schrieb:
> Noch ein Versuch:

Leider nicht :-(

Mit dem unten angegebenen Code kommt im Terminalfenster "MICROCHIP." an. 
Das "TECHNOLOGY." fehlt.

Hier mal im Anhang mein aktueller Quellcode, damit man mal einen 
Überblick hat, was alles mittlerweile verändert wurde.

Aktueller Stand "main.c":
1
#pragma config OSC = HS         // 14,7456 MHz
2
#pragma config PWRT = ON        // Power-On-Timer
3
#pragma config WDT = OFF        // Watchdog off
4

5
#include <delays.h>
6
#include <p18f258.h>
7

8
// Ausgänge initialisieren
9
void Ausgaenge_Init(void)
10
{
11
    TRISCbits.RC3 = 0;      // C3: LED rot
12
    TRISCbits.RC4 = 0;      // C4: LED grün
13
}
14

15
// Eingänge initialisieren
16
void Eingaenge_Init(void)
17
{
18
    // A0: Fotowiderstand
19
}
20

21
// Funktion Pin C3 Ein- oder Ausschalten
22
void Set_LED_rot(char status)
23
{
24
    if(status)  LATCbits.LATC3 = 1;
25
    if(!status) LATCbits.LATC3 = 0;
26
}
27

28
// Funktion Pin C4 Ein- oder Ausschalten
29
void Set_LED_gruen(char status)
30
{
31
    if(status)  LATCbits.LATC4 = 1;
32
    if(!status) LATCbits.LATC4 = 0;
33
}
34

35
// UART initialisieren
36
void UART_Init(void)
37
{
38
    SPBRG = 3;                  // Baud Rate Generator Register, 57600 bd
39
    TXSTAbits.BRGH = 0;         // High Speed Aus
40
    TXSTAbits.SYNC = 0;         // Asynchroner Modus
41
    TXSTAbits.TX9  = 0;         // 8-bit-Übertragung
42
    TXSTAbits.TXEN = 1;         // Transmit Enable
43
    RCSTAbits.SPEN = 1;         // RX und TX Pins aktivieren
44
}
45

46
void UART_Zeichen_senden(unsigned char zeichen)
47
{
48
    while(!TXSTAbits.TRMT);     // Warten, bis TXREG leer ist
49
    TXREG = zeichen;            // Zeichen senden
50
}
51

52
void UART_Zeile_senden(char *zeile)
53
{
54
    unsigned char c;
55

56
    // Solange senden, bis Stringende erreicht
57
    while((c = *zeile++))
58
    {
59
        // Einzelnes Zeichen senden
60
       UART_Zeichen_senden(c);
61
    }
62
}
63

64
int main(void)
65
{
66
    // Ausgänge initialisieren
67
    Ausgaenge_Init();
68

69
    // Eingänge initialisieren
70
    Eingaenge_Init();
71

72
    // UART initialisieren
73
    UART_Init();
74

75
    // Ausgang C4 auf High
76
    Set_LED_gruen(1);
77

78
    // Hauptschleife
79
    while(1)
80
    {
81
        // Ausgang C3 auf high
82
        Set_LED_rot(1);
83

84
        // Warten
85
        Delay10KTCYx(64);
86

87
        // Ausgang C3 auf low
88
        Set_LED_rot(0);
89

90
        // Warten
91
        Delay10KTCYx(255);
92

93
        // UART Test
94
        UART_Zeichen_senden('M');
95
        UART_Zeichen_senden('I');
96
        UART_Zeichen_senden('C');
97
        UART_Zeichen_senden('R');
98
        UART_Zeichen_senden('O');
99
        UART_Zeichen_senden('C');
100
        UART_Zeichen_senden('H');
101
        UART_Zeichen_senden('I');
102
        UART_Zeichen_senden('P');
103
        UART_Zeichen_senden('.');
104

105
        UART_Zeile_senden("TECHNOLOGY.");
106
   }
107

108
   return 0;
109
}
Gast #3070642
Lesenswert?

>und mich mal durch gute C-Bücher lesen

Das wird leider auch nichts helfen, wenn du das Grundprinzip der 
seriellen Datenübertragung beim Senden nicht kapieren willst!

Man muss ERST abfragen, ob das VORHERIGE Zeichen rausgegangen ist und 
der Sendebuffer somit frei (geworden) ist.
NUR DANN darf man in das Sende-Datenregister schreiben.

Du machst das genau falsch herum und so hast du den Effekt "jeden 2. 
Zeichen fehlt" und ähnliches.

Anschliessend warten braucht man nicht bzw. sollte das auch nicht tun.
Warum?  Das kannst dir jetzt selbst überlegen!

Gruss
#3070659
Lesenswert?

Erich schrieb:

> Man muss ERST abfragen, ob das VORHERIGE Zeichen rausgegangen ist und
> der Sendebuffer somit frei (geworden) ist.


Macht er ja jetzt auch nicht mehr
1
void UART_Zeichen_senden(unsigned char zeichen)
2
{
3
    while(!TXSTAbits.TRMT);     // Warten, bis TXREG leer ist
4
    TXREG = zeichen;            // Zeichen senden
5
}
´
Das sieht für mich durchaus OK aus.

Aber wenn ich mich recht erinnere, und worauf auch Holger hinauswollte: 
Auf einigen PIC gibt es da so einen Fallstrick, dass ein 
Character-Literal, also ein konstanter String - eben nicht ein const 
char* ist, sondern dass das ganze übers Flash abgewickelt wird (da wird 
der String in den Programmcode eingebettet). D.h. man muss dauernd drauf 
achten, ob man jetzt eine String-Konstante oder ein tatsächlich 
variables char-Array hat und dann je nachdem die richtige Funktion 
aufrufen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren