PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Fusing blockiert Avr !!!!!



samba971
03.09.2005, 02:06
Hallo Leute habe ein probleme,
wenn ich fusing benutze dann hängt mein AVR Mega 16 nach einigen sekunden.
kann mir jemand weiterhelfen?
Hier der Code in Bascom

Dim Tempd As Word
Dim Tempa As Single
Dim Tempround As Single
.
.
.
.

Onadc:
Waitms 500
Cls
Tempd = Getadc(1)
Tempa = Tempd - 94
Tempa = Tempa * 0.05
Locate 1 , 1
Lcd "temp digit = " ; Tempd
Lowerline
Lcd "Pression = " ; Getadc(1)
Locate 4 , 1
Print Tempa
Lcd Fusing(tempa , "###.&&")

Return

Danke

Marco78
03.09.2005, 05:53
Kommen dann auf dem LCD wirre Zeichen oder wie macht sich das bemerkbar das der AVR hängt?

samba971
07.09.2005, 02:36
Nein die Anzeige bleibt einfach hängen.
Habe inzwischen einen test ohne Interupt onADC gemacht da klappt es.
Liegt das am Interupt ???
Kann einer das vieleicht auf seinem Mc nachvollziehen ????
Danke für die Hilfe

PicNick
07.09.2005, 06:26
2 mal Getadc innerhalb einer ISR sind suboptimal. du mußt den wert einmal holen und zwischenspeichern für die darstellung

eine waitms 500 gleich vorn in der ISR ist auch nicht üblich.

samba971
08.09.2005, 02:30
Danke
Werde das mal ändern.
Aber warum funst das nicht mit fusing.
Denn wenn ich fusing nicht benutze läuft alles prima.

gerwin

hrei
08.09.2005, 03:31
Aber warum funst das nicht mit fusing.
Denn wenn ich fusing nicht benutze läuft alles prima.
gerwin
Single und dann noch in Verbindung mit Fusing braucht einfach viel Zeit. Erschwerend kommt hinzu, daß Du, wie von Picknick erwänhnt, noch ein recht abenteuerliches Wait in der ISR hast. Der Takt"mehrverbrauch" durch Fusing ist da der berühmte Tropfen, der das Faß zum überlaufen bringt.

Warum ist denn nun das Wait so überflüssig?
Nun, der Interupt wird ja erst dann ausgelöst, wenn die Wandlung fertig ist. Ein vorsorgliches Warten ist also völlig unnötig.

Generell ist es sinnvoll, ISRs so knapp wie möglich zu halten. Die Ausgabe sollte z.B. im Hauptprogramm erfolgen, in der ISR könntest Du dann schlicht ein Word benutzen. Das Word wird dann, je nachdem was Dir besser gefällt , in eine Singlevariable oder einen String umgewandelt, den Du dann via Format ausgeben könntest.

Grüße
Henrik

samba971
08.09.2005, 22:18
Hallo Henrik

Danke für die Erklärung, jetzt ist alles klar wie Klossbrühe.
Habe alles umgeschrieben und jetzt klappt es auch mit meinem Mc.

Nochmals Danke an alle.

Gruss
Gerwin

samba971
09.09.2005, 02:10
Habe aber jetzt ein neues problem....
Wenn ich dieses im Simulateur laufen lasse ist alles ok.
Doch auf dem Mc wenn ich eine Spannungsänderung am pin pa2
habe ändern sich beide Werte im terminal (resultpress + resulttemp)
am pin pao (ADC0) kann ich ändern wie ich will keine änderung am terminal ????????????????????
Habe ich ein probleme mit dem ISR
Kann ich nur einen Chanel zur zeit auslesen ???
Hier der Code

$regfile = "m16def.dat"
$crystal = 8000000
$baud = 9600

'$sim
Config Lcd = 20 * 4
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2
Config Lcdmode = Port
Config Adc = Single , Prescaler = Auto , Reference = Avcc

On Adc Adc_isr Nosave
Enable Adc
Enable Interrupts

Dim Dval_1 As Word
Dim Dval_2 As Word
Dim Resulttemp As Single
Dim Resultpress As Single

Declare Sub Calcultemp(resulttemp As Single , Dval_1 As Word)
Declare Sub Calculpress(resultpress As Single , Dval_2 As Word)

Do
Cls
Start Adc
Idle
Stop Adc
Call Calcultemp(resulttemp , Dval_1)
'print uart valeur
Print "11 " ; Fusing(resulttemp , "##.# ")
Locate 1 , 1
Lcd "Temperature =" ; Fusing(resulttemp , "##.# ")
Call Calculpress(resultpress , Dval_2)
Print "22 " ; Fusing(resultpress , "##.#")
Locate 2 , 1
Lcd " Pression =" ; Fusing(resultpress , "##.#")
Waitms 500
Loop

End

Adc_isr:
Dval_1 = Getadc(0)
Dval_2 = Getadc(2)
Return

Sub Calcultemp(resulttemp As Single , Dval_1 As Word)
Resulttemp = Dval_1 - 141
Resulttemp = Resulttemp * 0.16
End Sub

