PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART geht mit AT90S2313 und nicht mit ATtiny 2313?!?



TobiasBlome
03.11.2006, 19:04
Hallo,
ich wollte ein paar Variablen über com anzeigen. Weil das nicht funktionierte habe ich mich rangetastet:

Dieses Testprogramm läuft mit einem AT90S2313 und läuft nicht auf einem ATtiny 2313. Das bedeutet die Hardware ist in Ordnung! Ich habe es mit 3 ganz neuen unbenutzten ATtiny´s versucht und bin gescheitert #-o

Warum läuft es nicht?

P.S. ich habe natürlich $regfile = "2313def.dat" und $regfile = "ATtiny2313.dat" jedes mal geändert - also daran liegt es nicht.

Tobias


'$regfile = "2313def.dat" 'AT90S2313-Deklaration
$regfile = "ATtiny2313.dat" 'ATtiny2313-Deklaration
$crystal = 20000000 '20MHz
$baud = 9600 'Baudrate der UART: 9600 Baud

Dim I As Word

Do

Print "Hallo AVR: " ; I

Incr I
Wait 1


Loop
End

linux_80
03.11.2006, 19:18
Hallo,

Ich habe es mit 3 ganz neuen unbenutzten ATtiny´s versucht und bin gescheitert #-o

Dazu fällt einem doch ein, sind die Fuses auf externen Takt eingestellt, und läuft der mit 20MHz ?

TobiasBlome
03.11.2006, 19:21
hmm?

Also ich habe einen 20MHz Quarz eingestellt und auch angeschlossen.
Aber welche Fuses? Wo muss man die einstellen?

TobiasBlome
03.11.2006, 19:24
Würde es denn nicht beide µC betreffen und nicht nur den ATtiny?

linux_80
03.11.2006, 19:32
Beim 90S gabs keinen internen Takt, deshalb wird immer der externe verwendet.
Beim Tiny muss man das einstellen, standardmässig läuft der mit 1MHz, Du könntest mal probieren bei deinen Einstellungen auf 1MHz zu gehen, dann müsste es zumindest mit der UART-übertragung klappen.

Auf dieser Seite kommt unten vor wie man Fuses einstellen kann:
https://www.roboternetz.de/wissen/index.php/Bascom_-_Erstes_Programm_in_den_AVR_Controller_%C3%BCbertr agen
aber Vorsicht !

TobiasBlome
03.11.2006, 19:39
Aha, das leuchtet mir ein. Habe leider gerade keinen 1MHz Quarz da. Aber warum vorsicht? kann man da etwas kaputt machen?

Tobias

linux_80
03.11.2006, 19:47
Du brauchst keinen 1MHz Quarz, weil der schon eingebaut ist !

und ja, man kann (mehr oder weniger) etwas kaputtmachen,
wenn Du die Fusebits falsch einstellst, kommst Du nimmer auf den AVR um ihn zu flashen !
Dazu gibts auch eine Seite irgendwo im Wiki wie das ganau geht, welcher Wert usw.
das wäre u.a. hier:
https://www.roboternetz.de/wissen/index.php/AVR-Einstieg_leicht_gemacht#Grundschaltung_mit_Quarz
Das Beispiel ist zwar für einen Mega32, dürfte aber so ziemlich dasselbe sein bei diesem Tiny.

TobiasBlome
03.11.2006, 20:00
Also nun bekomme ich schon mal ein paar zeichen gesendet...
Aber da passt etwas noch nicht so ganz...

€xÿxøxøxÿøx8ðxðx€€x€€ø€€xÿ€xø€xÿxøxøxÿøx8ðxðx€€ x€€ø€xÿ€xø€xÿxøxøxÿøx8ðxðx€€
x€€x€xÿ€xø€xÿxøxøxÿøx8àxðx€€xÿ€€€ø€xÿ€xø€xÿxøx øxÿøx8ðxðx€€x€€øø€xÿ€xø€xÿxø
xøxÿøx8ðxðx€€x€€€xÿ€xø€xÿxøxøxÿøx8ðxðx€€xÿ€€xð €xÿ€xø€xÿxøxøxÿøx8àxðx€€xÿ€
€x€xÿ€xø€xÿxøxøxÿøx8ðxðx€€x€€€€€xÿ€xø€xÿxøxøxÿøx 8ðxðx€€x€€ø€€xÿ€xø€xÿxøxøxÿø
x8ðxðx€€x€€ø€xÿ€xø€xÿxøx

linux_80
03.11.2006, 20:06
Hier kommt dazu, das mit 1MHz die 9600Baud nicht ganz getroffen werden können, Du kannst es mal mit 4800 probieren.

Bei 20MHz schauts auch wieder besser aus mit den 9600.

TobiasBlome
03.11.2006, 20:13
Also in dem Fenster mit den Lock und Fuse bits Stand unter Fusebit A987:
0100:Internal RC Oszillator 8MHz

so

und das habe ich umgestellt auf:
1111:1111 external XTAL

es gibt aber noch 1110:1110 external XTAL aber wo ist der Unterschied?

