Guten leute,
Ich habe ein Fehler im Code komme aber nicht drauf habe schon gesucht
aber beim vergleichen ist mir kein Fehler aufgefallen, denke es liegt am
Interrupt vom ADC.
Kurz zum Code & Hardware, ATmega8L mit Ext. 4MHz Quarz und gebrannt wird
er mit stk500 auf einem Steckbrett.
Das Programm soll später in 2 Versionen laufen
1)Einmal den ADC wert lesen und am PC schicken.
z.B:
Spannung = 1.1V
2)Wenn PB0 auf masse ist, dauer haft messen und an PC schicken.
z.B:
Spannung = 1.1V
Spannung = 1.9V
Spannung = 2.1V usw.
Hoffe ist verständlich genug :)
Ob die Übertragung richtig ist, weis ich nicht da am terminal nichts an
kommt denke es liegt am ADC-Interrupt.
1
#ifndef F_CPU
2
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
> Danke für die Hilfe und Tipps.
* In einer ISR werden keine UART Ausgaben gemacht.
Die dauern viel zu lange
* Für den ADC brauchst du eigentlich überhaupt keinen Interrupt
Der macht das ganze System nur unnötig kompliziert.
* Ähm. Deine 'Interrupt-Steuerung', wozu soll die überhaupt gut sein?
* Für die ADC Funktionalität wären ein paar Funktionen angebracht,
damit du die Hauptschleife möglichst sauber und klein bekommst.
Das würde deiner Programmübersicht gut tun.
* Codeformatierung!
Nicht irgendwann, sondern jetzt!
* Anforderungen überprüfen!
> 1)Einmal den ADC wert lesen und am PC schicken.
Das ist keine sehr sinnvolle Anforderung. Was soll 'einmal' messen
bedeuten? Wie wird diese Einmalmessung angestossen.
Nach dem Anlegen der Versorgungsspannung soll der ADC einmal messen
ist normalerweise keine sinnvolle Anforderung. Das solltest du nochmal
überprüfen, ob das wirklich das ist, was du willst.
* Du willst dein Programm auf keinen Fall aus main() rauslassen. Selbst
wenn die Aufgabe darin besteht eine Einmalmessung zu machen, musst du
das Programm innerhalb mein() halten.
* Schmeiss dein Programm weg und schreib es neu.
Geht schneller, als da jetzt alles zurechtzurücken.
Aber schreib es diesmal vernünftig! Deine main() könnte so aussehen.
Das ist leicht zu überblicken und Fehler sind leichter zu sehen, als
wie wenn du da einen haufen Code unstrukturiert aufstapelst. Was
rauskommt, wenn du die Dinge unübersichtlich schreibst hast du ja
jetzt gesehen. Also mach es nicht.
Danke für die Tipps habe es geändert/neu geschrieben.
sieht auch übersichtlicher aus, habe aber probleme mit der sprintf().
in deinem Beispiel wird
sprintf( Buffer, "%d %.2f\n\r", adc_Value, Volt );
bekomme ich den richtigen decimal wert aber der float zeigt nur die
Vorkommastelle an und Nachkommastelle bleiben 00
999 2.00
999 2.00
999 2.00
sollte aber 2.63 sein.
Habe häufig an sprintf rum experimentiert kam aber oft nur misst bei
rum,
ich kam zu dem Ergebnis
sprintf( Buffer, "\n\rSpannung= %.2f V",Volt);
Spannung=2î
Spannung=2î
Spannung=2î
Spannung=1î
Spannung=1î
Spannung=1î
Spannung=0®
Spannung=0®
Spannung=0®
Spannung=0®
Den Buffer habe ich groß genug gewählt wunder mich warum er bei dem
String so ein murks darstellt(Ich weis der Programmierer macht Fehler,
nicht das Programm).
den bin ich auch im avr simulator durch gegangen und da läuft er. Es
werden zwar auch die Nachkommastellen als nullen dargestellt, aber läuft
nur einmal durch und stoppt. Die Realität sieht immer anders aus.
Habe die Baud Berechnung raus gelassen, ist noch die Selbe wie oben.
1
#include<avr/io.h>
2
#include<util/setbaud.h>
3
#include<avr/interrupt.h>
4
#include<stdlib.h>
5
#include<stdio.h>
6
7
volatileuint8_tFaktor=27;
8
volatileuint16_tTeiler=10240;
9
10
11
voidadc_init(void)
12
{
13
uint16_tresult;
14
/*Analog-Digital-Wandler-Init*/
15
ADMUX=(1<<REFS0);//ReferenzSpannung AVcc | Kanal 0 ADC0(PC0)
16
ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADPS2)|(1<<ADPS1);
17
//ADC enable| Singel Mode| Frequenzvorteiler F_CPU/64
18
19
ADCSRA|=(1<<ADSC);// eine Dummy-Wandlung
20
while(ADCSRA&(1<<ADSC)){}// auf Abschluss der Konvertierung warten
Danke für die hinweiße den zweiten link hatte ich schon gefunden danach
lief erst float mit Nachkommastellen, dern erstenlink wollte ich gerade
testen aber ich kann kein Projekt mehr builden, kommt die error
Hast du irgendwas beim Projekt verändert?
Der Error "avr-gcc: CreateProcess: No such file or directory" deutet
darauf hin das eine Datei fehlt.
Sonst einfach mal Fehlermeldungen Googeln, dass hilft meistens ;)!
www.google.at/search?q=avr-gcc%3A+CreateProcess%3A+No+such+file+or+direc
tory
Nah dem ich avr Studio neu installiert hatte lief es habe mir bei links
durch gelesen. das habe dann eingesetzt und eine neue Variable erstellt
des typs double mit 0.00263671 (Faktor/Teiler). Bekomme aber den
Übertragungsfehler wie oben? dann wird auch
sprintf( Buffer, "%d %.4f\n\r", adc_Value, Volt );
nicht richtig Übertragen es kommt dann,
3ð32 0.0844
3õ37 0.0976
3ù40 0.1055
4ò42 0.1107
4ó44 0.1160
4ô45 0.1187
Habe da noch eine Verständnis frage zu Strings
wenn ich "Hallo Welt" habe wird das doch so definiert
char Buffer[10] = "Hallo\n\r";
123456789+1 für \0
oder liege ich da falsch?
ok also char buffer [8] würde es dann heißen, denn ich habe mal mit dem
Buffer rum gespielt und gelesen (finde die Seite aber nicht) das wenn
ich
char buffer[2] = "hallo" würde dann Ha ausgeben.
Habe dann mal in den code Buffer [1]
sprintf( Buffer, "Spannung=%.2f V",Volt );
Eingeben was dann eigentlich zu einem S führt?
bekam aber trotzdem Spannung=2î
Spannung=1î
Spannung=1î
Spannung=1î
Marko schrieb:> ok also char buffer [8] würde es dann heißen,
lass doch den Compiler die Buchsataben zählen.
char Buffer[] = "Hallo\n\r";
> denn ich habe mal mit dem> Buffer rum gespielt und gelesen (finde die Seite aber nicht) das wenn> ich> char buffer[2] = "hallo" würde dann Ha ausgeben.
Nö. Das ist undefiniert. Alles mögliche kann passieren.
> Habe dann mal in den code Buffer [1]> sprintf( Buffer, "Spannung=%.2f V",Volt );> Eingeben was dann eigentlich zu einem S führt?
Zähl die Buchstaben. Wieviele brauchst du?
Hinweis: Es lohnt momentan noch nicht, da zu sparen!
Mach den Buffer 20 oder 30 Zeichen groß, so dass der Text auf jeden Fall
reinpasst. Zu groß ist (bis auf den Speicherverbrauch) kein Problem, zu
klein aber schon.
klar habe die buchstaben gezählt und komme auf 18+1 habe den buffer dann
auf 20 gestellt, aber egal was ich eingebe es kommt immer das selbe raus
ob 30, 25 oder 100.
Weiss langsam nicht mehr weiter, bin nochmal alles durch gegangen.
Die Ausgabe am terminal Passt nicht wird nicht richtig dargestellt.
Die Übertragung läuft auch dauerhaft, was eigentlich nicht seit sollte.
while(!(UCSRA&(1<<UDRE)))/* warten bis Senden moeglich */
37
{
38
}
39
40
UDR=c;/* sende Zeichen */
41
return0;
42
}
43
44
45
/* puts ist unabhaengig vom Controllertyp */
46
voiduart_puts(char*s)
47
{
48
while(*s)
49
{// so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)"
50
uart_putc(*s);
51
s++;
52
}
53
}
54
55
uint16_tADC_Read(uint8_tchannel)
56
{
57
58
59
// Kanal waehlen, ohne andere Bits zu beeinflußen
60
ADMUX=(ADMUX&~(0b00001111))|(channel&0b00001111);
61
ADCSRA|=(1<<ADSC);// eine Wandlung "single conversion"
62
while(ADCSRA&(1<<ADSC)){}// auf Abschluss der Konvertierung warten
63
64
returnADCW;// ADC auslesen und zurückgeben
65
}
66
67
voidPerformMeasurement()
68
{
69
uint8_tFaktor=27;
70
doubleTeiler=10240.00;
71
72
uint16_tadc_Value;
73
doubleVolt;
74
charBuffer[20];
75
76
77
adc_Value=ADC_Read(0);
78
Volt=((adc_Value*Faktor)/Teiler);
79
80
81
sprintf(Buffer,"\n\rSpannung= %.2f"Volt);
82
83
84
uart_puts(Buffer);
85
86
}
87
88
89
intmain()
90
{
91
92
adc_init();
93
uart_init();
94
95
DDRB&=(1<<PB0);// PB0 auf Eingang
96
PORTB|=(1<<PB0);// Pullup an PB0 einschalten
97
98
99
100
101
if(PINB&(1<<PB0)){
102
while(1)
103
PerformMeasurement();
104
}
105
106
else{
107
108
PerformMeasurement();
109
while(1)
110
;
111
}
112
113
114
115
return0;
116
117
}//Ende main
Hatte den code nicht eingefügt weil er sich nicht groß ändert.
hatte mit unterschiedlichen string funktionen experementiert (dtostrf
strcat usw.) kam aber immer zum selben prolem
Marko schrieb:> das war mein fehler beim kopieren und habe beim Korrigieren übersehen.
Welches Korrigieren?
Häng doch bitte dein File so an, wie du es compilierst!
Das ist wichtig. Denn mit diesem Fehler ist es unmöglich, dass du ein
HEX-File bekommst, welches du in den µC brennen kannst. D.h. du kannst
schon ein HEX-File brennen, nur entspricht das eben nicht dem, was du
jetzt programmiert hast.
Auf dieser Seite des Monitors kann ich nicht entscheiden, was da jetzt
Sache ist. Im Zweifelsfall gehe ich davon aus, dass der gezeigte Code
dann eben nicht der Code ist, der tatsächlich im µC läuft, womit deine
ganze Fehlerbeschreibung hinfällig ist.
Habe das ganze Projekt habe ich angehängt.
Und mit korrigieren meine ich, ich lese mir den post durch(LRS).
Ich kann den µC brennen, gehe den Code im AVR Simulator und da läuft die
UART-Übertragen nur einmal durch. Nur auf dem µC läuft er in einer dauer
schleife.
Da wird dann eben der Schalter nicht so schalten, wie du dir das
vorstellst.
Ist das ein Schalter oder ein Taster?
Wie ist er angeschlossen?
Annahme: Taster, und der schaltet sie wie es üblich ist, nach Masse
durch.
-> Dir ist klar, dass du noch vor dem Programmstart den Taster drücken
und gedrückt halten musst, bis die erste Messung da ist?
while(!(UCSRA&(1<<UDRE)))/* warten bis Senden moeglich */
5
{
6
}
was macht die Oder-Zuweisung an UCSRA da an dieser Stelle?
Damit hebelst du schon mal den Schutz gegen 'Überfahren' des UART aus,
was dein Problem erklären würde.
"\n\rSpannung= %.2f\0"
Du brauchst den String nicht mit \0 abschliessen. Das macht schon der
Compiler für dich. Jetzt hat dein String 2 Stück \0 Bytes am Ende :-)
Karl Heinz Buchegger schrieb:> was macht die Oder-Zuweisung an UCSRA da an dieser Stelle?> Damit hebelst du schon mal den Schutz gegen 'Überfahren' des UART aus,> was dein Problem erklären würde.
Wie das? Man kann UDRE nicht manuell setzen.
while(!(UCSRA&(1<<UDRE)))/* warten bis Senden moeglich */
5
{
6
}
7
8
UDR=c;/* sende Zeichen */
9
return0;
10
}
war eine kleine Hilfe für den Avr Simulator damit ich in I/O View nicht
immer
das bit setzten muss.
Ich gehe davon das die Taster auf masse sind (STK500), der µC ist auf
dem steckbrett aufgebaut.
Hi
>war eine kleine Hilfe für den Avr Simulator damit ich in I/O View nicht>immer das bit setzten muss.
Im wirlichen Leben wird UDRE so gelöscht .
MfG Spess
spess53 schrieb:> Hi>>>war eine kleine Hilfe für den Avr Simulator damit ich in I/O View nicht>>immer das bit setzten muss.>> Im wirlichen Leben wird UDRE so gelöscht .
Wobei man der Fairness halber sagen muss, dass das so von Atmel nicht
dokumentiert ist, da hat Stefan Ernst schon recht. (Und ich habs auch
erst jetzt nachgeschlagen).
D.h. keine Ahnung ob und wenn ja, was da wirklich passiert. Auf jeden
Fall aber gehört das da nicht hin.
Ich hatte mal alles aus der main gelöscht damit die
PerformMeasurement();
auch einaml durchlaufen wird aber, im terminal wird es immer als
schleife ausgegeben
Marko schrieb:> Die ADC interrupt erlauben hat doch nichts mit dem UART zu tuhen oder> sehe ich das falsch?
Ein erlaubter INterrupt, zusammen mit einem sei()
UND
einer nicht implementierten ISR
führt zu einem reset des µC.
(Da kommen dann auch deine scheinbaren Dauermessungen her)
Das wusste ich nicht, hatte es auch raus genommen weil ich es ja nicht
brauche.
Es Wird aber immer noch eine dauer übertragung durchgeführt.
kann es sein das es ander uart_puts() Liegen? weil es ja eine schleife
ist
1
intuart_putc(unsignedcharc)
2
{
3
4
while(!(UCSRA&(1<<UDRE)))/* warten bis Senden moeglich */
5
{
6
}
7
8
UDR=c;/* sende Zeichen */
9
return0;
10
}
11
12
13
/* puts ist unabhaengig vom Controllertyp */
14
voiduart_puts(char*s)
15
{
16
while(*s)
17
{// so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)"
Marko schrieb:> Es Wird aber immer noch eine dauer übertragung durchgeführt.> kann es sein das es ander uart_puts() Liegen? weil es ja eine schleife> ist
Nein
Ist der Text jetzt richtig?
OK.
Nur um sicher zu gehen:
Kannst du mal wo eine LED anschliessen?
Und dann dein Programm so umändern (ich hab jetzt mal eine LED an B-3
angenommen:
1
intmain()
2
{
3
DDRB|=(1<<PB3);// LED
4
5
PORTB|=(1<<PB3);
6
_delay_ms(500);
7
PORTB&=~(1<<PB3);
8
_delay_ms(500);
9
10
adc_init();
11
uart_init();
12
13
....
Die LED darf/muss einmal beim Programmstart kurz aufleuchten. Und danach
nie wieder. Wenn du sie danach wieder aufleuchten siehst, dann hast du
noch andere Dinge, die zum Reset führen.
Marko schrieb:> Ja das macht sie, Sie Flackert.> Das heist Irgend wo wird das Programm neu gestart?
genau.
Also alles noch mal durchsuchen, wo du einen Interrupt freigegeben hast,
für den du keine ISR hast.
(Oder du nimmst einfach mal alle sei() raus. Für einen kurzen Test ist
das ok. Ansonsten finde ich persönlich das unbefriedigend, wenn man
einen Fehler im Programm hat, den man im Grunde 'nur abschaltet' ohne zu
wissen, wo der Fehler liegt.)
Nein Das einzige was drin gewessen ist war avr/interrupt.h die habe ich
raus genommen ändert sich aber nichts.(um sicher zu sein habe ich den
avr studio nach folgenden sachen suchen lassen sei, cli, isr und sind
nicht im code vorhanden)
Mir ist aber noch was aufgefallen wenn ich die Delay änder die Frequenz
beleibt die selbe, was eigendlich nicht sein sollte.