Versuche vergebens und komme zu keinem Ergebnis. Vielleicht wisst ihr ja
wie ich es besser machen kann
bei C#:
serialPort1.Write(Time); //So schicke ich meinen String mit der Zeit auf
die Datenleitung
beim µC:
uint8_t uart_getc(void)
{
while (!(UCSR0A & (1<<RXC0))) // warten bis Zeichen verfuegbar
;
return UDR0; // Zeichen aus UDR an Aufrufer zurueckgeben
}
void uart_gets( char* Buffer, uint8_t MaxLen )
{
uint8_t NextChar;
uint8_t StringLen = 0;
NextChar = uart_getc(); // Warte auf und empfange das nächste
Zeichen
// Sammle solange Zeichen, bis:
// * entweder das String Ende Zeichen
kam
// * oder das aufnehmende Array voll
ist
while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
*Buffer++ = NextChar;
StringLen++;
NextChar = uart_getc();
}
// Noch ein '\0' anhängen um einen
Standard
// C-String daraus zu machen
*Buffer = '\0';
}
und wo genau ist dein problem??
ich persönlich würde die zeit einfach als normalen byte wert übertragen,
und jenachdem wo das byte liegt wird es interpretiert:
0-59=sekunde
60-119=minute
120-143=stunde
and so on
ausserdem solltest du vll deinen gesamten code anhängen
VON THRON schrieb:> serialPort1.Write(Time); //So schicke ich meinen String mit der Zeit auf> die Datenleitung
und woher sollen wir wissen welchen wert Time hat? Du wartest auf ein \n
schickt du es auch ab?
Peter II schrieb:> und woher sollen wir wissen welchen wert Time hat? Du wartest auf ein \n> schickt du es auch ab?
string Time = DateTime.Now.ToShortTimeString();
serialPort1.Open();
serialPort1.WriteLine("s"); //Startzeichen für Atmega zum übertragen
serialPort1.Write(Time);
VON THRON schrieb:> string Time = DateTime.Now.ToShortTimeString();
und hier wartest du auf
while( NextChar != '\n' && StringLen < MaxLen - 1 ) {
du sendest also kein \n also braucht du auch nicht darauf warten. woher
sollen wir jetzt MaxLen wissen?
Schicke bitte den vollständigen code sonst kann dir niemand helfen.
void Uhrstellen()
{
uart_gets( line, sizeof( line ) );
}
wollte dann beim einlesen so die daten reinholen und auslesen.
und damit die Uhr stellen. diese läuft soweit allerdings startet sie
immer wieder erst bei 0. und sollte über string von c# gestellt werden.
ISR (TIMER1_COMPA_vect)
{
sekunden++;
if (sekunden == 60)
{
minuten++;
sekunden = 0;
}
if (minuten == 60)
{
stunden++;
minuten = 0;
}
if (stunden == 24)
{
stunden = 0;
}
if ((stunden==23)&(minuten==59)&(sekunden==59))
{
speichern = 1;
}
}
auf dieseb Empfangsinterrupt versuche ich ja drauf zuzugreifen und
einzustellen nur des ganze will irgendwie nicht, bin schon den ganze Tag
mit beschäftigt und es will überhaupt nix.
Marcus B. schrieb:> deine ISR spricht schon gegen die grundregel, dass die ISR so kurz wie> möglich sein soll!
das man die Urzeit in der ISR berechnet ist OK. Sie ist kurz! Man muss
es nicht übertreiben.
Peter II schrieb:> das man die Urzeit in der ISR berechnet ist OK. Sie ist kurz! Man muss> es nicht übertreiben.
Perfektionist halt^^
Vielleicht guckst du mal, ob du wirklich in dem AVR(WELCHER überhaupt?!)
den Interrupt hast, ansonsten bleibt dir nix über als regelmässig zu
gucken ob du was empfangen hast in der main.
Marcus B. schrieb:> Peter II schrieb:>> das man die Urzeit in der ISR berechnet ist OK. Sie ist kurz! Man muss>> es nicht übertreiben.>> Perfektionist halt^^
Das hat in diesem Fall noch nicht mal etwas mit Perfektion zu tun,
sondern ist eine Frage der strukturierten Denkweise. Die Uhrezeit IST
die Kombination aus Stunden/Minuten/Sekunden. Die willst du immer
beisammen halten. Daher ist es auch nur vernünftig, das Erhöhen der
Uhrzeit als eine atomare Aktion aufzufassen, damit es keine ungültigen
Zwischenwerte gibt, die dann erst im Nachhinein irgendwann in der
Hauptschleife korrigiert werden. Eine ISR gewährleistet diese atomare
Aktion ganz von alleine. Und diese paar Inkements und Vergleiche machen
das Kraut auch nicht fett. Dafür kannst du aber von jeder Stelle im
restlichen Programm immer auf die Zeit zugreifen und musst nie
befürchten, dass diese illegal ist, weil das Hochzählen in main noch
nicht stattgefunden hat. INterrupts können jederzeit auftreten! Auch
zwischen deiner Zeit-Korrektur in main und der Auswertung. Deine
Auswertung arbeitet dann mit einer Zeit, die noch nicht korrigiert
wurde.
An den TO
Ich würde als allererstes mal mein C# Programm zur Seite legen, ein
Terminal Programm hochfahren und die Kommunikation vom Terminalprogramm
aus mit dem µC in die Gänge bringen. Das hat den Vorteil, dass der µC
auf demselben Weg antworten kann und zb Zwischenwerte oder sonstige
Statusmeldungen ausgeben kann, die ich dann am Terminal sehe und mir
meinen Reim darauf mache.
Du machst gerade den Kardinalfehler aller Kardinalfehler: Du führst
einen 2 Fronten Krieg. Du weißt nicht, ob dein C# etwas sendet, und was
genau UND du weißt nicht ob und was dein µC empfängt. Das einzige was du
weißt: ES funtkioniert nicht. Und aus diesem zustand musst du raus! Du
musst einen der beiden Teilnehmer in dieser Kommunikation erst mal durch
etwas ersetzen, was a) nachweislich sauber funktioniert und was b) dich
nicht im Dunkeln tappen lässt, was vor sich geht. Ein Terminalprogramm
erfüllt diese Vorgaben. DU bist dann der, der das zu Übertragende
eingibt. Du bist derjenige, der am Terminal tippt
1
s23:02:00 <return>
und dann am µC verfolgt, was dieses bewirkt. Verfolgen in dem Sinne,
dass der µC auf der UART ausgibt
1
s23:02:00 <return>
2
* received String "s23:02:00\n"
3
* s -> set command
4
* extracting hour "23"
5
* extracting minute "02"
6
* extracting second "00"
7
* setting internal clock to h 23, m 02, s 00
8
* finished
und anhand dieser Kontrollausgaben vom µC kannst du dann kontrollieren,
ob alles glatt gegangen ist. Beginnend beim String, den der µC empfangen
hat, bis hin zum Extrahieren der Uhrzeit und dem Übertragen in die
interne Uhr hat der µC jeden Schritt protokolliert.
Wenn auf deinem Terminal steht
1
s23:02:00 <return>
2
* received String "&%ahjs2jk\n"
3
* -> no command
dann hat daher der µC einen ganz anderen String erhalten und man weiß,
an welcher Stelle man nachhaken muss.
Wenn da steht
1
s23:02:00 <return>
2
* received String "s23:02:00\n"
3
* s -> set command
4
* extracting hour "s2"
5
* extracting minute ":0"
6
* extracting second ":0"
7
* setting internal clock to h 0, m 0, s 0
8
* finished
dann jast du dich ganz offenbar beim rausholen der Einzelstrings für
Stunde, Minute, Sekunde irgendwo vertan.
usw. usw.
Du musst Licht ins Dunkel bringen. Davon, dass sich der eine Computer
mit dem anderen Computer unterhält, hast du nichts. Da kannst du nicht
verfolgen was vor sich geht.
VON THRON schrieb:> bin Anfänger und bin mit dieser Aufgabe eindeutig zu überfragt im> gesamten.
Dann empfehel ich dir, deine Uhr erst mal zur Seite zu legen und dich
mit einem neuen Programm erst mal in Kommunikation über UART schlau zu
machen.
Techniken, welche Möglichkeiten gibt es, wie implementiert man sie, wie
überträgt man komplette Strings, usw.
Das alles sind Dinge, über die du halbwegs Bescheid wissen solltest, ehe
du dann die für dich geeignete Methode auswählen und in dein Programm
integrieren kannst.
VON THRON schrieb:> ja das stimmt nur bin ich mit der ganzen µC geschichte nicht wirklich> vertraut.
Dann lerne es.
Sorry, wenn das hart klingt. Aber wir alle mussten da durch.
VON THRON schrieb:> das sind die TOP Hilfen von jedem FORUM! SUPI
Du hast Hilfe erhalten.
Der wohl wichtigste Teil: Fang damit an, dass du die Kommunikation von
einem Terminal aus in die Gänge bringst anstelle von einem C# Programm.
Der nächst wichtigste Teil: Baue in dein Programm AUsgaben ein, so dass
dir das Programm selber weiter hilft und erzählt was es gerade warum und
aufgrund welcher Daten macht.
Die andere Hilfe ist die geklaute uart_gets Funktion (die auch von mir
stammt)
Das alles wurde dir schon vorgekaut.
Ich kann dir zeigen wie ein Rad aussieht, ich kann dir auch raufhelfen.
Aber radfahren musst du ganz alleine lerne.
VON THRON schrieb:> irgendwie ist das doch ein meilenstein vorraus für mich.
Dann fang vorne an und kopier' dir nicht irgendwas zusammen, was du
nicht verstehst.
Initialisiere deinen UART ohne Interrupt und frag' den in der "main" ab.
Wenn ein Zeichen vom Hyperterminal oder woher auch immer empfangen
wurde, schaltest du einen Port mit einer LED. Jetzt weisst du schon mal,
daß dein UART etwas empfangen kann.
Als nächstes wertest du das Zeichen aus. eine "1" LED ein, eine "0" LED
aus. Jetzt empfängst du nicht nur irgendwas, was ja auch Unsinn sein
kann, sondern klar definierte Zeichen.
Nächster Schritt: Zeichen wieder zurück senden usw. usw.
Und jetzt funktioniert deine Kommunikation.
Dann erst versuchst du das mit Interrupt.
Bei deiner jetzigen Vorgehensweise erntest du nur Frust und so schlaue
Tips wie "Nimm erstmal Bascom".
VON THRON schrieb:> das sind die TOP Hilfen von jedem FORUM! SUPI
Und wenn das jeder schreibt, dann kann es so falsch ja nicht sein.
mfg.
Was ist so schwer daran, erst mal mit einem eigenständigen Testprogramm
Erfahrung zu sammeln? Irgendwas in dieser Richtung
1
.....
2
3
intmain()
4
{
5
charc;
6
7
uart_init();//Initialisiere UART
8
9
while(1)
10
{
11
c=uart_getc();
12
if(c=='s'){
13
uart_puts("set command\r\n");
14
uart_puts("waiting for string, terminate with \\n\r\n");
15
16
uart_gets(line,sizeof(line));
17
18
uart_puts("received: ");
19
uart_puts(line);
20
uart_puts("\r\n");
21
}
22
}
23
}
und damit experimentierst du jetzt erst mal.
Vom Hyperterminal aus!
Du kannst ja dann weiter machen und zb aus dem String (der zb so
aussehen muss 23:25:30) die Einzelteile für Stunden, Minute, Sekunde
extrahieren.
Du kannst auch anstelle eines 's' Comamndos, deren 3 postulieren: eines
zum Setzen der Stunde, eines zum Setzen der Minute, eines zum Setzen der
Sekunden.
Du kannst ......
aber wichtig ist: nicht ich soll dir das vorkauen, sondern du sollst es
selber lernen, was du alles machen kannst und welche Möglichkeiten es
gibt (OK, ein paar Anregungen können nie schaden. Aber die hast du ja
jetzt)
Und entscheide dich, ob du den Empfang per Interrupt oder per Polling
(regelmässiges Nachsehen) machen willst. Beides zusammen führt dich nur
ins Verderben.
Da bei dir, so wie es aussieht eine Interrupt Lösung (noch) nicht
notwendig ist, würde ich den Empfangsinterrupt erst mal wieder
stilllegen.
Und WENN das dann funktioniert und du im Detail weißt, was du dem µC
alles schicken musst (Achtung: Jeder Tastendruck zählt. Auch Return ist
ein Tastendruck), DANN kannst du daran gehen und ein C# Programm
schreiben, welches diesen geforderten Text generiert und über die
serielle Schnittstelle schickt. Und dann wird das dann auch auf Anhieb
funktionieren. Und wenn nicht, dann weißt du, dass das Problem erst mal
nicht im µC liegt, sondern im C# Programm.
Nimm statt Hyperterminal lieber Hterm:
http://www.der-hammer.info/terminal/
sieht auf den ersten Blick was komisch aus, aber wenn man die Oberfläche
verstanden hat, geht das mit der Kommunikation über den COM-Port
einfacher
und immer dran denken- nur ein Programm kann auf den Port zugreifen!
mfg
VON THRON schrieb:> ISR Routine des Controllers> cli();
Schon falsch. Mach' dich mit den Grundkonzepten deines Controllers
vertraut. Beim Eintritt in eine ISR sind beim AVR alle (weiteren)
Interrupts automatisch gesperrt.
> while (UCSR0A & (1<<RXC0))> {> verb = UDR0;> }
Wenn du mehr als ein Zeichen empfängst, solltest du dir ggf. den
Überlauf irgendwo vermerken.
> if (verb=='s')> {> uart_gets(text,25);
Das wiederum macht man nun wirklich nicht mehr in einer ISR. Bei
üblichen 9600 Bd braucht jedes Zeichen etwa 1 ms, bis es übern
Draht ist. Das sind für den Controller Ewigkeiten, die er nicht
mit blockierten Interrupts rumlungern sollte.
Aber wie Karl Heinz schon schrieb, vielleicht pollst du ja die UART
für den Anfang erstmal. UART mit Interrupt hat eigentlich nur Sinn,
wenn man dann die Daten innerhalb der ISR in einen Ringpuffer liest,
aber das ist für dich vorerst der übernächste Schritt.
ich brauch den Interrupt da ich ja sobald der ausgelöst hat der
controller ja was machen soll.
irgendwie macht er zwar alles was er soll doch er stellt die Uhr nicht
void zeitstellen()
{ uart_gets(text,25); // hole Text und speichere im
Array
stunden = atoi(text); // wandle Text von string in int
stunden
uart_gets(text1,25); // hole Text1 und speichere im Array
minuten = atoi(text1); // wandle Text von string in int
stunden
//Test Ausgabe Uhr richtige Zeichenfolge
uart_puts("aktuelle Uhrzeit: "); // Test zur Ausgabe der
Aktuellen Zeit
uart_puts(dtostrf( stunden, 1,0,string )); // Zeige Stunden an
uart_puts(":"); // zeige : an
uart_puts(dtostrf( minuten, 1,0,string )); // Zeige Minuten an nach
dem :
uart_puts("\n"); // sende \n zum beenden
}
c sharp:
string help;
string Time=DateTime.Now.ToShortTime();
serialPort1.Open();
serialPort1.Write("b");
help = Time.Substring(0, 2);
serialPort1.Write(help + "\n");
help = Time.Substring(3, 2);
serialPort1.Write(help + "\n");
help = serialPort1.ReadTo("\n");
serialPort1.Close();
VON THRON schrieb:> ich brauch den Interrupt
Sagt wer?
> da ich ja sobald der ausgelöst hat der> controller ja was machen soll.
Du brauchst dein Programm nur oft genug nachsehen lassen, ob an der UART
ein Zeichen reingekommen ist. Das reicht dann schon. Dazu braucht man
erst mal keine Interrupts.
> void zeitstellen()> { uart_gets(text,25); // hole Text und speichere im Array> stunden = atoi(text);
Ich geb dir nochmal den wirklich guten Rat:
Solange du auf diesem Level programmierst, bist du gut beraten, wenn du
erst mal den text, den du von uart_gets bekommst, zur Kontrolle gleich
wieder irgendwo ausgibst. Glaube nichts, nimm nichts an! Gerade bei
Kommunikatino kann alles mögliche schief gehen. Und solange du Symptome
nicht deuten kannst, bist du extrem gut beraten, wenn du von der
Verarbeitungskette
Eingabe - Verarbeitung - Ausgabe
auch den Schritt "Eingabe" in Zweifel ziehst. Solange du nicht
nachweisen kannst, dass dein µC auch tatsächlich deine Eingabe so
kriegt, wie du dir das vorstellst, solltest du davon ausgehen, dass er
das nicht tut. Also ist Kontrolle angesagt. Und Kontrolle bedeutet, dass
der µC Ausgaben macht. Und je früher du diese Ausgaben in der
Verarbeitungskette hast, desto besser kannst du Fehler bereits im Ansatz
erkennen.
> c sharp:
Und ich wiederhole auch gerne nochmal den anderen wirklich guten Rat:
Mach deine ersten Schritte mit einem Terminalprogramm und sende händisch
das was du 'zu sagen' hast zum µC. Solange der µC nicht auf deine
Handeingaben im Terminal sauber reagiert, hat es keinen Sinn die
Vorhänge zuzuziehen, indem man auf dem PC ein Programm laufen hat, bei
dem man nicht sieht, was es denn nun wirklich auf der Leitung ausgibt.
Du kannst natürlich diese Ratschläge gerne auch weiterhin ignorieren.
Dann hampelst du halt noch 2 Wochen rum und bringst nichts weiter. Du
kannst aber auch akzeptieren, dass der schnellere Weg manchmal ein
vermeintlicher Umweg ist.
Jörg Wunsch schrieb:>> if (verb=='s')>> {>> uart_gets(text,25);>> Das wiederum macht man nun wirklich nicht mehr in einer ISR.
Besonders spannend finde ich die Mischung aus Interrupt und Polling an
dieser Stelle. Ein sicherer Weg ins Desaster.
OK.
Einen Hinweis geb ich dir noch:
Du wirst eine Funktion brauchen, die dir sagt, ob ein Zeichen an der
UART eingetroffen ist. Die Funktion brauchst du, damit du in der
Hauptschleife in main() entscheiden kannst, ob die UART überhaupt
Aufmerksamkeit benötigt oder nicht. Denn dein uart_getc() ist ja ein
wartendes getc, es wartet bis auf der UART etwas eintrifft.
Wenn also dieses uart_getc()
1
uint8_tuart_getc(void)
2
{
3
while(!(UCSR0A&(1<<RXC0)))// warten bis Zeichen verfuegbar
4
;
5
returnUDRE0;// Zeichen aus UDR an Aufrufer zurueckgeben
6
}
eine wartende Funktion ist, wie sieht dann eine Funktion
1
uint8_tuart_hasc()
2
{
3
....
4
}
aus, die darüber Auskunft geben soll, ob an der UART überhaupt ein
Zeichen vorliegt?
Diese Funktion wirst du dann so benutzen
1
intmain()
2
{
3
....
4
5
while(1)
6
{
7
if(uart_hasc()){// Hoppla, da will wer was von uns
8
9
c=uart_getc();
10
oder
11
text=uart_gets();
12
oder
13
.....
14
}
...
1
uart_puts(dtostrf(stunden,1,0,string));//Senden an USART (VERSUCH)
dtostrf? Bist du des Wahsinns fette Beute?
Wozu den Umweg über float? Beschäftigungstherapie für den µC?
ich lasse doch bei c# nochmal über die Zeile
help = serialPort1.ReadTo("\n");
lass ich mir zeigen was er vom Mikrocontroller hier reinschreibt
aktuelle Zeit: Stunden : Minuten
das bekomme ich hin das er mir da die Stunden richtig anzeigt und auch
die Minuten.
habe schon geschaut über hterm was passiert habe ihm dort die Zeichen
vorgegeben dann hat er die Zeichen ausgegeben so wie ich es mir wünsche.
dann habe ich mich wie ich es geschieben habe an den Controller über c#
die Zeichen gesendet und mit der help zum schluss nochmal ausgelesen.
was kann jetzt noch sein?
VON THRON schrieb:> Frag mich was das Problem ist das ganze über einen Interupt auszulösen!?
meinst du jetzt generell oder im speziellen?
Generell ist es kein Problem.
Im Speziellen ist es das Problem, dass du die dazu notwendige
Programmiertechnik nicht beherrscht.
Ich frag mich nämlich, warum du nicht schon längst dein Problem mittels
Polling (also in der Hauptschleife abfragen) gelöst hast. Ich seh jetzt
in deinem Programm nichts, was dem im Wege stehen würde. (Ausser dem
Interrupt/Polling Mischmasch der erst mal bereinigt werden müsste)
Se Sk. schrieb:> Hast du eigentlich eine Möglichkeit zum Debuggen des µC? Mit welchem µC> arbeitest du denn überhaupt?
ich arbeite mit dem µC von Atmel dem Atmega 644.
so ich habe meinen Fehler! habe nicht dir richtige reinfolge beachtet
hab den interrupt früher ausgelöst und hätte das zum schluss machen
sollen bevor ich in die Main gehe und siehe da es geht!
Trotzdem danke nochmal.