mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Rechteckgenerator Warteschleife


Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Kannnix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).

Autor: Michael (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Steffen N. (steno)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Tobias Korrmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es bi dem Atmega8 keine Timer die man nutzen kann?

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  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

Autor: thcamper (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
Locate 1 , 14                                      'Anzeige "Betrieb"
         Lcd "BET"


         2f = F                                             'Variablenumwandlung in Word
         T = 36864.11 / Presc                               'Prozessortakt/Vorteiler
         T = T / 2f                                         'Warteimpulse pro Periode

         Impuls = T * Tv                                    'Warteimpulse pro Impuls (Tv=Tastverhältnis)

         Pause = 100 - Tv

         Pause = T * Pause                                  'Warteimpulse pro Pause


         Config Timer1 = Timer                              'Konfiguration Timer1 als Timer

         If Presc = 8 Then                                  'Prescaler für Frequenzbereiche einstellen
         Tccr1b = 2
         Elseif Presc = 64 Then
         Tccr1b = 3
         End If

         Waitms 500

         Enable Timer1                                      'Start Timer1
         Do


         Portc.3 = 0                                        'Ausgang auf Low
         Timer1 = 0                                         'Reset Timer1
         Do                                                 'Warteschleige Pause
         Loop Until Timer1 = Pause

         Portc.3 = 1                                        'Ausgang auf High
         Timer1 = 0                                         'Reset Timer1
         Do                                                 'Warteschleife Impuls
         Loop Until Timer1 = Impuls




         Loop Until Pinc.5 = 0


         Portc.3 = 0
         Disable Timer1
         Goto Auswahl

Autor: avr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: avr (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist das eigentlich gut beschrieben:

http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM

Du brauchst den MODUS 14.

avr

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Tmelle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier nochmal der Programmteil Betrieb für den PWM-Modus umgeschrieben:
Vieleicht kann mir ja einer sagen was hier falsch ist.
Config Portb.1 = Output


         'TCCR1A Register
         'Bit 7:6= Match Portb.1=1, Bottom Portb.1=0,
         'Bit 5:4= - = 00
         'Bit 3:2= - = 00 (wird nur bei non-PWM gebraucht)
         'Bit 1:0= 10= Modus14

         Tccr1a = &B11100010

         'TCCR1B Register
         'Bit 7:6= Noise Canceler: Aus
         'Bit 5  = Reserviert
         'Bit 4:3= 11= Modus14
         'Bit 2:0= 101 = Prescaler: 1024

         Tccr1b = &B00011101

         '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

         'Output Compare Register = TV*TPeriode = 0,5*1000 = 500

         Compare1a = 500

         'Warteschleife

         Do

         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

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Condi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tschuldigung.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.