TobiasBlome
03.11.2006, 20:21
Und nun hab´ ich den ersten zerschossen... :-(

bei jedem programmieren kommt nun ein Fenster mit FFFFFFFFFFF
und eine zweites Fenster mit

>READLB entry not found<

Kann mir einer sagen was ich da einstellen muss?

TobiasBlome
03.11.2006, 20:23
Was muss ich den machen um den internen takt zu benutzen?

Ist der Interne für ales oder kann man auch den Quarz für das Programm und den internen NUR für UART nehmen?

Wen man den internen benutzen will, lässt man dann die Zeile $crystal = 20000000 einfach weg?

coCo
03.11.2006, 20:24
11111111 dürfte eigentlich stimmen. Ist dein Quarz richtig angeschlossen?

Und zerschossen würde ich nicht sagen, du kannst ihn ganz einfach widerbeleben (falls du wirklich etwas falsches eingestellt hast) indem du einen Quarzoszillator an XTAL1 anschließt.

MfG

coCo
03.11.2006, 20:25
Du musst das bei den Fusebits eingestellt haben, dass du den internen verwendest. Aber der ist glaub ich net so genau wie ein externer...
Korrigiert mich wenn ich Müll laber :D

Dirk
03.11.2006, 20:28
Hallo TobiasBlome,

das müßte für einen 20 MHz Quarz klappen:
Fusebit C -> 1:Divide clock by 8 disabled
Fusebit A987 -> 1111:1111

Damit läuft der Tiny dann mit 20 MHz.

Wenn er mit 8 MHz intern laufen soll (also kein externer Quarz), läßt du A987 wie es war (intern RC) und stellst nur C um, wie oben!

Gruß Dirk

TobiasBlome
03.11.2006, 20:37
Wunderbar es geht;-))))

Ich hatte FuseBit C nicht umgestellt!
Davon steht aber auch nix in der Anleitung auf der Webside :roll:

__________

mit dem zerschießen: ich hatte den auf 1000:1000 external RC osc eingestellt. kann ich denwieder hin bekommen?

coCo
03.11.2006, 20:40
Hi,
ich würde mal annehmen "osc" steht für Oscilator. Du musst dann einfach einen Quarzoszilator an XTAL1 anschließen. Dann kannst du wieder auf deinen AVR zugreifen und die Fuses richtig einstellen.

MfG

TobiasBlome
03.11.2006, 20:41
Wann muss ich die Fusebits setzen? nach jedem Programm übertragen oder reicht es einmalig solange ich nichts ändere, also Quarzfrequenz...?

Kann ich das auch irgendwo in da Programm reinschreiben oder geht das nur einzelnt über das programmierfenster?

Tobias

Dirk
03.11.2006, 20:44
RC osc heisst: Widerstands-Kondensator-Oszillator, ist nicht gleich Quarz-Oszillator (XTAL).

Die Fuses muss man nur 1x einstellen.

Gruß Dirk

TobiasBlome
03.11.2006, 20:51
Danke!
Abend ist gerettet :D

TobiasBlome
04.11.2006, 15:00
Noch ne Frage:

Mein Programm läuft nicht mehr richtig (alle Zeiten verstellt) Kann es sein ich vorher den externen quarz gar nicht benutzt habe?!

Wenn ja, kann ich UART auch mit dem Internen Taktgenerator nutzen? wie?

Tobias

TobiasBlome
04.11.2006, 15:54
](*,) Oh mann ich bin ja so blind:

Das hat ja Dirk gestern Abend noch geschrieben :oops:
Tobias

Dirk
04.11.2006, 16:03
Hallo Tobias,


Mein Programm läuft nicht mehr richtig (alle Zeiten verstellt) Kann es sein ich vorher den externen quarz gar nicht benutzt habe?!

Zur Klarheit:
1. Ein neuer tiny2313 hat einen INTERNEN 8 MHz RC-Oszillator und teilt den internen Takt durch 8 (Fusebit C = 0). Damit läuft ein neuer tiny mit [highlight=red:7f5d28b9cc]1 MHz[/highlight:7f5d28b9cc] und das muss dann auch im Programm mit $crystal = 1000000 angegeben werden.

2. Setzt du NUR Fusebit C auf 1, wird der Teiler : 8 inaktiviert und du hast einen internen (RC-Oszillator-) Takt von 8 MHz ($crystal = 8000000).

3. Willst du auf einen externen Quarz (XTAL) umstellen, hast du primär 3 Möglichkeiten für A987:
1111:1111 von 8 MHz bis 20 MHz
1111:1110 von 3 MHz bis 8 MHz
1111:1101 von 0,9 bis 3 MHz

Zu deinen Fragen:
Beim neuen tiny2313 nutzt du immer zuerst den internen Takt, wie unter 1. beschrieben.
Erst durch Manipulationen an A987 kannst du auf externe Taktquelle oder Quarz/RC-Oszillator umstellen.
Was bei dir jetzt Sache ist, hängt von deinen Fuses ab. Poste doch 'mal hier die aktuelle Einstellung. Diese Einstellung muss dann zu der $crystal Anweisung passen.

Gruß Dirk

TobiasBlome
04.11.2006, 16:37
Also mal ganz langsam für mich:

Ich habe ein Programm geschrieben und bin avon ausgegangen, das ich mit dem externen 20MHz Quarz arbeite. Da ich aber die Werte nicht errechnet sondern nach Empfinden eingestellt habe (z.b. Geschwindigkeit Übeblendeffekt) weiß ich nun naürlich nicht was ich eigendlich eingestellt habe...

Also hier das falsche Programm, welches aber funktioniert! Nur leider keine UART hat:


'-------------------------------------------------------------------------------
' Modellbauschalter 4/8Kanal mit ATtiny2313 und hardware PWM
'-------------------------------------------------------------------------------
'Beschreibung:

