Rechteckgenerator Warteschleife

Gast #1336399
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
Gast #1337661
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.
#1337666
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
Gast #1338212
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.
Gast #1338758
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
Gast #1338788
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.
Gast #1339234
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:
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
Gast #1339254
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
Gast #1339873
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
Gast #1340307
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
Gast #1340427
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
Gast #1341703
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
Gast #1341759
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.
Gast #1342438
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren