Hallo, ich möchte einen Rechteckgenerator mit dem Controller Atmega8 bauen. Es sollen Frequenzen von 1 Hz bis 1MHz ausgewählt werden. Die Menüsteuerung mit einlesen der Werte (Frequenzbereich, Tastverhältnis und Frequenz) funktioniert bereits. Ein Problem was ich habe ist die Gestalltung der Warteschleife für die Impulszeit und die Pausenzeit. In etwa habe ich mir das so vorgestellt: Bsp 1Hz und Tastverhältnis 50%: Do PORTB.0=1 warteschleife für Impuls (0,5s) PORTB.0=0 warteschleife für Pause (0,5s) Loop Mein Problem ist die Durchführung der Takte (z.B. 0,5s) Weil meine Prozessortaktung 3,686411Mhz beträgt müssen für 1s Wartezeit 3686411 Takte durchgeführt werden. Für 0,5s also 1823405,5 Takte (die Hälfte). Jetzt zu meinem Problem: i=0 Do i=i+1 Loop XX Wenn ich das jetzt richtig verstehe besteht diese Schleife aus 3 Takten also muss Sie 1823405,5/3=607802 mal Wiederhohlt werden. Ist das Richtig so? MfG Tmelle
Die Schleife besteht aus erheblich mehr als 3 Takten, schau Dir mal den generierten Assemblercode an. Da siehst Du genau, was passiert. Grob geschätzt: Mit einem Takt von 3MHz kannst Du 1MHz max. Frequenz vergessen (siehe oben).
Mit Atmegas hab ich keine Erfahrung aber nur mal so als Tip: Bei einem PIC ist der Systemtakt nur ein viertel des Oszilatortaktes, d.h.u.a. es müssen vier Ozilatortakte vergehen bis sich überhaupt ein Portpin ändern kann bzw. eine Änderung im PIC ankommt. Beim Atmega könnte ich mir vorstellen ist es ähnlich und dann wird es aber eng mit ca. 3 Mhz Oszilatortakt 1 Mhz Takt an den Pins zu generieren.
Hallo Tmelle, also ich kann dich beruhigen, der Atmega macht pro Oszilatortakt ein Prozessortakt. Allerdings kommen mir für ein 1MHz Rechtecksignal 3,6Mhz Prozessortakt recht wenig vor. Ich würde höher gehen und vor allem einen Timer inkl. Interrupt und Timercompareregister benutzen. Damit erfolgt das Pintoggeln automatisch und Du brauchst dich überhaupt nicht mehr um irgendwelche Warteschleifen zu kümmern. Im Hauptprogramm werden die Werte eingelesen und nur die entsprechenden Register des Timers gesetzt. Siehe auch: http://www.mikrocontroller.net/articles/AVR-Tutorial:_Timer Gruß, Steffen
Hallo, danke für eure Antworten, ich werde das Mal mit den Timern Probieren. Mein Problem ist, dass bei dem Generator das Tastverhältnis, also das Verhältnis Pausenzeit/Impulszeit einstellbar sein soll. Das Hauptprogramm ließt die gewünschte Frequenz und das Tastverhältnis ein. (bereits Fertig). Der Prozessortakt wird beim fertigen Gerät dann auf 16MHz erhöht. Zum Entwickeln werde ich erstmal einen Frequenzbereich von 1-100Hz benutzen. Es wäre nett wenn ihr mir helfen könntet.
Sry für Tripplepost aber der Timer funktioniert jetzt auch mit der Einstellung des Tastverhältnisses. Jetzt fehlt mir die Möglichkeit den Prescaler des Timers umzuändern bzw. zu senken, damit höhere Frequenzen möglich sind. Ich habe das wiefolgt versucht: Disable Reset Timer1 If Presc = 8 Then Config Timer1 = Timer , Prescale = 8 If Presc = 64 Then Config Timer1 = Timer , Prescale = 64 Das Funktioniert leider nicht weil (ich denke), der Compiler (in diesem Falle Bascom) sich die ganzen Configzeilen am Anfang raussucht und diese zuerst in hexcode umwandelt. Gibt es eine möglichkeit den Prescaler innerhalb des Programms zu ändern? MfG Tmelle
@ Tmelle (Gast) >Gibt es eine möglichkeit den Prescaler innerhalb des Programms zu >ändern? Sicher. Einfach das Register TCCR1B direkt beschreiben. Siehe Datenblatt. MFG Falk
Also ich habe das bei meinem ersten Projekt so gemacht, dass ich nen kleinen prescaler verwendet habe. Dann wird mit jedem Interrupt des Timers einfach ein Register Decrementiert. Ist ein bestimmter Wert erreicht, von mir aus EA, war meine Periode zu Ende und der Wert wurde wieder auf 00 gesetzt. Das gleiche Register habe ich benutzt um das Tastverhältnis einzustellen also wird z.b. bei FA einfach der Portpin invertiert und bei 00 noch einmal. Du brauchst quasi 3 Register: Zähler, Wert-Tastverhältniss und Wert-Frequenz. Ich gebe aber zu bedenken, dass diese Methode wohl nicht die effektivste ist, da du nur 255 stufen hast - man könnte ggf. 2 register zum Zählen nehmen. Das mit den die vergehen bis der Portpin invertiert wird Takten sollte sich aber ausgleichen, bzw. minimal sein vllt. 2 takte, da er immer die gleiche schleife fährt. Anfänger-Idee halt.
Hallo, eure Beträge haben mich schonmal weiter gebracht. Aber leider muss ich euch mit einem weiteren Problem nerven: Frequenzbereich 1: 1Hz-100Hz Prescaler=64 Frequenzbereich 2: 100Hz-1kHz Prescaler=8 Die Einstellung der Frequenz (F bzw 2f), des Tastverhältnisses (Tv) und des Prescalers (Presc) werden durch das Hauptprogramm eingelesen bzw. festgelegt (funktioniert so wie es soll). Der Frequenzbereich 1Hz-100Hz funktioniert auch so wie er soll (Toleranz ca 0.4 Hz) Nur der Frequenzbereich 100Hz - 1kHz Funktioniert nicht so wie er soll, die Werte für die Warteschleifen berechnen sich jedoch korekt. Ich weiss nicht woran das liegt, sitze hier jetzt schon 2 Std. und suche den Fehler. Ich hoffe ihr als erfahrenen Mikrocontroller-Programmierer/innen könnt mir auch hier weiterhelfen. Hier noch der Code des Programmteils welche für den Betrieb zuständig ist:
1 | Locate 1 , 14 'Anzeige "Betrieb" |
2 | Lcd "BET" |
3 | |
4 | |
5 | 2f = F 'Variablenumwandlung in Word |
6 | T = 36864.11 / Presc 'Prozessortakt/Vorteiler |
7 | T = T / 2f 'Warteimpulse pro Periode |
8 | |
9 | Impuls = T * Tv 'Warteimpulse pro Impuls (Tv=Tastverhältnis) |
10 | |
11 | Pause = 100 - Tv |
12 | |
13 | Pause = T * Pause 'Warteimpulse pro Pause |
14 | |
15 | |
16 | Config Timer1 = Timer 'Konfiguration Timer1 als Timer |
17 | |
18 | If Presc = 8 Then 'Prescaler für Frequenzbereiche einstellen |
19 | Tccr1b = 2 |
20 | Elseif Presc = 64 Then |
21 | Tccr1b = 3 |
22 | End If |
23 | |
24 | Waitms 500 |
25 | |
26 | Enable Timer1 'Start Timer1 |
27 | Do
|
28 | |
29 | |
30 | Portc.3 = 0 'Ausgang auf Low |
31 | Timer1 = 0 'Reset Timer1 |
32 | Do 'Warteschleige Pause |
33 | Loop Until Timer1 = Pause |
34 | |
35 | Portc.3 = 1 'Ausgang auf High |
36 | Timer1 = 0 'Reset Timer1 |
37 | Do 'Warteschleife Impuls |
38 | Loop Until Timer1 = Impuls |
39 | |
40 | |
41 | |
42 | |
43 | Loop Until Pinc.5 = 0 |
44 | |
45 | |
46 | Portc.3 = 0 |
47 | Disable Timer1 |
48 | Goto Auswahl |
Das du den Timer einsetzt ist schon OK. Aber du solltest ihn besser Nutzen, besonderst je näher deine Ausgabefrequen an die Taktfrequenz heranreicht. Du willst ein Rechtecksignal mit variabler Frequenz und einstellbarem Verhältnis. Das einstellen eines bestimmten Dutys ist eigentlich eine PWM. Das kann der Timer 1 in Hardware machen und dabei einen Pin (OSC1A/B) ansteuern. Einmal gestartet braucht sich das Programm nicht mehr darum kümmern, kann die Werte jedoch bei Bedarf ändern (OCR1A/B-Register). Die variable Frequenz ergibt sich aus dem TOP-Wert des Timers. Bei einer 8 Bit PWM ist er 255 bei 10 sind es 1023. Aber der Mega kann (wenn man es ihm sagt ICR1-Register) auch bis 617 Zählen. Die Frequenz ist immer
Jetzt versuch mal in deinem Programm zuerst ein PWM und dann das Verändern des TOP-Wertes. Tutorial und Datenblatt helfen. Am Ende dann ICR1 aus Frequenzeingabe berechnen und den Duty OCR1 als Prozentualen Anteil von ICR1. Möglich sind bei deinem Quarz ca. 3,6 kHz mit 0,1% Schritten. avr
Hallo, ich bin jetzt schonmal weiter, die PWM funktioniert jetzt. Ich habe nur noch keine Idee wie ich den TOPwert des Zählers ändere. Also die Timer im PWM Modus arbeiten ja wenn ich das richtig aus den Tutorials verstanden habe so: -Zählen (vorwärts) -Bei ereichen des Comparewertes Port auf High. -TOPwert ereicht. -Zählen (rückwärts) -Bei ereichen des Comparewertes Port wieder auf Low. -Bei ereichen von 0 wieder von vorne beginnen. Den Comparewert berechne ich wie du sagtest über das Tastverhältnis. Was auch schon gut Funktioniert (100% Prüfen konnte ich das noch nicht weil mein Oszilloskop gerade repariert wird). Jetzt fehlt mir nur noch die Möglichkeit den TOPwert festzulegen (Aus dem Datenblatt bin ich auch nicht sonderlich schlau geworden weil mir als Einsteiger in Microcontroller noch der Überblick darin fehlt). MfG Tmelle
Hier ist das eigentlich gut beschrieben: http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM Du brauchst den MODUS 14. avr
Hallo, ich komme mit den ganzen Einstellungen in den Registern irgendwie nicht zurecht. Ich bekomme mit meinen Einstellungen zwar Frequenzen heraus aber nicht die die ich will. Evtl könnte mir ja jemand eine Timer Config erstellen, wäre echt net. MfG
Hi, dein Problem sind nicht die Register sondern das Grundverständnis. Angenommen du hast eine 1Mhz Clock und willst ein 100Hz Signal haben(Prescaler 1). Der Timer muss dazu 100 Mal von 0 nach top und wieder nach 0. Das wird dann alle 1000000hz/100Hz = 10000 Taktzyklen passiert sein müssen. Um den Top Wert zu erhalten wird das noch durch 2 geteilt. Also müsste das Top Register 5000 haben. Für ein Tasverhältnis von 30% muss in das Output Compare Register also 1500. Jetzt musst du nur noch den Prescaler setzen damit die Werte in die Register passen. Condi
Genau so habe ich das ja berechnet, also ich denke das Prinzip habe ich schon verstanden. Ich weiss nur noch nicht was der Unterschied von z. B. ICR1L und ICR1H ist.
Hi >Ich weiss nur noch nicht was der Unterschied von z. B. ICR1L und ICR1H >ist. ICR1 ist ein 16 Bit Register. ICR1L sind davon die niederwertigen und ICR1H die höherwertigen 8 Bit. Gleiches gilt für die OC-Register. Zu beachten ist, das erst das H-Byte und danach das L-Byte geschrieben wird. Beim Lesen erst L-Byte, danach H-Byte. MfG Spess
Also wenn ich jetzt zum Beispiel in IRC1 987 schreiben möchte, muss ich dann 987 erst in binärcode umwandeln um den Wert in das Register zu schreiben, oder wie stelle ich das am besten an? MfG Tmelle
Sry, war gerade bei 10 Bit. 987 geht natürlich nicht, als Beispiel könnte natürlich der Wert 234 sein. Oder ist das Regiter beim 10 Bit Modus auch in 2x 5 Bit eingeteilt?
Hi >muss ich dann 987 erst in binärcode umwandeln... 987=$03DB=0000001111011011b Bascom ist egal, wie du einen Wert angibst. Richtig geschrieben versteht es dich schon. >Sry, war gerade bei 10 Bit. 987 geht natürlich nicht,... Wieso? 10 Bit: 0...1023 >Genau so habe ich das ja berechnet, also ich denke das Prinzip habe ich >schon verstanden. Wenn ich deinen letzten Post lese, würde ich das bezweifeln. MfG Spess
Ich habe oben schon von 10 Bit geredet aber im Post davor ging es um 8bit, deshalb habe ich mich korrigiert. Ich meinte: Ich war gerade bei 10 Bit, 987 geht natürlich bei 8 Bit nicht. Sry habe mich unverständlich ausgedrückt. Mein Problem mit in Binär umwandeln war weil ich in zb. ICR1H zB. die 4 höherwertigen Bits und in ICR1L die 4 niederwertigen Bits hineinschreiben muss. Bascom erkennt aber leider nicht das komplette Register IC1R (wird nicht durch Bascom in Großbuchstaben und in andere Farbe geändert) somit muss ich ja den umweg über ...H und ...L gehen.
Hier nochmal der Programmteil Betrieb für den PWM-Modus umgeschrieben: Vieleicht kann mir ja einer sagen was hier falsch ist.
1 | Config Portb.1 = Output |
2 | |
3 | |
4 | 'TCCR1A Register |
5 | 'Bit 7:6= Match Portb.1=1, Bottom Portb.1=0, |
6 | 'Bit 5:4= - = 00 |
7 | 'Bit 3:2= - = 00 (wird nur bei non-PWM gebraucht) |
8 | 'Bit 1:0= 10= Modus14 |
9 | |
10 | Tccr1a = &B11100010 |
11 | |
12 | 'TCCR1B Register |
13 | 'Bit 7:6= Noise Canceler: Aus |
14 | 'Bit 5 = Reserviert |
15 | 'Bit 4:3= 11= Modus14 |
16 | 'Bit 2:0= 101 = Prescaler: 1024 |
17 | |
18 | Tccr1b = &B00011101 |
19 | |
20 | 'Input Capture Register (TOP-Wert) |
21 | 'Ich kann mir denken das das falsch ist, aber wie Teile ich am besten die Dezimalzahl? |
22 | Icr1l = 1000 |
23 | Icr1h = 1000 |
24 | |
25 | 'Output Compare Register = TV*TPeriode = 0,5*1000 = 500 |
26 | |
27 | Compare1a = 500 |
28 | |
29 | 'Warteschleife |
30 | |
31 | Do
|
32 | |
33 | Loop Until Pinc.5 = 0 |
Hier müsste eine Frequenz von 3686411/(1024*1000)= 3,6Hz herauskommen, aber der Ausgang verändert sich nicht, sprich f=0Hz. Entschuldigung das ich euch mit meinen "einfachen" Problemen nerve, ich hoffe ihr helft mir trozdem. Gruß Tmelle
Hi > 'Input Capture Register (TOP-Wert) > 'Ich kann mir denken das das falsch ist, aber wie Teile ich am > besten die Dezimalzahl? > Icr1l = 1000 > Icr1h = 1000 Die 1000 passen nicht in ICR1L oder ICR1H. In Bascom sollte es etwa so gehen(ohne Gewähr): DIM i as Word i=1000 ICR1H= High(i) ICR1L= Low(i) MfG Spess
Hm, ähm was sagt denn die Hilfe dazu? http://avrhelp.mcselec.com/config_timer1.htm alternativ: Beitrag "Melodieklingel BASCOM ATmega8" http://www.mcselec.com/index.php?option=com_content&task=view&id=69&Itemid=57 http://www.mcselec.com/index.php?option=com_content&task=view&id=244&Itemid=57
Hi >Hm, ähm was sagt denn die Hilfe dazu? >http://avrhelp.mcselec.com/config_timer1.htm.... Hier wird gerade versucht dem OT etwas 'fortgeschrittenere' BASCOM-Programmierung zu vermitteln. Und dann kommst du mit dem Urschleim aus der Hilfe. MfG Spess
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.