'4Steuerkanäle von Fernsteuerung auf 8 µC - Ausgänge
'Das Hi-Signal vom Empfänger wird mit "Pulsein" ermittelt!
'Knüppelstellung mitte hat ca. 121 Zeiteinheiten bei einem 3.6864 MHz Quarz!
'guter Schaltbereich für:
'oben einschalten ca.: 140 -> bei 8 MHz int. = 9 -> bei 20 MHz = 200
'unten einschalten ca.: 100 -> bei 8 MHz int. = 6 -> bei 20 MHz = 100
'Der mit "Pulsein" gemessene Wert wird in Pulsbreite1-4 ausgegeben.
'Kanal1-3u/o wird zum speichern benutzt, damit damit nicht bei jedem Durchlauf
'über "toggle" geschaltet wird, sondern erst wieder,
'wenn der Knüppel vorher in Nullstellung gewesen ist!
'"toggle" schaltet den Ausgang von Hi auf Low und wieder zurück!
'Der PNP Transistor BD 238 schaltet bei einem LOW Signal 5V auf die LED
'Nicht angeschlossene Kanäle müssen auf einen angeschlossenen Kanal gebrückt
'werden, damit der Eingang nicht abgefragt wird - da kein Signal kommt wartet
'das Programm, bis ein ERROR nach ca.650ms kommt!

'Wenn beide Funktionen von Kanal 2 geschaltet haben wird die
'Unterbodenbeleuchtung im wechsel über PWM gesteuert!


'FUSE BITs SETZEN!!!!!!
'Wenn er mit 8 MHz intern laufen soll (also kein externer Quarz):
'Fusebit A987 wie es war (0100:intern RC 8MHz)
'Fusebit C -> 1:Divide clock by 8 disabled


'-------------------------------------------------------------------------------
'Konfiguration µC:
$regfile = "ATtiny2313.dat" 'ATtiny2313-Deklarationen
$crystal = 20000000 'interne Frequenz bei ATtiny2313
$baud = 9600 'Baudrate der UART: 9600 Baud

'-------------------------------------------------------------------------------
'Ein- Ausgänge:
Ddrd = &B1000011 '1 Ausgang, 0 Eingang = Pin PD6,1+0 als Ausgang / PD5-2 als Eingang
Ddrb = &B11111111 '1 Ausgang, 0 Eingang = Pin PB7-0 als Ausgang
Portb = &B11111111 'PB0...PB7 auf High setzen

'-------------------------------------------------------------------------------
'Variablen auswertung FB
Dim Pulsbreite1 As Word 'Knüppelstellung Knüppel 1 '
Dim Pulsbreite2 As Word
Dim Pulsbreite3 As Word
Dim Pulsbreite4 As Word

Dim Kanal1o As Bit 'Speicher von Knüppel 1 OBEN
Dim Kanal1u As Bit 'Speicher von Knüppel 1 UNTEN
Dim Kanal2o As Bit
Dim Kanal2u As Bit
Dim Kanal3o As Bit
Dim Kanal3u As Bit

Dim Led1 As Byte
Dim Led1m As Byte 'LED1 Merker
Dim Led2 As Byte
Dim Led2m As Byte
Dim Led1pause As Word 'Als Pause zwischen den Lichteffekten für die UnterBodenbel.

Dim Portb3 As Bit 'PWM
Dim Portb4 As Bit 'PWM


'-------------------------------------------------------------------------------
'Konfiguration Timer:
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1
Config Timer0 = Timer , Prescale = 256 'Teiler
Enable Timer0 'timer einschalten
On Timer0 Ledcount 'Unteprogramm aufrufen
Enable Interrupts 'interrupts einschalten


'-------------------------------------------------------------------------------
' HAUPTPROGRAMM
'-------------------------------------------------------------------------------
Led1 = 255 'PWM Startwert vorgeben
Led2 = 1 'PWM Startwert vorgeben


Do 'Do Loop Schleife

'Print "U-Boden toggle: " ; Portb3
'Print "U-Boden toggle: " ; Portb4
'Print "Led1: " ; Led1
'Print "Led2: " ; Led2


'Hardware PWM mit Timer1 U N D
'FB auswerten: Umschaltung von normal auf PWM

If Portb3 = 0 And Portb4 = 0 Then

Compare1a = Led1 '=PB3 / max 255
Compare1b = Led2 '=PB4 / max 255

Else
If Portb3 = 0 Then
Compare1a = 255
Else
Compare1a = 0
End If

If Portb4 = 0 Then
Compare1b = 255
Else
Compare1b = 0
End If

End If




'FB auswerten:
'Umschaltung von normal auf PWM


'Kanal 1 LICHT HINTEN:
'____________________

Pulsein Pulsbreite1 , Pind , 5 , 1 'Pulsbreite auslesen (1=High Impuls)
'Knüppel rastend OBEN
If Pulsbreite1 > 9 And Kanal1o = 0 Then 'wenn Knüppel oben und Kanal1oben=0 dann
Toggle Portb.1 'Pin 1 mal schalten (entweder auf Hi oder Low je nach vorherigem zustand)
Kanal1o = 1 'Variable Kanal1o setzen damit nicht neu getoggled werden kann
End If
If Pulsbreite1 < 9 Then 'Wenn Knüppel nicht oben dann
Kanal1o = 0 'Variable Kanal1o RÜCKsetzen damit neu getoggled werden kann
End If
'Knüppel rastend UNTEN
If Pulsbreite1 < 6 And Kanal1u = 0 Then
Toggle Portb.0
Kanal1u = 1
End If
If Pulsbreite1 > 6 Then
Kanal1u = 0
End If



'Kanal 2 UNTERBODEN:
'___________________

Pulsein Pulsbreite2 , Pind , 4 , 1 'Pulsbreite auslesen (1=High Impuls)
'Knüppel rastend OBEN
If Pulsbreite2 > 9 And Kanal2o = 0 Then
Toggle Portb3
Kanal2o = 1
End If
If Pulsbreite2 < 9 Then
Kanal2o = 0
End If
'Knüppel rastend UNTEN
If Pulsbreite2 < 6 And Kanal2u = 0 Then
Toggle Portb4 'ACHTUNG PB4!!! nicht PB2!!!
Kanal2u = 1
End If
If Pulsbreite2 > 6 Then
Kanal2u = 0
End If



