Moin,
ich will die Werte von 3 Hall Sensoren gerne über UART ausgeben.
Allerdings nur dann, wenn sie sich auch ändern. Das mit dem Ausgeben
funktioniert soweit. Das mit dem ändern allerdings nicht. Dafür hatte
ich eine Variable sensorold angelegt, die dann mit den aktuellen
Sensorwerten verglichen wird. Leider wird sie immer wieder 0. In jedem
Schleifendurchlauf! Ich versteh leider nicht warum. Auch das
_delay_ms(500) wird scheinbar komplett ignoriert.
1
#include<avr/io.h>
2
#define F_CPU 20000000UL
3
#include<util/delay.h>
4
#define BAUD 9600L
5
#include<stdlib.h>
6
#include<string.h>
7
8
9
10
intuart_putc(unsignedcharcharacter)
11
{
12
while(!(UCSR0A&(1<<UDRE0))){}//warten bis Senden möglich
Martin W. schrieb:> Auch das _delay_ms(500) wird scheinbar komplett ignoriert.
Worauf begründest du den Schein? Schließ doch mal ein LED an einen Pin
an, der mit jedem Zyklus getoggelt wird...
BTW: der Watchdog ist ausgeschaltet?
Lothar M. schrieb:> Martin W. schrieb:>> Auch das _delay_ms(500) wird scheinbar komplett ignoriert.> Worauf begründest du den Schein? Schließ doch mal ein LED an einen Pin> an, der mit jedem Zyklus getoggelt wird...
Das leite ich daraus ab, das mir die Konsole innerhalb einer Sekunde
bereits völlig zugeballert wird. Daher weiß ich ja auch, das der Rest
funktioniert. Die ausgegebenen Sensorwerte sind richtig. Daher weiß ich
auch, dass sensorold am ende der Schleife auf keinen Fall mit 0
überschrieben wird. Trotzdem ist es beim Sprung in den Anfang der
Schleife wieder 0.(hab ich mir über uart ausgeben lassen)
>> BTW: der Watchdog ist ausgeschaltet?
Das klingt sehr spannend, aber wie finde ich das heraus? Die Fuse für
Watchdog ist nicht gesetzt. Und von Hand hab ich da auch nix
angeschaltet.
kommst du denn überhaupt in diesen Programmteil?
du nutzt strcat! ohne erstmalig sensor[] überhaupt zu initialisieren.
vermutlich sollte es mal NULL sein aber wer weiss?
Martin W. schrieb:> char sensor[200];
sollte besser char sensor[200]={0}; sein bevor es mit strcat weitergeht!
Martin W. schrieb:> völlig zugeballert wird
Was wird denn ausgegeben?
Beim ersten Scheifendurchlauf ist das char-Array "sensor"
uninitialisert, es sei denn, der Compiler initialisiert es automatisch
mit 0en.
jb schrieb:>>>fake schrieb:>>> Damit setzt Du doch bei jedem Schleifendurchlauf sensorold auf 0.>>>Nö.>> Wohle. Ganz sicher.>> Gruß J
Warum sollte das so sein ?
Zu beginn der Schleife wird meine Sensorspeicher (sensorbin) gelöscht.
Dann werden die Sensoren in den Speicher geschrieben. Dass das
funktioniert hat, weiß ich anhand der UART-Ausgabe. sensorbin ist also
nun nicht mehr 0. Anschließend wird doch erst sensorold = sensorbin;
ausgeführt.
Joachim B. schrieb:> kommst du denn überhaupt in diesen Programmteil?>> du nutzt strcat! ohne erstmalig sensor[] überhaupt zu initialisieren.>> vermutlich sollte es mal NULL sein aber wer weiss?>> Martin W. schrieb:>> char sensor[200];>> sollte besser char sensor[200]={0}; sein bevor es mit strcat weitergeht!
Hab ich geändert. Hilft nur leider nicht. Die Ausgabe bleibt die selbe,
also z.B.:
A1
B0
C1
Aushabe erfolgt geschätzt 10 mal pro Sekunde, oder öfter.
Martin W. schrieb:> Aushabe erfolgt geschätzt 10 mal pro Sekunde, oder öfter.
dann hast du ein viel größere Problem:
> _delay_ms(500);
dann sollte maximal 2mal in der sekunde etwas gesendet werden.
>> muss aus der main() heraus.
Warum ?
Peter II schrieb:> Martin W. schrieb:>> Aushabe erfolgt geschätzt 10 mal pro Sekunde, oder öfter.>> dann hast du ein viel größere Problem:>>> _delay_ms(500);>> dann sollte maximal 2mal in der sekunde etwas gesendet werden.
Ja davon sprach ich ja auch schon. Deswegen klang das mit dem Watchdog
ja auch so gut. Aber wenn der nicht per default an ist, kanns das nicht
sein.
Frickelfritze schrieb:> Wie war das doch nochmal?>> Lokale Variablen werden nicht automatisch initialisiert,> globale dagegen schon.>> betrifft:>
1
charsensor[200];
>> Eigentlich sollte der Compiler eine Warnung ausgeben ....
Es ist egal ob Global oder nicht initialisiert oder nicht. Fehler
bleiben leider immer die selben.
Joachim B. schrieb:> Martin W. schrieb:>> char sensor[200];>> sollte besser char sensor[200]={0}; sein bevor es mit strcat weitergeht!
Das ist suboptimal. Damit werden sämtliche 200 Speicherstellen von
sensor in einer Schleife genullt, obwohl das gar nicht notwendig ist.
Die erste Stelle reicht nämlich (wg. strcat):
BlaBla schrieb:
>
char sensor[200];
> uint8_t sensorold = 0;> uint8_t sensorbin = 0;>> muss aus der main() heraus.
Warum ?
Das ist so! Bei jedem Durchlauf der while-Schleife werden die Variablen
auf Null gesetzt. Mach daraus globale Variablen, dann werden die Inhalte
beibehalten.
Frank M. schrieb:> Das ist suboptimal. Damit werden sämtliche 200 Speicherstellen von> sensor in einer Schleife genullt,
stimmt, wer packt das auch in eine Schleife im Code, das gehört sich
anders!
Frank M. schrieb:> Die erste Stelle reicht nämlich (wg. strcat):char sensor[200];> sensor[0] = '\0';
auch das stimmt und ist effektiver wenn der sensor[] unbedingt im Code
in der while stehen bleiben soll!
BlaBla schrieb:> Das ist so! Bei jedem Durchlauf der while-Schleife werden die Variablen> auf Null gesetzt. Mach daraus globale Variablen, dann werden die Inhalte> beibehalten.
Das ist blanker Unsinn. Die Variablen werden ausserhalb der
while-Schleife definiert und auf Null gesetzt. Da main() auch nie
verlassen wird, bleiben sie auch als lokale Variablen die ganze Laufzeit
am Leben.
Sorry, aber Du scheinst wenig bis gar keine Ahnung von C zu haben. Ich
wäre vorsichtig mit solchen Vorschlägen.
BlaBla schrieb:> Das ist so! Bei jedem Durchlauf der while-Schleife werden die Variablen> auf Null gesetzt.
welche schleife meinst du? Die NACH der Initialisierung?
Joachim B. schrieb:> auch das stimmt und ist effektiver wenn der sensor[] unbedingt im Code> in der while stehen bleiben soll!
Die Definition von sensor[] steht gar nicht in der while-Schleife,
sondern darüber ;-)
Ausserdem ist eine lokale Variable hier sogar ressourcensparender:
Wenn Du sensor[200] nämlich global definierst, werden trotzdem wieder
200 Speicherstellen gelöscht, obwohl die erste komplett reicht.
Martin W. schrieb:> strcpy(sensor, "");// String leeren
1
sensor[0]='\0'
ist hier etwas eleganter. Man muss nicht unbedingt immer mit Funktionen
auf Variablen schießen - auch wenn sie in moderneren
C-Compiler-Umgebungen intern abgebildet werden.
Meine Antwort hat sich erledigt. Habe heute einen Knick in der Optik.
Die Variablen stehen an der richtigen Stelle. Auf die Polemik von Frank
M. werde ich nicht weiter eingehen.
Frank M. schrieb:> Die Definition von sensor[] steht gar nicht in der while-Schleife,> sondern darüber ;-)
ach was solls der ganze Code ist undurchsichtig!
Martin W. schrieb:> Ich versteh leider nicht warum. Auch das> _delay_ms(500) wird scheinbar komplett ignoriert.
wenn dem so ist dann resetet der Controller.
mach doch einfach vor der while in der main eine uart Ausgabe. Sagen wir
Ausgabe von "start".
Dann siehst Du auf jeden Fall ob ein Reset während des Programmablaufs
stattfindet.
Zurück zum Problem des TO:
- Sind Compiler-Warnings mit -Wall eingeschaltet?
- Ändert sich etwas, wenn du den delay-wert auf 5000 erhöhst?
- Poste mal den Build-Output und das .lss-File
BlaBla schrieb:> Noch eine Idee: liegt die richtige Spannung für 20 MHz an.
Spannung sind 4,91V
Werner P. schrieb:> Martin W. schrieb:>> Ich versteh leider nicht warum. Auch das>> _delay_ms(500) wird scheinbar komplett ignoriert.>> wenn dem so ist dann resetet der Controller.>> mach doch einfach vor der while in der main eine uart Ausgabe. Sagen wir> Ausgabe von "start".>> Dann siehst Du auf jeden Fall ob ein Reset während des Programmablaufs> stattfindet.
War ne gute Idee. Der Atmel scheint sich neu zu starten. Zumindest wird
das Start ständig geschrieben. Der neustart erfolgt alle 16 UART Zeichen
wenn ich mich nicht verzählt hab.
Aber woran kann das liegen ?
Martin W. schrieb:> Aber woran kann das liegen ?
Wenn der Code in deinem Eingangspost alles ist dann kann es eigentlich
nur noch ein Hardwarefehler sein.
Schaltplan?
Edit: Was passiert wenn Du in der while mal alles ausdokumentierst?
Noch eine Idee: AtmelStudio 7 zeigt mir die Variable "sensorbin" nicht
im Debugger mit der Compiler-Option -Os an. Die wird scheinbar hinfort
optimiert. Mit der folgenden Änderung wird sie wieder sichtbar.
Frank M. schrieb:>> sollte besser char sensor[200]={0}; sein bevor es mit strcat weitergeht!>> Damit werden sämtliche 200 Speicherstellen von> sensor in einer Schleife genullt, obwohl das gar nicht notwendig ist.
Komisch, mein Compiler initialisiert mit dieser Art
1
charsensor[200]={0};
genau ein Element von sensor[], und zwar das erste. So war
ich es bisher auch gewohnt.
Frank M. scheint einen neuartigen Compiler zu haben oder einen
der einen anderen Standard verfolgt ..... vielleicht M$?
CRätsel schrieb:> Frank M. scheint einen neuartigen Compiler zu haben
kann nicht sein, der Frank weiss es immer besser als ich.....
Ich glaube fast ich muss das wirklich auf meinem Compiler untersuchen
was da genau passiert obwohl es mir total schnurz ist ob
Joachim B. schrieb:> char sensor[200]={0};
200 Byte auf 0 setzt oder nur das erste Byte
aber da Frank mir wieder mal widersprach:
Frank M. schrieb:> Das ist suboptimal. Damit werden sämtliche 200 Speicherstellen von> sensor in einer Schleife genullt
interessiert es mich schon ob mit Recht oder nur weil er ein
Widerspruchsgeist ist.
CRätsel schrieb:> Komisch, mein Compiler initialisiert mit dieser Art> char sensor[200]={0};> genau ein Element von sensor[], und zwar das erste. So war> ich es bisher auch gewohnt.
dafür spricht:
http://www.tutorials.at/c/09-arrays-strings.html
Ein wichtiger Punkt bei lokal deklarierten Arrays ist deren
Initialisierung. Ein Beispiel:
int daten[3] = { 0, 0, 0 };
Hier wird das Array daten mit 3 Elementen vom Typ int deklariert und
zugleich definiert. Alle drei Elemente werden auf 0 gesetzt
(initialisiert). Die einzelnen Werte werden dabei der Reihe nach
zwischen geschwungenen Klammern { } angegeben.
int daten[] = { 4, 10, -20 };
Hier wurde die Anzahl der Elemente in eckigen Klammern weggelassen. Das
ist immer dann möglich, wenn ein Array gleich initialisiert wird. Denn
es geht für den Compiler aus der Initialisierungsliste ohnehin hervor,
wieviel Speicher und Elemente reserviert werden müssen.
Das erste Element (daten[0]) wird mit 4 initialisiert, das zweite
(daten[1]) mit 10 und das dritte (daten[2]) und zugleich letzte mit -20.
Werner P. schrieb:> Martin W. schrieb:>> Aber woran kann das liegen ?>> Wenn der Code in deinem Eingangspost alles ist dann kann es eigentlich> nur noch ein Hardwarefehler sein.>> Schaltplan?>> Edit: Was passiert wenn Du in der while mal alles ausdokumentierst?
Also ich hab alles im While auskommentiert. Ergebnis: Der Kontroller
startet permanent neu, statt in der while schleife zu verharren. :'(
Lass ich ihn etwas Ausgeben, schafft er vor dem Absturz etwa 16 Zeichen.
Am Reset Pin hab ich mal mit dem Oszi gemessen und konnte nix sehen was
einen Restart rechtfertigen würde.
Schaltplan hab ich mal angehängt. Ich denke aber mal nicht, dass ich da
etwas total verkackt habe.
Martin W. schrieb:> dass ich da etwas total verkackt habe.
Naja, total nicht aber bisschen schon.
Die Abblock-Cs an Vcc und Avcc fehlen. Was das in deinem Fall
ausmacht wage ich nicht zu beurteilen, aber gut ist das nicht.
Abblock-Cs müssen übrigens direkt am Controller sein.
Frickelfritze schrieb:> Abblock-Cs müssen übrigens direkt am Controller sein.
... und dürfen nicht weggelassen werden bloss weil am
Spannungsregler schon welche sitzen .....
Martin W. schrieb:> Leider stürzt er immer noch ab.
Aufbau zeigen ....
Die 27pF am Quarz kommen mir etwas hoch vor, könnte die
Betriebssicherheit beeinträchtigen. 18pF müssten reichen.
Ein 78L05 als Spannungsregler ..... ob der Strom ausreicht
um alles zu speisen .... ich weiss nicht was die IRS2184
an Strom ziehen ....
... und wieviel Oberspannung hast du auf der Primärseite
des Reglers?
Frickelfritze schrieb:> Martin W. schrieb:>> Leider stürzt er immer noch ab.>> Aufbau zeigen ....>> Die 27pF am Quarz kommen mir etwas hoch vor, könnte die> Betriebssicherheit beeinträchtigen. 18pF müssten reichen.>> Ein 78L05 als Spannungsregler ..... ob der Strom ausreicht> um alles zu speisen .... ich weiss nicht was die IRS2184> an Strom ziehen ....
Der 78L05 versorgt ausschließelich die MCU.
> ... und wieviel Oberspannung hast du auf der Primärseite> des Reglers?
12V. Die Frage hat das Problem gelöst. Von sowas hab ich noch nie
gehört, und es ist mir echt peinlich, das die Quasi 1.Frage jeder
Telefonhotline mein Problem löst. Auf die Frage hin, hab ich das
Netzteil einmal aus der Steckdose gezogen um nochmal auf die
Beschriftung zu gucken. 12V DC 800mA. Also eigentlich ok. Nach dem
wieder reinstecken ging alles.
Ist irgendwem sowas schon mal passiert ? Ich finde das sehr Skuril. Ich
dachte spätestens nach dem Programmieren und dem damit verbundenen Reset
müsste ein Absturz des Prozis behoben sein... aber offensichtlich war
das hier nicht der Fall.
Vielen Dank an alle die geholfen haben und die vielen Tipps nebenbei.
Der Thread ist damit gelöst.
Martin W. schrieb:> Der Thread ist damit gelöst.
Danke für die Rückmeldung!
Aber die Abblock-Cs baust du noch dazu! Sonst gibt's ein
schlechtes Gewissen und ......
Martin W. schrieb:> Also eigentlich ok. Nach dem wieder reinstecken ging alles.
Vielleicht wird es dem 78L05 doch etwas ungemütlich wenn er
7 Volt verarbeiten und xx mA liefern muss.
Frickelfritze schrieb:> Martin W. schrieb:>> Also eigentlich ok. Nach dem wieder reinstecken ging alles.>> Vielleicht wird es dem 78L05 doch etwas ungemütlich wenn er> 7 Volt verarbeiten und xx mA liefern muss.
Jup. Also gut anfassen kann man ihn nicht. Ich denke ich werde ihn
tatsächlich tauschen, zumal in der Endfassung 16,88V anliegen können
sollen.
Das sind dann 11,88V drop. Bei den erlaubten 100mA wären das dann schon
Rund 1,2 Watt. Andererseits darf das Ding laut Datenblatt 70°C heiß
werden.
Martin W. schrieb:> Andererseits darf das Ding laut Datenblatt 70°C heiß> werden.
Mit nicht vorhandenen Reserven sollte man nicht spekulieren.
Das nennt man Leben auf Pump.
Frickelfritze schrieb:>> dass ich da etwas total verkackt habe.>> Naja, total nicht aber bisschen schon.
L1 an AREF ist auch eher daneben, die würde eher an AVCC Sinn ergeben.
Wenn man die Versorgungsspannung als Referenz will setzt man einfach die
REFSn Bits in ADMUX passend.
CRätsel schrieb:> Komisch, mein Compiler initialisiert mit dieser Art> char sensor[200]={0};> genau ein Element von sensor[], und zwar das erste. So war> ich es bisher auch gewohnt.>> Frank M. scheint einen neuartigen Compiler zu haben oder einen> der einen anderen Standard verfolgt ..... vielleicht M$?
Der "neuartige" Compiler ist ein stinknormaler avr-gcc.
Testcode:
Joachim B. schrieb:> dafür spricht:>> http://www.tutorials.at/c/09-arrays-strings.html> Ein wichtiger Punkt bei lokal deklarierten Arrays ist deren> Initialisierung. Ein Beispiel:>> int daten[3] = { 0, 0, 0 };>> Hier wird das Array daten mit 3 Elementen vom Typ int deklariert und> zugleich definiert.
Ich muss Dir leider widersprechen: Das spricht überhaupt nicht dafür.
Das ist der normale Ansatz eines Tutorial-Schreibers, wenn er dem Leser
die Initialisierung beibringen will.
Der Autor dieses Tutorials kennt lediglich die folgende Regel nicht:
"Wenn eine Initialisierung angegeben wird und diese unvollständig(!)
ist, wird der Rest automatisch mit Nullen gefüllt".
Die wenigsten kennen diese, obwohl sie steinalt, also keine irgendwelche
komische "Neuerung" irgendeines Standards ist. Im Gegenteil: Das war
schon immer so.
Joachim B. schrieb:> machst du ja gerne,
:-)
> aber ich räume ein eine Fundstelle ist naturgemäß wenig aussagekräftig.
Was Du da zitiert hast, ist ja nicht falsch - höchstens unvollständig.
Der Autor hätte auf die zusätzliche Möglichkeit der
Komplettinitialisierung eines Array ruhig hinweisen können.
Bei
1
intdaten[2048]={0};
hätte er nämlich sonst eine ziemliche Schreibarbeit :-)
Joachim B. schrieb:> eine Fundstelle ist naturgemäß> wenig aussagekräftig.
Genügt dir K&R, The C Programming Language, Prentice Hall, Kapitel 4.9,
auf Seite 84?
Oder auch die Second Edition vom K&R-Klassiker, hier Seite 86:
"If there are fewer initializers for an array than the number specified,
the missing elements will be zero for external, static, and automatic
variables."
Also ist kein "neuartiger" Compiler dafür notwendig. Das war schon seit
Anbeginn von C so.
guest schrieb:> Frickelfritze schrieb:>>> dass ich da etwas total verkackt habe.>>>> Naja, total nicht aber bisschen schon.>> L1 an AREF ist auch eher daneben, die würde eher an AVCC Sinn ergeben.> Wenn man die Versorgungsspannung als Referenz will setzt man einfach die> REFSn Bits in ADMUX passend.
Du hast vollkommen recht, da hab ich kacke gebaut! Wird natürlich
korrigiert.
Georg G. schrieb:> Genügt dir K&R, The C Programming Language, Prentice Hall, Kapitel 4.9,> auf Seite 84?
habe ich nicht, aber das hier ist auch interessant!
QC hält sich nicht an die automatische Arraygröße wenn Werte vorgegeben
sind
Joachim B. schrieb:> QC hält sich nicht an die automatische Arraygröße wenn Werte vorgegeben> sind
Die früheren C-Compiler für Windows aus den 80ern haben jede Menge
falsch bzw. "anders" gemacht als das UNIX-Original. Wirf das QuickC-Buch
am besten wech oder verfeuere es im Kamin, aber verschenke es
keinesfalls. Der andere könnte darin lesen und einiges lernen, was
schlicht und einfach falsch ist. ;-)
Frank M. schrieb:> Die früheren C-Compiler für Windows
sorry das war DOS! (alles weisst du auch nicht gelle :)
und das M$ immer alles anders macht weiss man ja, wieso wurde
dennFAT16(!?) auf int 32k Cluster reglementiert? wenn es auch locker
uint 64k Cluster sein könnten? denn negative Cluster will ja keiner.
Ich muss noch mal nach meinem Sybex Buch suchen, nur das hier fiel mir
gerade beim Werkstattumzug in die Hände.
Georg G. schrieb:> Möchtest du eine Windows Version von QC haben? Mit LCC32 erzeugt.
habe sogar das Original, als QC für win und als VC für win aber leider
ziemlich unbrauchbar, die hatten sogar mit Kompatiblität geworben, war
aber nur geschönt, meinte Quellcode kompatibel, was für ein Witz, die HP
IEEE Libs konnte man nicht nutzen.