Hey,
bei meinen neuen Projekt versuche ich zum ersten mal einen PIC18f4550
über ein RS232-Kabel mit meinen PC zu verbinden. Das Empfangen und
Senden von Daten von und zum PC funktioniert erstmal super. Nur leider
nicht mehr wenn ich das vom PC Empfangene Zeichen in einen String
schreibe.
Das blinken an PortA0 wird deutlich langsamer (immer 1sek an und 1aus).
Singnale an PortA1 nur noch verzögert und an PortA2 kommt garnix mehr.
Pic läuft mit 18,432MHZ
Bitte helft mir! Ich bin am Verzweifeln...
main.c
Wo benutzt du einen string? Du hast zwar die Library eingebunden, nutzt
sie aber nicht. Du verwendest ein char Array, was zugegebenermassen auch
ein string ist.
Die einzige "Falle", wo das Programm stecken bleiben könnte, sehe ich in
der Funktion putsUSART:
Du übergibst ein Array (hier ein string). Du sendest solange Zeichen,
bis im übergebenen Array der Wert 0 steht. Am Ende eines strings steht
jedoch immer ein '\0'. Finde heraus, was dein Programm dort wirklich
tut. Ausserdem kann das Programm auch hier
1
while(busyUSART()==1){}
steckenbleiben
Was ich sonst noch gesehen habe:
- In der main Funktion wird nicht geprüft, ob die Variable usartcount
grösser gleich 25 ist (ist zwar auskommentiert, vielleicht willst du's
ja mal verwenden).
- Warum wartest du zwischen den einzelnen Zeichen immer 100ms? Bei
19.2kbaud dauert das Senden/Empfangen eines Zeichens ca. 520us (8 Bits +
2 Start-/Stoppbits).
Noch was. Wenn dieser Teil nicht auskommentiert ist:
1
if(usartbuffer[usartcount]=='\r'){
2
usartbuffer[usartcount+1]=0;
3
putsUSART(usartbuffer);
4
usartcount=0;
5
}else{
6
usartcount+=1;
7
}
wirst du Probleme haben. In der Funktion putsUSART werden Zeichen
gesendet, bis der Wert 0 im Array steht. Du schreibst aber nie den Wert
0 in das Array. Daher kann das Programm quer durch den Speicher Werte
senden und mit etwas Glück hört es irgendwann auf.
Jörg Marschner schrieb:> while(1)> { LATA0=!LATA0; delay(100);> char received = getcUSART();> if( received ) {
Ich hasse solche Art des Quellcodeschreibens. Versuche doch wenigstens,
nicht ständig Variablendeklarationen und deren Benutzung in einen Topf
zu werfen. So unsäglich faul kannst du doch wohl nicht sein!
void MyBlaBla(void)
{ char received;
while(mycondition)
{ if CharAvailable()
{ received = GetTheChar();
DoSomethingWithIt(received);
}
}
}
Es ist immer eine oberfaule Sache, ein Array einfach vollaufen zu
lassen, ohne zu prüfen, ob man damit einen Bufferoverrun verursacht. Am
PC ist das immer noch die beliebteste Methode, um Scheunentore für
Malware aufzureißen. Also lerne mal, einen Ringpuffer zu programmieren.
Ansonsten sieht dein Programm reichlich prozedural aus und das ist keine
gute Sache, wenn man mehrere Dinge erledige will, z.B. Empfangen, darauf
vor Ort reagieren und obendrein noch was senden. Für sowas solltest du
dir einen anderen Ansatz für's Ganze angewöhnen: Ereignisorientierte
Programmierung.
Und wozu du unbedingt 100 ms vertrödeln willst, außer zum Verpassen von
empfangenen Zeichen, ist mir ebenfalls unklar.
W.S.
Jörg Marschner schrieb:> Hey,> bei meinen neuen Projekt versuche ich zum ersten mal einen PIC18f4550> über ein RS232-Kabel mit meinen PC zu verbinden.
Nur mal so aus Neugier: Hat dein PC kein USB?
Der Rest wurde ja schon gesagt.
Grüße.
Vielen Dank für die Hinweiße! Ich wird es mir zu Herzen nehmen und mich
heut Abend gleich noch mal hinsetzen und die ganze Sache überarbeiten.
Die 100-ms-Verzögerung hab ich nur zum Debuggen einprogrammiert, um
besser sehen zu können wann und wo meine LEDs angesteuert werden bzw.
die Ports ein Signal ausgeben. Später soll die Verzögerung natürlich
komplett weg.
Also dann vielen Dank ich werd euch informieren, wenn es funktioniert!
Gruß Jörg
Update: Ich hab in den letzten Wochen fast alles Getestet... Ich hab mir
extra noch 2 PICs zugelegt mit dem ergebnis das ich Daten zum Pic
schicken kann und vom Pic zum PC. Allerdings scheinen sich die Pics alle
zu weigern meine einzeln gesendeten Zeichen in eine Array zuschreiben
und auf ein Enter (\r) an mich zurückzusenden...
Bitte schaut doch nochmal drüber ihr seit meine letzte Hoffnung!
PIC18F4550
18,432MHZ
9600Bound
usart.h (Ja ich weiß ich verwende den Datentyp hier falsch - bitte ni
böse sein)
1
//Initialisiert die USART Schnittstelle
2
voidinitUSART(unsignedintspbrg){
3
SPBRG=spbrg;
4
RCSTAbits.SPEN=1;
5
TXSTAbits.TXEN=1;
6
RCSTAbits.CREN=1;
7
}
8
9
//Schreibt ein Byte in das Tranmit-Register und
10
//überträgt dieses
11
voidwriteUSART(unsignedchardata){
12
while(PIR1bits.TXIF==0);// Wait for USART
13
TXREG=data;// Store data in Transmit register
14
}
15
16
17
//Überträgt mehrere Zeichen über die USART-Schnittstelle
18
voidputsUSART(unsignedchar*data){
19
inti=0;
20
while(data[i]){
21
writeUSART(data[i]);//Übertrage das Zeichen
22
i++;
23
}
24
}
25
26
//liest ein Zeichen aus dem Empfangspuffer aus
27
unsignedchargetcUSART(void){
28
if(PIR1bits.RCIF!=0){// Wait until RCIF gets low
29
returnRCREG;// Retrieve data from reception register
30
}
31
return0;
32
}
main.c
1
#include<htc.h>
2
#include<pic18f4550.h>
3
#include<stdio.h>
4
#include<stdlib.h>
5
#include<string.h>
6
#include"usart.h"
7
8
#define FREQ 18432000 // Frequency = 12MHz
9
#define baud 9600
10
#define spbrg_value (((FREQ/64)/baud)-1) // Refer to the formula for Baud rate calculation in Description tab
11
12
voidmain(void)
13
{
14
// PORT A
15
LATA=0b00000000;
16
TRISA=0b00000000;// Alle Ports sind Ausgänge
17
18
// PORT B
19
LATB=0b00000000;
20
TRISB=0b00000000;// Alle Ports sind Ausgänge
21
22
TRISCbits.TRISC7=1;//Make UART RX pin input
23
TRISCbits.TRISC6=1;//Make UART TX pin output
24
25
voidinitUSART(spbrg_value);
26
27
unsignedcharbuf[32];
28
unsignedintcount=0;
29
30
putsUSART("Hallo ");// Funktioniert und kommt am pc ohne fehler an
31
putsUSART("TEST");// Funktioniert und kommt am pc ohne fehler an
32
33
while(1)
34
{
35
unsignedcharusartin=getcUSART();// Funktioniert
36
if(usartin!=0){
37
if(usartin=='\r'){// Funktioniert wird aufgerufen
38
buf[count]='\0';
39
putsUSART(buf);// Geht nicht
40
count=0;
41
}else{
42
writeUSART(usartin);// Funktioniert und kommt am pc ohne fehler an
43
buf[count]=usartin;// Scheint nicht zu funktonieren.. WARUM????
Jörg Marschner schrieb:> buf[count] = usartin; // Scheint nicht zu funktonieren.. WARUM????
Probiere direkt nach dieser Zeile mal ein
writeUSART(buf[count]);
Kommt das auch an? (Bitte mit -O0 kompilieren.)
wenn ich direkt nach: buf[count] = usartin;
writeUSART(buf[count]); schreibe,
dann kommt von der Funktion nur Mist zurück der Rest funktioniert...
Also scheint ja wirklich mit der Zuweisung was nicht zu stimmen..
Von welcher Funktion kommt Mist zurück? Und was funktioniert dann
plötzlich? Die spätere Ausgabe von buf?
Verschiebe die Deklaration von buf mal aus der main raus. Also mache
eine globale Variable daraus. Ich hätte evtl. noch ein Bug beim Inlining
von getcUSART vermutet, aber wenn es mit -O0 auch auftritt, dann kann
man das ausschließen. Ansonsten poste mal noch die Ausgabe von
avr-objdump -S "dein binary". Dann kann man mal schauen ob mit dem
generierten Code etwas nicht stimmt.
Ich hab den PIC18-Simulator von OshonSoft... Dort funktioniert das
Programm/das HEX-File jedoch fehlerfrei. Und die Fehlersuche im
Schaltkreis hat Ergeben das der PIC keine Daten in die char array
schreiben kann/will. Weder so wie es im Programm steht noch mit
strcpy(); und auch nicht wenn man direkt char buf[] = "Text der rein
soll"; schreibt.
Mir ist leider absulut nicht klar warum, vorallen da alles andere
Funktioniert und dieser Fehler bei 3 verschiedenen PICs auftritt.
Auch wenn mit SPEN=1 die Portpins für den UART geschaltet werden, würde
ich sicherheitshalber
"TRISCbits.TRISC6=1; //Make UART TX pin output" in
"TRISCbits.TRISC6=0;" ändern. Bei dir ist der Pin auf INPUT gestellt.
Laut Datenblatt sollen TRISC6 und TRISC7 auf 1 gestellt werden. Habs
trotzdem probiert und es bringt keine Veränderung. Die reine
USART-Übertragung funktioniert ja auch ohne Probleme.
Jörg Marschner schrieb:> Wie gesagt USART-Kommunikation funktioniert.
Tja - vielleicht wird der String / Array falsch übergeben, wenn es an
der USART nicht liegt.
Kannst ja mal probieren statt
unsigned char buf[32];
char *buf='dummytext........................'; // <- genügend Zeichen in
den String, damit Speicherplatz belegt wird
zu verwenden.
VG
Ray
teste doch mal:
...
if (usartin=='\r') { // Funktioniert wird aufgerufen
buf[count] = '\0';
putsUSART("TEST");
writeUSART('0'+count);
putsUSART(buf); // Geht nicht
count=0;
} else {
...
vg
Martin
Hey Ray, dein Vorschlag liefert ein echt interessantes Ergebnis. Wenn
ich Enter drücke bekomm ich vom PIC immer den Dummytext zurück.
Komischerweiße nie die Zeichen die der PIC vorher empfangen hat...
komisch
@Martin: writeUSART(count); funktioniert und liefert mir die Anzahl der
Zeichen die der PIC vorher empfangen hat.
Hier noch der Code von main.c an usart.h hat sich nix geändert...
1
#include<htc.h>
2
#include<pic18f4550.h>
3
#include<stdio.h>
4
#include<stdlib.h>
5
#include<string.h>
6
#include"usart.h"
7
8
#define FREQ 18432000 // Frequency = 18,432MHz
9
#define baud 9600
10
#define spbrg_value (((FREQ/64)/baud)-1) // Refer to the formula for Baud rate calculation in Description tab
Jörg Marschner schrieb:> unsigned char *buf = "....a....a....a....a....a....a....a";
so und jetzt wirfst du das gleich wieder raus und ersetzt es, wie
gehabt, duch
unsigned char buf[30];
Denn so, mit dem Pointer, ist es definitiv falsch. Nicht wegen dem
Pointer, sondern weil der Pointer auf ein Stringliteral zeigt. Und an
dem hast du nichts rumzufummeln.
also bei jedem halbwegs normalen Compiler wird bei folgendem Ausdruck:
unsigned char *buf = "....a....a....a....a....a....a....a";
die Variable buf ins Ram gelegt und mit der Adresse des Strings
"....a....a....a....a....a....a....a" initialisieren. Compiler und
Linker sorgen dafür, dass ale Strings sortiert und von Doubletten
befreit ins Flash wandern. Und dort kann man nun mal nichts
hinschreiben. Du kannst zwar buf eine andere Adresse zuweisen aber den
String selbst nicht ändern. Kommst du von AVR? Dort würdes das gehen,
deshalb macht man auch die Krücke mit dem PROGMEM um solche Strings in
den Flash zu verlagern um nicht den Ram damit zu zu müllen. "buf[count]
= usartin;" geht des wegen nicht!
unsigned char buf[] = "....a....a....a....a....a....a....a";
Dieser Ausdruck (ob das bei allen Comiplern geht weiss ich nicht) macht
das anders. Er belegt soviel Bytes im Ram wie der String lang ist +1.
Diesen Buffer kann man dann nach belieben ändern.
Hoffe das das bei deinem PIC Compiler so ist. Zumindestens ist das der
normalfall für den gcc.
Würde unsigned char buf[] = "....a....a....a....a....a....a....a"; nicht
das selbe bewirken wie unsigned char buf[30];?
Also RAM freihalten/belegen?
Funktioniert aber jedenfalls auch nicht.
Ich verwende MPLAB X IDE und Hi-Tech PICC18-PRO (v9.80) als Compiler
Ich hab vorher keine noch nie Programme für mC geschrieben (Außer ein
paar kleine LED I/O für PIC16). Daher hab ich mit Arrays nie viel
gemacht. (Zumindest bei mC). Ansonsten schreibe ich abundan PC-Programme
(c/c++ und das nur als xxs-Hobby! Also ohne viel Ahnung) wo ich so ein
Problem noch nie hatte.
das schon, aber wenn man macht:
unsigned char buf[30];
buf="....a....a....a....a....a....a....a";
hat man wieder das gleiche Problem. buf zeigte am Anfang schön auf 30
Bytes im Ram. Nach der Zuweisung zeigt er auf einen readonly Bereich im
Flash.
Ich habe den Thread aber nicht im Detail verfolgt. (Heute ist Feiertag!)
Also mit anderen Worten, ob du das so machst weiss ich nicht,, aber wenn
dann ist das falsch!
@Gast
Kurz und Knapp. Nein das mach ich nicht.
Das Feiertag ist weiß ich und nimm es mir bitte nicht übel aber niemand
zwingt dich zum Feiertag oder sonstwann sich um meine Probleme zu
kümmern.
Nicht falsch verstehen ich bin für alle Hinweiße und Ratschläge dankbar
und ich weiß zu schätzen das es Leute gibt die sich vollkommen
unentgeldlich um Probleme anderer kümmern! Wenn es so eine Seite bzw so
ein Forum mit all seinen Mitgliedern nicht gäbe.... Ich will gar ni dran
denken... Aber trotzdem muss ich sagen niemand zwingt dich (schon
garnicht an einem Feiertag)
Gruß Jörg
Hey Leute! Vielen Dank für eure Hilfe, jetzt hab ich die Lösung...
Seht hier Beitrag "Array beschreiben schlägt fehl"
Einfach volatile vor die char-Array und vor int count=0; und schon
gehts...
Optimierung steht zwar schon auf none aber na gut...