'Kanal 3:
'________

Pulsein Pulsbreite3 , Pind , 3 , 1 'Pulsbreite auslesen (1=High Impuls)
'Knüppel rastend OBEN
If Pulsbreite3 > 9 And Kanal3o = 0 Then
Toggle Portb.5
Kanal3o = 1
End If
If Pulsbreite3 < 9 Then
Kanal3o = 0
End If
'Knüppel rastend UNTEN
If Pulsbreite3 < 6 And Kanal3u = 0 Then
Toggle Portb.2 'ACHTUNG PB2!!! nicht PB4!!!
Kanal3u = 1
End If
If Pulsbreite3 > 6 Then
Kanal3u = 0
End If



'Kanal 4 (Taster / Taster):
'________

Pulsein Pulsbreite4 , Pind , 2 , 1 'Pulsbreite auslesen (1=High Impuls)
'Knüppel tastend OBEN
If Pulsbreite4 > 9 Then 'Knüppel oben
Portb. 7 = 0 'Port PB 7 setzen
Else 'sonst
Portb. 7 = 1 'Port PB 7 zurücksetzen
End If
'Knüppel tastend UNTEN
If Pulsbreite4 < 6 Then 'Knüppel unten
Portb. 6 = 0 'Port PB 6 setzen
Else 'sonst
Portb. 6 = 1 'Port PB 6 zurücksetzen
End If



'Automatikfunktion für Scheinwerfer: GEPRÜFT MIT HARDWARE OK
'___________________________________

If Portb.0 = 0 Or Portb.1 = 0 Then 'Wenn PB0 oder PB1 Hi sind dann
Portd.6 = 0 ' PD6 setzen
Else 'sonst
Portd.6 = 1 'PD6 RÜCKsetzen
End If

Loop



'Unterprogramme:
'_______________

Ledcount: 'Farbwechsel über Timer1

Timer0 = 150 'LED´s wechseln die Farbe mit ca 2 Hz


'While Led1pause < 1000 'wenn Led1Pause < 100 dann Schleife bearbeiten
'Incr Led1pause
'Print "Led1Pause: " ; Led1pause

'---LED1---
If Led1 = 255 Then 'Wenn Led1 100% dann Merker zum hochzählen setzen
Led1m = 0
End If

If Led1 = 0 Then 'Wenn Led1 0% dann Merker zum runterzählen setzen
Led1m = 1
End If

'Zähler1 hoch/runter
If Led1m = 1 Then
Incr Led1 'Wenn Merker Led1m = 1 -> um 1 hochzählen
End If

If Led1m = 0 Then
Decr Led1 'um 1 runterzählen
End If


'---LED2---
If Led2 = 255 Then
Led2m = 0
End If

If Led2 = 0 Then
Led2m = 1
End If

'Zähler1 hoch/runter
If Led2m = 1 Then
Incr Led2 'um 1 hochzählen
End If

If Led2m = 0 Then
Decr Led2 'um 1 runterzählen
End If



'Wend


'If Led1pause = 100 Then
'Led1pause = 0
'End If

Return

'================================================= ===============================
'Pinbelegung µC
'================================================= ==============================
' AtmelATtiny2313
'PD0 = Frei +---U---+
'PD1 = ResetTaster (Reset) PA2 +1 20+ Vcc +5V
'PD2 = Kanal 4 FREI ->PD0 +2 19+ PB7 Zusatzfunktion 3 tastend
'PD3 = Kanal 3 FREI ->PD1 +3 18+ PB6 Hupe / tastend
'PD4 = Kanal 2 x x Xtal 2 / PA1 +4 17+ PB5 Zusatzfunktion 2 rastend
'PD5 = Kanal 1 x x Xtal 1 / PA0 +5 16+ PB4 Licht Boden 2 / rastend (OC1B)PWM
'PD6 = Licht vorne Kanal 4->PD2 +6 15+ PB3 Licht Boden 1 / rastend (OC1A)PWM
'PB0 = Licht hinten 1 Kanal 3->PD3 +7 14+ PB2 Zusatzfunktion 1 rastend (OC0A)PWM
'PB1 = Licht hinten 2 Kanal 2->PD4 +8 13+ PB1 Licht hinten 2 / rastend
'PB2 = Licht Boden 1 Kanal 1->PD5 +9 12+ PB0 Licht hinten 1 / rastend
'PB3 = Licht Boden 2 GND +10 11+ PD6 Licht vorne
'PB4 = Zusatzfunktion 1 +-------+
'PB5 = Zusatzfunktion 2
'PB6 = Hupe
'PB7 = Zusatzfunktion 3

Da ich noch nichts von den Fuse Bits wuste habe ich die auch nicht verstellt ;-)

Fusebits habe ich so(also unverändert):

http://www.putfile.com/pic.php?img=3894932

Tobias

TobiasBlome
04.11.2006, 16:48
schön wäre es natürlich alles umzurechnen - aber einfacher wäre es vielleicht nur die UART zum laufen zu bekommen, wenn es denn eine passende Baudrate gibt...

Tobias

Dirk
04.11.2006, 16:50
Hallo Tobias,

die Fuses auf dem Bild sind die primäre Einstellung des tiny.
Damit hat er einen Takt von 1 MHz ($crystal = 1000000). Es ist ganz egal, ob ein Quarz angeschlossen ist: Er wird nicht benutzt!