Sub Calculpress(resultpress As Single , Dval_2 As Word)
Dim X As Single
X = 4000 / 1023
Resultpress = Dval_2 * X
End Sub[/code]

Gruss Gerwin

PicNick
09.09.2005, 08:20
Ich nehm an, daß dir die Sache mit den Interrupts noch nicht in allen Details klar ist.
Der Ablauf beim adc-lesen ist folgender (schematisch):
1 Einstellen der Kanalnummer
2 Start der Messung
3 Warten auf Fertigwerden
4 Lesen des Ergebnisses

Durch den Interrupt kann Punkt 3 entfallen, den die ISR-Routine wird genau nach Fertigwerden der Messung automatisch aufgerufen.

So, wie dein Programm abläuft, kann ich dir nur raten, das Ganze Interrupt-Zeugs zu knicken. Denn ob du "idle" sagst oder gleich direkt auf das Ready-Bit wartest, ist zeitmäßig Jacke wie Hose, aber wesentlich leichter zu beherrschen.

Empfehlung:


Start Adc
Do
Cls

Dval_1 = Getadc(0)
Call Calcultemp(resulttemp , Dval_1) 'print uart valeur
Print "11 " ; Fusing(resulttemp , "##.# ")
Locate 1 , 1
Lcd "Temperature =" ; Fusing(resulttemp , "##.# ")

Dval_2 = Getadc(2)
Call Calculpress(resultpress , Dval_2)
Print "22 " ; Fusing(resultpress , "##.#")
Locate 2 , 1
Lcd " Pression =" ; Fusing(resultpress , "##.#")
Waitms 500
Loop

End

pebisoft
09.09.2005, 08:36
hallo hatte damals mal ein program geschrieben für den radencoder.
wollte die langsame getadc von bascom nicht nutzen. vielleicht kannst du ihn weiterverwenden. wenn du onadc nutzen tust, nimm am besten auch die direkten avr-ansprechregister.
mfg pebisoft


$regfile = "m16def.dat"
$crystal = 8000000
$baud = 19200

Dim Adhi As Byte
Dim Adlow As Byte
Dim Adcergebnis As Word
Dim Radzaehler As Byte
Dim Toggle_rad As Byte

Disable Interrupts
Adcsra.aden = 1
Adcsra.adate = 1
Adcsra.adie = 1
Adcsra.adsc = 1
Adcsra.adps0 = 1
Adcsra.adps1 = 1
Adcsra.adps2 = 1
Admux.refs0 = 1
Enable Interrupts

Radzaehler = 0
Toggle_rad = 0

On Adc Onadc

Do

Waitms 1
Print Radzaehler

Loop

Onadc:
Admux.mux0 = 1 !! ist adcport pina1 , ohne mux ist pina0
Adcsra.adsc = 1 !! startet das auslesen
Adlow = Adcl
Adhi = Adch
Adcergebnis = Adhi * 256
Adcergebnis = Adcergebnis + Adlow
If Adcergebnis > 400 And Toggle_rad = 1 Then
Incr Radzaehler
Toggle_rad = 0
End If
If Adcergebnis < 100 And Toggle_rad = 0 Then
Incr Radzaehler
Toggle_rad = 1
End If
Return

End

samba971
09.09.2005, 19:04
Ok...
Danke für eure Hilfe.
Aber .....jetzt weiss ich leider immer noch nicht, warum ich nicht während eines ADC Interupts beide Oder Alle Kanäle auslesen kann.
Oder habe ich nur den Wert von dem ADC der den Interupt ausgelöst hat??

.....

Gruss Gerwin

hrei
09.09.2005, 19:49
Hallo,


Ok...
Danke für eure Hilfe.
Aber .....jetzt weiss ich leider immer noch nicht, warum ich nicht während eines ADC Interupts beide Oder Alle Kanäle auslesen kann.
Oder habe ich nur den Wert von dem ADC der den Interupt ausgelöst hat??


Die AVRs haben nur einen ADC. Die Kanäle werden intern gemultiplext. Erfolgt der Interrupt, ist die gesamze Mimik fertig und alle Kanäle können ausgelesen werden. Du startest die Wandlung ja auch schlicht durch: Start ADC und nicht durch ADC(x).

Auch wenn das etwas oberlehrerhaft klingen mag (es ist nicht so gemeint):
Wirf einen Blick ins Datenblatt des µC, da wird dann vieles klarer.

Grüße
Henrik

PS: Picknick hat außerdem recht, in Deinem Fall sehe auch ich keine Notwendigkeit das auslesen des ADC im Interrupt vorzunehmen. Das kann sinnvoll sein, wenn man den ADC freilaufend arbeiten läßt und das letzte Quäntchen an Geschwindigkeit und damit Zeitauflösungsfaktor herausholen will.

samba971
10.09.2005, 00:15
Ok Danke für eure Hilfe..
jetzt wird einiges klar.......

Ich komm wieder.......
Spätestens beim nächsten Problem :lol:

Gruss
Gerwin