Hallo Leute,
ich bräuchte eure Hilfe!
Ich verwende MPLAB X IDE zum programmieren, da ich einen PIC
Mikrocontroller verwende.
Ich hab mich jetzt schon länger eingearbeitet und möchte Daten von einem
Mikrocontroller zum PC per Bluetooth schicken. Das ganze funktioniert
soweit auch.
Mein Problem:
Ich möchte mein Programm jetzt in mehrere Source-files unterteilen. Dazu
habe ich die einzelnen Source files und dazugehörige header-files
angelegt.
Mein Programm arbeitet diese files auch wunderbar nacheinander ab.
Leider hänge ich dabei noch etwas, wenn es darum geht ein char-Array zu
übergeben.
In meiner Main baue ich mir ein char Array, dass 8 Zeichen lang ist =>
funktioniert wunderbar!
Anschließend rufe ich meine Funktion auf und möchte mein gebautes Array
dort haben!
Ich habe mir gedacht, ich mache das folgendermaßen:
in meiner Main (die durch eine Schleife immer wieder neu abgearbeitet
wird) rufe ich folgende Funktion auf und baue mir daraus mein Array:
1
intBluetooth_send()
2
{
3
staticintlaufvar=0;
4
staticintsendezahl=0;
5
intLaenge=8;
6
charsenden[8];
7
staticintsperren=1;
8
9
if(sperren==1)
10
{
11
//Byte-Array zum senden bauen
12
senden[sendezahl]=0x02;//STX senden
13
sendezahl++;
14
if((data0==0x03)||(data0==0x16))//Wenn ETX oder DLE in Nutzdaten vorkommt
15
{
16
senden[sendezahl]=0x16;//DLE einfügen
17
sendezahl++;
18
senden[sendezahl]=data0;
19
sendezahl++;
20
}
21
else
22
{
23
senden[sendezahl]=data0;
24
sendezahl++;
25
}
26
27
if((data1==0x03)||(data1==0x16))
28
{
29
senden[sendezahl]=0x16;
30
sendezahl++;
31
senden[sendezahl]=data1;
32
sendezahl++;
33
}
34
else
35
{
36
senden[sendezahl]=data1;
37
sendezahl++;
38
}
39
40
if((data2==0x03)||(data2==0x16))
41
{
42
senden[sendezahl]=0x16;
43
sendezahl++;
44
senden[sendezahl]=data2;
45
sendezahl++;
46
}
47
else
48
{
49
senden[sendezahl]=data2;
50
sendezahl++;
51
}
52
53
if((data3==0x03)||(data3==0x16))
54
{
55
senden[sendezahl]=0x16;
56
sendezahl++;
57
senden[sendezahl]=data3;
58
sendezahl++;
59
}
60
else
61
{
62
senden[sendezahl]=data3;
63
sendezahl++;
64
}
65
66
if((din==0x03)||(din==0x16))
67
{
68
senden[sendezahl]=0x16;
69
sendezahl++;
70
senden[sendezahl]=din;
71
sendezahl++;
72
}
73
else
74
{
75
senden[sendezahl]=din;
76
sendezahl++;
77
}
78
79
80
if((laufvar==0x03)||(laufvar==0x16))
81
{
82
senden[sendezahl]=0x16;
83
sendezahl++;
84
senden[sendezahl]=laufvar;
85
laufvar++;
86
sendezahl++;
87
}
88
else
89
{
90
if(laufvar<=255)//Laufvariable um Datenempfang beim Empfänger prüfen zu können
91
{
92
senden[sendezahl]=laufvar;//Zählt von 0-255 und beginnt wieder bei 0
93
laufvar++;
94
sendezahl++;
95
}
96
else
97
{
98
senden[sendezahl]=0;
99
laufvar=1;
100
sendezahl++;
101
}
102
}
103
104
senden[sendezahl]=0x03;
105
sendezahl=0;
106
}
107
sperren=Bluetooth_Send(Laenge,senden);// Hier wird Bluetooth_Send aufgerufen
108
109
return0;
110
}
Ich weiß, dass das ganze durch die DLE maskierung auch länger als 8
werden kann (muss ich später noch ändern), aber das stört vorläufig
nicht.
Mein Header sieht wie folgt aus:
__delay_us(80);//Verzögerung um Bluetoothmodul nicht zu überfordern (80µs)
21
if(!IFS0bits.U1TXIF)//Wenn Interrupt Flag nicht gesetzt
22
{
23
U1TXREG=senden[i];
24
i++;
25
}
26
else
27
{
28
IFS0bits.U1TXIF=0;//Rücksetzen der Interruptflag
29
}
30
}
31
if(i==Lang)
32
{
33
finish=1;//erst wenn finish = 1, wird ein neues Array gebaut
34
i=0;
35
}
36
else
37
{
38
finish=0;
39
}
40
41
return(finish);
42
}
Mein Array sende ich über ein BLuetoothmodul, und empfange die Daten mit
einem Terminalprogramm (Funktioniert wunderbar)
Die Daten sollen die Struktur wie folgt haben:
STX, 0x00, 0x00, 0x00, 0x00, 0x00, "Laufvariable von 0-255", ETX
...ständig wiederholen (die Nullen werden später mit Sensordaten
befüllt)
Mein Problem ist jetzt, dass ich am Terminalprogramm folgendes empfange:
{FF}{00}{00}{00}{88}{09}{00}{00}{FF}{00}{00}{00}{88}{09}{00}{00}...
und das ganze ständig!
Hab folgendes festgestellt:
nach dem ersten Durchlauf hab ich richtigerweise noch das STX im Array
stehen. Im zweiten Durchlauf ist das bauen eines neuen Arrays
gesperrt(da noch nicht alles gesendet ist). So bald ich nun wieder meine
Funktion fürs Senden aufrufe, werden beliebige Werte in mein Array
geschrieben. => Eben diese, die dann auch gesendet werden. Warum?
Bitte um Hilfe!
Gruß Chris
Das hat zwar mit deinem Problem nichts zu tun, deine #includes sehen mit
den vollen Namen merkwürdig aus:
1
#define FCY 16000000UL
2
#include<xc.h>
3
#include<stdint.h>
4
#include<stdio.h>
5
.
6
.
so sieht das bei mir aus. Und p33FJ16GS404.h gehört da garnicht hin, das
erledigt xc.h automatisch. Ich schreib auch die Config-Bits mit in den
Source, dann kann man nichts falsch einstellen und weiß auch in paar
Monaten noch, wie sie sein sollen.
Christian O. schrieb:> char senden[8];
Das ist eine sogenannte Auto-Variable. Die liegt auf dem Stack und das
Array enthält erstmal nicht zwingend 0-Werte.
Ich verstehe Deine Logik nicht, aber ist immer gewährleistet, dass
niemals mehr als 8 Daten da hinein gelangen? Wenn mehrere Bedingungen
wahr sind, können die Variable sendezahl größer als 8 werden.
Beim Funktionsaufruf
Bluetooth_Send(Laenge, senden);
gibst Du auch gar nicht "sendezahl" herunter. Sie erhält also keine
Information, wieviele Zeichen Du mittlerweile in "senden" gesammelt hast
und wieviele Du senden willst.
Willst Du das wirklich so? Und wenn sendezahl am Ende nur 6 ist,
schickst Du dann noch 2 zufällige Werte aus dem Array hinterher?
Hui, das sieht ja wirr aus. Ich fang einfach mal irgendwo an.
Du hast zwei Funktionen, die fast identisch heissen, das ist eher
verwirrend (Bluetooth_send vs. Bluetooth_Send). Funktionen sollten das
tun, was ihr Name verspricht, das ist bei mindestens einer der beiden
nicht der Fall.
1
staticintsendezahl=0;
Das static kannst du dir sparen, du setzt die Variable am Ende der
Funktion so oder so wieder auf Null.
1
charsenden[8];
Der Inhalt des Arrays ist ersmal undefiniert. Es steht halt das drin,
was gerade zufälligerweise dort im RAM steht. Benutze den Datentypen
char nur, wenn du die Variable für Zeichen nutzen willst. Merke dir:
char != signed char
char != unsigned char
1
senden[sendezahl]=0x02;//STX senden
2
sendezahl++;
3
if((data0==0x03)||(data0==0x16))//Wenn ETX oder DLE in Nutzdaten vorkommt
Magic Numbers stiften eher Verwirrung. De Werte kannst du mit einem
Makro oder einer const-Variable definieren. Benutzte aussagekräftige
Namen.
1
if(laufvar<=255)//Laufvariable um Datenempfang beim Empfänger prüfen zu können
2
{
3
senden[sendezahl]=laufvar;//Zählt von 0-255 und beginnt wieder bei 0
4
laufvar++;
5
sendezahl++;
6
}
7
else
8
{
9
senden[sendezahl]=0;
10
laufvar=1;
11
sendezahl++;
12
}
13
}
Der Kommentar ist falsch. laufvar zählt von 1-256, wobei 256 abgefangen
und die Null manuell zugewiesen wird. So wäre es übersichtlicher
(funktioniert nur, wenn ein unsigned char 8 Bit hat):
1
staticunsignedcharlaufvar=0;
2
...
3
laufvar++;/* nutzt den Ueberlauf */
4
senden[sendezahl]=laufvar;
5
sendezahl++;
Versuche die Funktion Bluetooth_send besser zu strukturieren. Irgendwie
werden Werte abhängig von globalen Variablen in ein Array geschrieben.
Keiner weiss, wie viele Werte tatsätzlich geschrieben werden. Als
Maximum habe ich 14 gezählt, dein Array hat aber die Länge 8.
Grundsätzlich habe ich deine Funktion so verstanden:
- Erzeuge ein Array aus den Werten data0, data1, data2, data3, din und
laufvar.
- Der erste Wert im Array ist STX.
- Für alle Werte:
- Ist der Wert gleich ETX oder DLF, schreibe DLF und anschliessend den
Wert, ansonsten nur den Wert.
- Der letzte Wert im Array ist ETX.
Versuche identische Funktionalität in universelle Funktionen zu
verpacken, z.B. das Schreiben der einzelnen Werte in das Array.
Was mir noch gerade aufgefallen ist:
Bluetooth_Send verarscht den Aufrufer so richtig. Es sendet nur das
nächste Byte, nicht das gesamte Array. Das Array wird jedoch nach jedem
Durchlauf neu berechnet, somit können wiederum andere Werte an gleicher
Position stehen. Auch der Übergabeparameter Laenge ist immer 8, obwohl
eine variable Anzahl an Werten ins Array geschrieben werden.
Bringe Struktur in dein Programm, so wird das nichts.
Nachtrag:
Normalerweise macht man das so:
Irgendwo werden die Daten erzeugt, die versendet werden müssen. Dann
packt man diese in das geignete Prorotoll und schiebt diese in einen
Sendebuffer (FIFO). Eine andere unabhängige Instanz prüft zyklisch, ob
Daten im Buffer vorhanden sind und ob das Sendemodul verfügbar ist.
Trifft beides zu, veranlasst die Instanz, dass das Sendemodul die Daten
versendet.
Erstmal danke für eure Antworten!
Frank M. schrieb
>Ich verstehe Deine Logik nicht, aber ist immer gewährleistet, dass>niemals mehr als 8 Daten da hinein gelangen? Wenn mehrere Bedingungen>wahr sind, können die Variable sendezahl größer als 8 werden.
Ja es kann größer werden, dass weiß ich auch... für das Problem wollte
ich mir eine Lösung überlegen, so bald meine Daten richtig übergeben
werden bzw. gesendet werden => Das spielt im Moment erst mal keine Rolle
für mein Problem
>gibst Du auch gar nicht "sendezahl" herunter. Sie erhält also keine>Information, wieviele Zeichen Du mittlerweile in "senden" gesammelt hast>und wieviele Du senden willst.
Ich wollte das erst mal statisch mit 8 Zeichen machen um zu überprüfen
ob das Senden überhaupt funktioniert! Um die ganze Problematik wollte
ich mich später kümmern!
be stucki schrieb:
>Hui, das sieht ja wirr aus. Ich fang einfach mal irgendwo an.
Ich weiß schäm! Ich werde versuchen das Programm etwas besser zu
strukturieren und meine Namen der Funktionen anzupassen!
>Das static kannst du dir sparen, du setzt die Variable am Ende der>Funktion so oder so wieder auf Null.
Verstanden!
>Der Inhalt des Arrays ist ersmal undefiniert. Es steht halt das drin,>was gerade zufälligerweise dort im RAM steht. Benutze den Datentypen>char nur, wenn du die Variable für Zeichen nutzen willst.
Das da erst mal undefiniert Dinge aus dem RAM stehen ist mir bewust. Was
würdest du für einen Datentyp benutzen? STX DEL und ETX sind ja ASCII
zeichen... und die hex-Werte zwischendrin kann man ja auch als Zeichen
verstehen... ist also doch kein Problem oder?!
>Der Kommentar ist falsch. laufvar zählt von 1-256, wobei 256 abgefangen>und die Null manuell zugewiesen wird. So wäre es übersichtlicher
Für mich war in dem Kommentar eher die Überlegung was ich am Ende raus
bekomme... da wird der Wert von 0 auf 255 erhöht und wieder bei 0
angefangen....gelöst ist das eben mit dem Zähler von 1-256... mal sehen
ob ich das vllt noch anders mache! Werd mir deinen Vorschlag durch den
Kopf gehen lassen.
>Versuche die Funktion Bluetooth_send besser zu strukturieren. Irgendwie>werden Werte abhängig von globalen Variablen in ein Array geschrieben.>Keiner weiss, wie viele Werte tatsätzlich geschrieben werden. Als>Maximum habe ich 14 gezählt, dein Array hat aber die Länge 8.
Jop stimmt! Das Problem werd ich lösen, wenn meine Übergabe prinzipiell
erst mal funktioniert! (Ob ich da eventuell ein paar Werte verliere,
interessiert mich vorerst nicht... ;-) )
>Grundsätzlich habe ich deine Funktion so verstanden:>- Erzeuge ein Array aus den Werten data0, data1, data2, data3, din und>laufvar.>- Der erste Wert im Array ist STX.>- Für alle Werte:> - Ist der Wert gleich ETX oder DLF, schreibe DLF und anschliessend den>Wert, ansonsten nur den Wert.>- Der letzte Wert im Array ist ETX.
Genau so soll es sein!
>Was mir noch gerade aufgefallen ist:>Bluetooth_Send verarscht den Aufrufer so richtig. Es sendet nur das>nächste Byte, nicht das gesamte Array. Das Array wird jedoch nach jedem>Durchlauf neu berechnet, somit können wiederum andere Werte an gleicher>Position stehen. Auch der Übergabeparameter Laenge ist immer 8, obwohl>eine variable Anzahl an Werten ins Array geschrieben werden.
Ja er sendet nur das nächste Byte (ich wollte hier eine Schleife im
Source-file vermeiden). Die Schleife habe ich in der Main, die immer
wieder meine Sendefunktion aufruft! Das Array wird nicht nach jedem
Aufruf neu berechnet, da ich erst wenn ich 8 Bytes gesendet habe, eine
Freigabe zum neu berechnen erteile:
Vor dem Bauen des Arrays steht folgende Anweisung:
1
if(sperren==1)
sperren schalte ich mit hilfe der Sendefunktion auf 0:
1
if(i==Lang)
2
{
3
finish=1;//erst wenn finish = 1, wird ein neues Array gebaut
4
i=0;
5
}
6
else
7
{
8
finish=0;
9
}
10
11
return(finish);
Mein Problem ist jetzt, dass beim zweiten Durchlauf (wo dann das Bauen
des Arrays gespert ist) einfach beliebige Werte in das Array geschrieben
werden, die dann gesendet werden....Ich verstehe nicht warum! Wenn ein
Array einmal befüllt ist, behält er doch normalerweise die Werte oder
nicht?
Könnte es sein, dass wegen meiner deklaration im Header das Array jedes
mal beliebig befüllt wird bzw. einer anderen Adresse zugewiesen wird
wenn ich die Funktion neu aufrufe?
>Normalerweise macht man das so:>Irgendwo werden die Daten erzeugt, die versendet werden müssen. Dann>packt man diese in das geignete Prorotoll und schiebt diese in einen>Sendebuffer (FIFO). Eine andere unabhängige Instanz prüft zyklisch, ob>Daten im Buffer vorhanden sind und ob das Sendemodul verfügbar ist.>Trifft beides zu, veranlasst die Instanz, dass das Sendemodul die Daten>versendet.
Daten erzeugen wird in einer separaten Funktion gemacht, die meine
Eingänge auslesen. Diese werden dann in data0 etc. gespeichert. Aus
diesen wird dann mein Array gebaut.
Das ganze möchte ich dann via UART an mein BLuetoothmodul schicken.
Hierzu wird mein Byte durch das U1TXREG in den FIFO-Sendebuffer
geschoben. (dieser ist maximal 4Byte lang, weshalb ich einfach jedes
Byte extra rein packe.)
1
if(!IFS0bits.U1TXIF)//Wenn Interrupt Flag nicht gesetzt
Durch diese Abfrage prüfe ich, ob das Sendemodul bereit ist, Daten zu
senden. Die Interrupt Flag muss ich dann manuell wieder rücksetzen um
senden zu können.
Das ist doch also in etwa das, was du gemeint hast oder?
Aber wie gesagt, mein Problem ist ja aktuell ein anderes!
"Mein Problem ist jetzt, dass beim zweiten Durchlauf (wo dann das Bauen
des Arrays gespert ist) einfach beliebige Werte in das Array geschrieben
werden, die dann gesendet werden....Ich verstehe nicht warum! Wenn ein
Array einmal befüllt ist, behält er doch normalerweise die Werte oder
nicht?
Könnte es sein, dass wegen meiner deklaration im Header das Array jedes
mal beliebig befüllt wird bzw. einer anderen Adresse zugewiesen wird
wenn ich die Funktion neu aufrufe?"
Christian O. schrieb:> Mein Problem ist jetzt, dass beim zweiten Durchlauf (wo dann das Bauen> des Arrays gespert ist) einfach beliebige Werte in das Array geschrieben> werden, die dann gesendet werden....Ich verstehe nicht warum! Wenn ein> Array einmal befüllt ist, behält er doch normalerweise die Werte oder> nicht?
Dann musst du das Array als static definieren, so wie du es bei anderen
Variablen tust. Ansonsten wird das Array bei jedem Funktionsaufruf mit
"zufälligen" Werten gefüllt.
Christian O. schrieb:> Könnte es sein, dass wegen meiner deklaration im Header das Array jedes> mal beliebig befüllt wird bzw. einer anderen Adresse zugewiesen wird> wenn ich die Funktion neu aufrufe?"
Ja, natürlich.
Entweder Du machst das Array static statt wie jetzt implizit auto, oder
Du initialisierst es zunächst mit 8 Nullen.
Christian O. schrieb:> Was> würdest du für einen Datentyp benutzen? STX DEL und ETX sind ja ASCII> zeichen... und die hex-Werte zwischendrin kann man ja auch als Zeichen> verstehen... ist also doch kein Problem oder?!
Wenns ASCII-Zeichen sind, ist char ok. Sonderzeichen würde ich jedoch
zur besseren Lesbarkeit des Codes als Makro hinschreiben:
1
#define ASCII_STX 0x02
2
// usw...
Christian O. schrieb:> Jop stimmt! Das Problem werd ich lösen, wenn meine Übergabe prinzipiell> erst mal funktioniert! (Ob ich da eventuell ein paar Werte verliere,> interessiert mich vorerst nicht... ;-) )
Das macht man schon grundsätzlich so, wie du das gemacht hast: Übergabe
eines Zeigers + Länge. Andererseits ist dein Array mit ETX terminiert
(wie ein String mit '\0'), dann kannst du dir die Längenangabe sparen.
Kann jedoch auch Verwirrung stiften, da ein char-Array normalerweise für
Strings verwendet wird. Also evt. doch noch die '\0' am Schluss
spenieren. Eigentlich ist es ja auch nichts anderes als ein String.