Du müsstest das $crystal im Prog ändern.

Frage: Welche Frequenz hättest du denn gern für deinen tiny?

Gruß Dirk

Dirk
04.11.2006, 16:54
Da warst du wieder schneller als ich!

Wenn dein $crystal-Eintrag zur realen Taktfrequenz des tiny passt, dann kannst du auch den UART nutzen. Rechnen must du da gar nichts.

Aber: Nicht jede Taktfrequenz passt zu jeder Baudrate.

Gruß Dirk

TobiasBlome
04.11.2006, 17:02
Also Kurzfassung:

Du sagst mit diesen Fuseeinstellungen hat der Tiny 1MHz.
Eingestellt habe ich aber $crystal 20MHz

ABER:
Wenn ich nun von 20 auf 1 MHz ändere läuft das Programm nicht mehr. Was soll ich denn nun machen? Weil UART mit $Baud 9600 funktioniert nicht - warum?

Tobias

Dirk
04.11.2006, 19:24
Hallo Tobias,

sieh dir 'mal diese Tabelle an:
http://www.kreatives-chaos.com/artikel/baudraten-tabelle-fuer-avrs

Da gibt es Baudraten, die nicht zur Taktfrequenz passen.
Bei 20 MHz könnte 9600 Baud aber noch klappen.

Aber: Bei deinen 1 MHz geht 9600 Baud mit -7% Fehler nicht!

Was bleibt: Wenn du 9600 Baud brauchst:
Auf 20 MHz extern XTAL umstellen.
Oder einen "krummen" Quarz, z.B 18,432 MHz, nehmen.

Gruß Dirk

TobiasBlome
04.11.2006, 21:16
Die Tabelle ist sehr gut, auch für andere Projekte. Aber ich habe noch das Problem, das ich nicht weis, mit welcher Frequenz der µC arbeitet, weil ich mit dem internen Taktgeber arbeite, der auf 1 MHz eingestellt ist, aber im Programm sind 20Mhz eingestellt. Das Programm läuft sehr gut mit diese "unbekannten" Frequenz nur kann ich so die UART nicht einstellen, weil ich die Frequenz nicht weis.... Kann ich die Frequenz irgendwie messen? Also z.b. Prog. löschen und einen Pin setzen und rücksetzen und das die Frequenz am Pin messen? Dann müsste am pin doch die µC Frequenz sein oder?

Tobias

linux_80
04.11.2006, 22:25
Wenn Du an den Fuses nix gemacht hast, läuft der mit 1MHz.

Den AVR interessiert es überhaupt nicht, was Du in deinem Programm bei $crystal hinschreibst, das ist nur für Bascom intern um die Zeiten auszurechnen, wenn zB. Wartezeiten für Waitms usw. berechnet werden.
Also das bei Waitms 100 auch 100ms gewartet werden und nicht irgendwas anderes, was bei Dir jetzt anscheinend passiert ist, weil der Wert mit der echten MHz nicht zusammengepasst hat !

TobiasBlome
05.11.2006, 14:57
Ach so. Ich habe jetzt die Fuse Bits und $Crystal auf 20MHz geändert(externen Quarz angeschlossen) und die Werte für z.B. "Pulsein" angepasst.

Aber nun möchte ich noch eine Wartezeit im Unterprogramm "Ledcount:" einbauen.

Wenn die Variable Led1 = 255 oder Led1 = 0 dann soll er ca 1 sekunde warten. Wie kann ich das am einfachseten realisieren? Ich habe es mit einer Loop Schleife versucht, damit der Rest vom Programm weiter läuft - aber leider komme ich aus dieser Loopschleife nicht mehr raus weil sich dann der Wert von Led1 nicht mehr ändert...
Wie kann ich das ändern?


Ledcount: 'Farbwechsel über Timer0

Timer0 = 1 'Geschwindigkeit mit der die LED´s die Farbe wechseln



If Led1 = 255 Then

Do
Print "Led1Pause: " ; Led1pause
Incr Led1pause 'Erhöhe Variable Led1pause Um 1
Loop Until Led1pause = 100 'Wenn Led1pause = 100 , verlasse Schleife

Else

'---LED1---
If Led1 = 255 Then 'Wenn Led1 100% dann Merker zum hochzählen setzen
Led1m = 0
End If


If Led1 = 0 Then 'Wenn Led1 0% dann Merker zum runterzählen setzen
Led1m = 1
End If

'Zähler1 hoch/runter
If Led1m = 1 Then
Incr Led1 'Wenn Merker Led1m = 1 -> um 1 hochzählen
End If

If Led1m = 0 Then
Decr Led1 'um 1 runterzählen
End If


'---LED2---
If Led2 = 255 Then
Led2m = 0
End If

If Led2 = 0 Then
Led2m = 1
End If

'Zähler1 hoch/runter
If Led2m = 1 Then
Incr Led2 'um 1 hochzählen
End If

If Led2m = 0 Then
Decr Led2 'um 1 runterzählen
End If


End If




If Led1pause = 100 Then
Led1pause = 0
End If

Return

coCo
05.11.2006, 15:01
Du kannst einfach Wait bzw. Waitms und einen Wert dahinter verwenden. Zum Beispiel:
Wait 1 'Warte 1 Sekunde
Waitms 10 'Warte 10 Millisekunden

Dabei bleibt das ganze Programm stehen.

MfG

TobiasBlome
05.11.2006, 15:09
Ja, hab´s probiert.
Aber dann funktioniert ja der ganze Rest für eine Sekunde nicht mehr - also auch wenn ich ene Taster drücke wird der nicht mehr abgefragt...

Gibt es da noch eine andere Möglichkeit?


Ledcount: 'Farbwechsel über Timer0

Timer0 = 1 'Geschwindigkeit mit der die LED´s die Farbe wechseln



'---LED1---
If Led1 = 255 Then 'Wenn Led1 100% dann Merker zum hochzählen setzen
Led1m = 0
Wait 1
End If


If Led1 = 0 Then 'Wenn Led1 0% dann Merker zum runterzählen setzen
Led1m = 1
Wait 1
End If

'Zähler1 hoch/runter
If Led1m = 1 Then
Incr Led1 'Wenn Merker Led1m = 1 -> um 1 hochzählen
End If

If Led1m = 0 Then
Decr Led1 'um 1 runterzählen
End If


'---LED2---
If Led2 = 255 Then
Led2m = 0
End If

If Led2 = 0 Then
Led2m = 1
End If

'Zähler1 hoch/runter
If Led2m = 1 Then
Incr Led2 'um 1 hochzählen
End If

If Led2m = 0 Then
Decr Led2 'um 1 runterzählen
End If





Return

TobiasBlome
10.11.2006, 10:29
Hat denn keiner eine Idee, wie ich das mit einer Schleife realisieren kann, so dass der µC nicht für 1! Sekunde lamgelegt ist?

Dirk
10.11.2006, 18:22
Hallo Tobias,

dein Unterprog Ledcount: ist ja eigentlich eine ISR, also eine Interruptroutine. Da drin darfst du sowieso keine Pause einbauen, weil - wie du auch gesagt hast - ja dann alles blockiert wird.
Eine ISR sollte so schnell wie möglich ablaufen, damit das Hauptprogramm nicht unterbrochen wird.

Die Logik wäre also Folgende:
In der ISR erzeugst du nur einen "Takt" (z.B. als Zähler, der hochgezählt wird oder als Flag, das immer in der ISR 1 wird und im Hauptprogramm wieder gelöscht wird,- da gibt es mehrere Möglichkeiten.)
Das eigentliche Ein-/Ausschalten von LEDs o.ä. geschieht im Hauptprogramm, aber getriggert von dem Takt der ISR.
Wenn deine ISR z.B. einen Takt von 10 Hz (10x / Sek.) vorgibt, dann kann im Hauptprogramm z.B. bei jedem 10. Takt eine LED ein- oder ausgeschaltet werden, ...

Also: Programm umstricken wird empfohlen. O:)

Gruß Dirk

TobiasBlome
10.11.2006, 19:43
Danke für die Antwort,
also wenn ich in der ISR nur hoch und runterzählen soll, bleibt ja nur noch die Auswertung ob hoch oder runter gezählt werden soll über. (Also das setzten oder Rücksetzen von Variable "Led1m" und "Led2m") Das würde meinen µC etwas beschleunigen.

Aber das löst ja noch nicht das Problem mit der Wartezeit oder hab ich da etwas überlesen?


Eigendlich müsste ich doch nur eine weitere Variable setzen/rücksetzen?
'Zähler1 hoch/runter
If Led1m = 1 AND LED1PAUSE = 0 Then
Incr Led1 'Wenn Merker Led1m = 1 -> um 1 hochzählen
End If

würde das reichen?

Dann fehlt noch das setzen/rücksetzen von LED1PAUSE? Wie könnte man das machen - mit einer Loopschleife?

If Led1 = 255 Then
Led1Pause = 1

do
INCR Warten1
loop Until Warten1 = 100

Led1Pause = 0
End if


Tobias

Dirk
10.11.2006, 20:43
Hallo Tobias,

wie gesagt: In der ISR am besten keine Warteschleife, sondern ich würde den ganzen Ablauf in das Hauptprogramm nehmen. Da kann man immer Pausen einfügen, wenn nötig.
Eine Timer-ISR sollte nur regelmäßige, genau definierte kurze Aktionen durchführen, die unabhängig vom Hauptprogramm eintreten müssen.

Gruß Dirk

TobiasBlome
11.11.2006, 09:24
Also ich habe nun diese Warteschleife in das Hauptprogramm geschrieben:

'Warteschleife für 100% BLAU und 100% ROT

If Led1 = 250 Or Led1 = 0 Then
Led1Pause = 1
Incr Warten1
End If

If Warten1 = 20 Then
Led1pause = 0
Warten1 = 0
End If

Funktioniert super!

Tobias

P.S. nun ist das Program fertig


'-------------------------------------------------------------------------------
' Modellbauschalter 4/8Kanal mit ATtiny2313 und hardware PWM
'-------------------------------------------------------------------------------
'Beschreibung:

'4Steuerkanäle von Fernsteuerung auf 8 µC - Ausgänge
'Das Hi-Signal vom Empfänger wird mit "Pulsein" ermittelt!
'Knüppelstellung mitte hat ca. 121 Zeiteinheiten bei einem 3.6864 MHz Quarz!
'guter Schaltbereich für:
'oben einschalten ca.: 140 -> bei 8 MHz int. = 9 -> bei 20 MHz = 200 -> bei 1 MHz = 100
'unten einschalten ca.: 100 -> bei 8 MHz int. = 6 -> bei 20 MHz = 100 -> bei 1 MHz = 50
'Der mit "Pulsein" gemessene Wert wird in Pulsbreite1-4 ausgegeben.
'Kanal1-3u/o wird zum speichern benutzt, damit damit nicht bei jedem Durchlauf
'über "toggle" geschaltet wird, sondern erst wieder,
'wenn der Knüppel vorher in Nullstellung gewesen ist!
'"toggle" schaltet den Ausgang von Hi auf Low und wieder zurück!
'Der PNP Transistor BD 238 schaltet bei einem LOW Signal 5V auf die LED
'Nicht angeschlossene Kanäle müssen auf einen angeschlossenen Kanal gebrückt
'werden, damit der Eingang nicht abgefragt wird - da kein Signal kommt wartet
'das Programm, bis ein ERROR nach ca.650ms kommt!

'Wenn beide Funktionen von Kanal 2 geschaltet haben wird die
'Unterbodenbeleuchtung im wechsel über PWM gesteuert!


'FUSE BITs SETZEN!!!!!!
'Wenn er mit 8 MHz intern laufen soll (also kein externer Quarz):
'Fusebit A987 wie es war (0100:intern RC 8MHz)
'Fusebit C -> 1:Divide clock by 8 disabled
'1. Ein neuer tiny2313 hat einen INTERNEN 8 MHz RC-Oszillator und teilt den internen Takt durch 8 (Fusebit C = 0). Damit läuft ein neuer tiny mit 1 MHz und das muss dann auch im Programm mit $crystal = 1000000 angegeben werden.

'2. Setzt du NUR Fusebit C auf 1, wird der Teiler : 8 deaktiviert und du hast einen internen (RC-Oszillator-) Takt von 8 MHz ($crystal = 8000000).

'3. Willst du auf einen externen Quarz (XTAL) umstellen, hast du primär 3 Möglichkeiten für A987:
'1111:1111 von 8 MHz bis 20 MHz
'1111:1110 von 3 MHz bis 8 MHz
'1111:1101 von 0,9 bis 3 MHz

'Zu deinen Fragen:
'Beim neuen tiny2313 nutzt du immer zuerst den internen Takt, wie unter 1. beschrieben.
'Erst durch Manipulationen an A987 kannst du auf externe Taktquelle oder Quarz/RC-Oszillator umstellen.

'-------------------------------------------------------------------------------
'Konfiguration µC:
$regfile = "ATtiny2313.dat" 'ATtiny2313-Deklarationen
$crystal = 20000000 'externer Quarz 20MHz
$baud = 9600 'Baudrate der UART: 9600 Baud

'-------------------------------------------------------------------------------
'Ein- Ausgänge:
Ddrd = &B1000011 '1 Ausgang, 0 Eingang = Pin PD6,1+0 als Ausgang / PD5-2 als Eingang
Ddrb = &B11111111 '1 Ausgang, 0 Eingang = Pin PB7-0 als Ausgang
Portb = &B11111111 'PB0...PB7 auf High setzen

'-------------------------------------------------------------------------------
'Variablen auswertung FB
Dim Pulsbreite1 As Word 'Knüppelstellung Knüppel 1 '
Dim Pulsbreite2 As Word
Dim Pulsbreite3 As Word
Dim Pulsbreite4 As Word

Dim Kanal1o As Bit 'Speicher von Knüppel 1 OBEN
Dim Kanal1u As Bit 'Speicher von Knüppel 1 UNTEN
Dim Kanal2o As Bit
Dim Kanal2u As Bit
Dim Kanal3o As Bit
Dim Kanal3u As Bit

Dim Led1 As Byte
Dim Led1m As Bit 'LED1 Merker
Dim Led2 As Byte
Dim Led2m As Bit
Dim Led1pause As Word 'Als Pause zwischen den Lichteffekten für die UnterBodenbel.
Dim Warten1 As Word

Dim Portb3 As Bit 'PWM
Dim Portb4 As Bit 'PWM


'-------------------------------------------------------------------------------
'Konfiguration Timer:
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1
Config Timer0 = Timer , Prescale = 1024 'Teiler
Enable Timer0 'timer einschalten
On Timer0 Ledcount 'Unteprogramm aufrufen
Enable Interrupts 'interrupts einschalten


'-------------------------------------------------------------------------------
' HAUPTPROGRAMM
'-------------------------------------------------------------------------------
Led1 = 255 'PWM Startwert vorgeben
Led2 = 0 'PWM Startwert vorgeben


Do 'Do Loop Schleife
'Print "Pulsbreite2: " ; Pulsbreite2
'Print "U-Boden toggle: " ; Portb3
'Print "U-Boden toggle: " ; Portb4
'Print "Led1blau: " ; Led1
'Print "Led2rot: " ; Led2
'Print "Led1pause: " ; Led1pause
'Print "Warten1: " ; Warten1

'Hardware PWM mit Timer1 U N D
'FB auswerten: Umschaltung von normal auf PWM

If Portb3 = 0 And Portb4 = 0 Then

Compare1a = Led1 '=PB3 / max 255
Compare1b = Led2 '=PB4 / max 255

Else
If Portb3 = 0 Then
Compare1a = 255
Else
Compare1a = 0
End If

If Portb4 = 0 Then
Compare1b = 255
Else
Compare1b = 0
End If

End If

'Warteschleife für 100% BLAU und 100% ROT

If Led1 = 250 Or Led1 = 0 Then
Led1Pause = 1
Incr Warten1
End If

If Warten1 = 20 Then
Led1pause = 0
Warten1 = 0
End If




'FB auswerten:

'Kanal 1 LICHT HINTEN:
'____________________

Pulsein Pulsbreite1 , Pind , 5 , 1 'Pulsbreite auslesen (1=High Impuls)
'Knüppel rastend OBEN
If Pulsbreite1 > 200 And Kanal1o = 0 Then 'wenn Knüppel oben und Kanal1oben=0 dann
Toggle Portb.1 'Pin 1 mal schalten (entweder auf Hi oder Low je nach vorherigem zustand)
Kanal1o = 1 'Variable Kanal1o setzen damit nicht neu getoggled werden kann
End If
If Pulsbreite1 < 200 Then 'Wenn Knüppel nicht oben dann
Kanal1o = 0 'Variable Kanal1o RÜCKsetzen damit neu getoggled werden kann
End If
'Knüppel rastend UNTEN
If Pulsbreite1 < 100 And Kanal1u = 0 Then
Toggle Portb.0
Kanal1u = 1
End If
If Pulsbreite1 > 100 Then
Kanal1u = 0
End If



'Kanal 2 UNTERBODEN:
'___________________

Pulsein Pulsbreite2 , Pind , 4 , 1 'Pulsbreite auslesen (1=High Impuls)
'Knüppel rastend OBEN
If Pulsbreite2 > 200 And Kanal2o = 0 Then
Toggle Portb3
Kanal2o = 1
End If
If Pulsbreite2 < 200 Then
Kanal2o = 0
End If
'Knüppel rastend UNTEN
If Pulsbreite2 < 100 And Kanal2u = 0 Then
Toggle Portb4 'ACHTUNG PB4!!! nicht PB2!!!
Kanal2u = 1
End If
If Pulsbreite2 > 100 Then
Kanal2u = 0
End If



'Kanal 3:
'________

Pulsein Pulsbreite3 , Pind , 3 , 1 'Pulsbreite auslesen (1=High Impuls)
'Knüppel rastend OBEN
If Pulsbreite3 > 200 And Kanal3o = 0 Then
Toggle Portb.5
Kanal3o = 1
End If
If Pulsbreite3 < 200 Then
Kanal3o = 0
End If
'Knüppel rastend UNTEN
If Pulsbreite3 < 100 And Kanal3u = 0 Then
Toggle Portb.2 'ACHTUNG PB2!!! nicht PB4!!!
Kanal3u = 1
End If
If Pulsbreite3 > 100 Then
Kanal3u = 0
End If



'Kanal 4 (Taster / Taster):
'________

Pulsein Pulsbreite4 , Pind , 2 , 1 'Pulsbreite auslesen (1=High Impuls)
'Knüppel tastend OBEN
If Pulsbreite4 > 200 Then 'Knüppel oben
Portb. 7 = 0 'Port PB 7 setzen
Else 'sonst
Portb. 7 = 1 'Port PB 7 zurücksetzen
End If
'Knüppel tastend UNTEN
If Pulsbreite4 < 100 Then 'Knüppel unten
Portb. 6 = 0 'Port PB 6 setzen
Else 'sonst
Portb. 6 = 1 'Port PB 6 zurücksetzen
End If



'Automatikfunktion für Scheinwerfer: GEPRÜFT MIT HARDWARE OK
'___________________________________

If Portb.0 = 0 Or Portb.1 = 0 Then 'Wenn PB0 oder PB1 Hi sind dann
Portd.6 = 0 ' PD6 setzen
Else 'sonst
Portd.6 = 1 'PD6 RÜCKsetzen
End If

Loop



'Unterprogramme:
'_______________

Ledcount: 'Farbwechsel über Timer0

Timer0 = 1 'Geschwindigkeit mit der die LED´s die Farbe wechseln

'Zähler für PWM vor oder zurücklaufenlassen ( Led1m & Led2m )

'---LED1---
If Led1 = 255 Then 'Wenn Led1 100% dann Merker zum hochzählen setzen
Led1m = 0
End If


If Led1 = 0 Then 'Wenn Led1 0% dann Merker zum runterzählen setzen
Led1m = 1
End If

'Zähler1 hoch/runter
If Led1m = 1 And Led1pause = 0 Then
Incr Led1 'Wenn Merker Led1m = 1 -> um 1 hochzählen
End If

If Led1m = 0 and Led1Pause = 0 Then
Decr Led1 'um 1 runterzählen
End If


'---LED2---
If Led2 = 255 Then
Led2m = 0
End If

If Led2 = 0 Then
Led2m = 1
End If

'Zähler1 hoch/runter
If Led2m = 1 and Led1Pause = 0 Then
Incr Led2 'um 1 hochzählen
End If

If Led2m = 0 and Led1Pause = 0 Then
Decr Led2 'um 1 runterzählen
End If





Return

'================================================= ===============================
'Pinbelegung µC
'================================================= ==============================
' AtmelATtiny2313
'PD0 = Frei +---U---+
'PD1 = ResetTaster (Reset) PA2 +1 20+ Vcc +5V
'PD2 = Kanal 4 FREI ->PD0 +2 19+ PB7 Zusatzfunktion 3 tastend
'PD3 = Kanal 3 FREI ->PD1 +3 18+ PB6 Hupe / tastend
'PD4 = Kanal 2 x x Xtal 2 / PA1 +4 17+ PB5 Zusatzfunktion 2 rastend
'PD5 = Kanal 1 x x Xtal 1 / PA0 +5 16+ PB4 Licht Boden 2 / rastend (OC1B)PWM
'PD6 = Licht vorne Kanal 4->PD2 +6 15+ PB3 Licht Boden 1 / rastend (OC1A)PWM
'PB0 = Licht hinten 1 Kanal 3->PD3 +7 14+ PB2 Zusatzfunktion 1 rastend (OC0A)PWM
'PB1 = Licht hinten 2 Kanal 2->PD4 +8 13+ PB1 Licht hinten 2 / rastend
'PB2 = Licht Boden 1 Kanal 1->PD5 +9 12+ PB0 Licht hinten 1 / rastend
'PB3 = Licht Boden 2 GND +10 11+ PD6 Licht vorne
'PB4 = Zusatzfunktion 1 +-------+
'PB5 = Zusatzfunktion 2
'PB6 = Hupe
'PB7 = Zusatzfunktion 3