Forum: Mikrocontroller und Digitale Elektronik Zeitschalter


von Steffen (Gast)


Lesenswert?

Hallo,
habe  mittlerweile das Tutorial "durchgearbeitet" und bin jetzt auf 
jeden Fall um einiges schlauer! Aber schon bei meinem ersten Projekt 
habe ich ein kleines Problem : Wie kann ich nach einer bestimmten Zeit ( 
z.B. 1,5 Sekunden ) eine Led aufleuchten lassen ? Eigentlich benötige 
ich nur eine Funktion, die den MC eben diese Zeit nichts tun lässt ( 
außer "nop" ) . Ich habe mal etwas von "delay" gelesen ( Tutorial : LCD 
) , kann nun aber damit nicht sonderlich viel anfangen . Ich habe z.Z. 
einen 4433 @ 4 MHz und schreibe noch meine Programme in ASM, auf Anraten 
einiger Teilnehmer hier. Ich denke mal, dass das nicht so schwer sein 
wird, oder ?

Gruß

Steffen

von Rudi (Gast)


Lesenswert?

Hallo Steffen!

Die von Dir angeschprochene Möglichkeit funktioniert natürlich,
wenn Du aber Deinen µC 1,5 sek lang zum "Nichtstun" verdonnern willst, 
brauchst Du 6 Millionen nop´s. Außerdem ist Dein Controller während der 
Wartezeit außer Gefecht gesetzt und kann keine anderen Aufgaben 
ausführen (z.B. Tastaturabfrage). Darum ist es wohl besser, Du erledigst 
solche Aufgaben mit einem Timer. Die zum Einstellen des Timers 
notwendigen Register findest Du im Datenblatt Deines Controllers. 
Achtung: Interrupts müssen auch aktiviert sein.

Gruß,
Rudi

von Michael T (Gast)


Lesenswert?

Hallo,
mit einem Timer ist es sicher besser.

Trotzdem die sache mit Delay ist so:

.def Delay = rXX
.def Delay1= rXX


Loop:

Programm

Dly:
 dec delay
 brne Dly
 dec delay1
 brne Dly

rjmp loop

Delay(1) wird von 0 - 255 gezählt.
Da beide gezählt werden ist die zeit bis zum Rücksprung größer.
Das ganze läst sich durch weitere Delay's ausbauen.

Viele Grüße
 Michael T

von Steffen (Gast)


Lesenswert?

Hallo,
erstmal Danke. Das mit dem Timer hört sich eigentlich schon ganz gut an 
! Sehe ich das richtig : Wenn der 8-bit Timer jeden Takt bis 255 gezählt 
hat und dann eins weiter springt, dann gibt's einen Interrupt. Gut und 
was nun ? Man sollte nun noch die Anzahl der Interrupts zählen , damit 
man auf eine bestimmte Zeit kommt, aber wie ? Hat das Oqverflow-Bit im 
SRG eigentlich etwas mit dem Timer zu tun ?

Gruß

Steffen

von Rudi (Gast)


Lesenswert?

Hallo Steffen!
Bin auch Neuling und hab den Timer schon vor einigen Wochen ausprobiert 
- wenn ich mich recht erinnere geht das so: (hoffentlich erzähl ich 
keinen Blödsinn!)

Der Timer zählt im Reg. TCNT0 (ich glaub nach unten), wobei Du
a) in selbiges Register einen Ausgangswert schreiben kannst
b) in TCCR0 einen Vorteiler einstellen kannst (max. 1024 - dann wird nur 
jeder 1024te Taktzyklus gezählt)

Den Interrupt gibt´s, wenn TCNT0 überläuft (Bit7 von TIMSK muß gesetzt 
sein). Du erhältst also etwas weniger als 4000x /sec. einen Inerrupt.
Diese hohe Impulsfrequenz kannst Du Durch Zähler in Deinem Interrupt - 
Handler (nach dem Delay-Muster von Michael) weiter teilen.
Du kannst auch mehrere Zähler einfügen und somit einen Timer für mehrere 
Aufgaben nutzen.

Rudi

von Bernhard Efler (Gast)


Lesenswert?

hi!

ich beschäftige mich auch gerade mit den timern und hab auch ne frage 
dazu!

wielange dauert jetzt bei einem 4 MHz kristall ein takt? also wenn ich 
1024 taktzykeln verstreichen lass, wieviele s bzw ms sind das dann?

Bernhard

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

1 Takt = 1Takt = 1/4000000 s

von Steffen (Gast)


Lesenswert?

Hallo,
ich habe mich nun etwas näher mit dieser Materie befasst und folgendes 
ist dabei herausgekommen :

----------------------------------------------
.INCLUDE "4433def.inc"
.DEF  mp = R16 ; Zähler für Anzahl Nulldurchgänge
.DEF  z1 = R0
.DEF    z2 = R17

    rjmp  main

main:

  ldi  mp,RAMEND ;Initiate Stackpointer (Unterprogramme!)
  out  SPL,mp

  ldi  mp,0      ; z1 kann nicht direkt gesetzt werden, da R0
  mov  z1,mp     ; Kopieren von mp in das Register z1

  ldi  mp,0x04   ;Initiate Timer/Counter 0 Vorteiler (256)
  out  TCCR0,mp  ; an Timer 0 Control Register

  ldi  mp,0xFF   ; alle Bits als Ausgang
  out  DDRB,mp   ; in Datenrichtungsregister

loop:

    in  mp,TCNT0  ; Inhalt des 8-Bit-Zählers lesen
  cpi  mp,0      ; auf Null testen
  brne  loop      ; Wenn nicht null, dann wieder loop
  rcall  IncZ1     ; Unterprogramm Software-Zähler erhöhen

warte:

  in  mp,TCNT0  ; Inhalt Zähler 0 lesen
  cpi  mp,0      ; auf Null testen
  breq  warte     ; Warte bis nicht mehr Null
  rjmp  loop      ; Nächste Runde

IncZ1:

  inc  z1        ; Erhöhe Software-Zähler
  cpi z1,0
    breq IncZ2
  rjmp    warte

IncZ2:
    inc     z2
    cpi z2, 100   ; Wenn 100 erreicht -> Ausgabe ( nach ca. 6,5 Sec )
    breq ausgabe
    rjmp warte

ausgabe:

    ldi r18, 0b11111100 ;0b11111100 in r16 laden
    out PORTB, r18      ;r16 ins IO-Register PORTB ausgeben

ende:    rjmp ende           ;Sprung zur Marke "ende" -> Endlosschleife
----------------------------------------------------

Dieses tolle Programm soll nach ca. 6,5 Sekunden 2 LEDs anschalten. Die 
Programmteile sind aus veschiedenen Tutorials zusammengesetzt, aber 
AVRStudio findet immer einen Fehler ( bei " cpi z1,0 " ). Wo ist da das 
Problem ? Cpi heißt doch : vergleiche mi ner Konstante (0) . Gruß

Steffen

von mikki merten (Gast)


Lesenswert?

der CPI Befehl lässt sich nur in Verbindung mit den Registern R16 bis 
R31 benutzen.

von Frank Simon (Gast)


Lesenswert?

Bei mir blinkts so:

.include "4433def.inc"
.def temp = r16
.def counter = r17
.def leds = r18
.equ start = 256 - 244 ;  bei 8 MHz entspricht das ca. 1/32 sec
.equ loops = 32;

rjmp reset           ; Reset Handler
reti         ; IRQ0 Handler
reti                 ; IRQ1 Handler
reti                 ; Timer1 Capture Handler
reti                 ; Timer1 compare Handler
reti                 ; Timer1 Overflow Handler
rjmp timer0          ; Timer0 Overflow Handler
reti                 ; SPI Transfer Complete Handler
reti                 ; UART RX Complete Handler : RXCIE
reti                 ; UDR Empty Handler
reti                 ; UART TX Complete Handler
reti                 ; ADC Conversion Complete Interrupt Handler
reti                 ; EEPROM Ready Handler
reti                 ; Analog Comparator Handler

reset:
ldi temp, RAMEND
out SP, temp; set stack pointer

ldi temp, 0xFF
out DDRC, temp     ; PORTC configured for output
ldi temp, 0xFF
out PORTC, leds   ; LEDs ausschalten

ldi temp, 1<<TOIE0    ; 0000 0010
out TIMSK, temp    ; timer 0 interrupt ein
ldi temp, start
out TCNT0, temp   ; Startwert des Timers
ldi temp, 0b00000101
out TCCR0, temp    ; Timer starten mit Vorteiler 1024

ldi counter, loops
ldi leds, 0xFF

sei ; interrupts generell aktivieren

main:
loop:
rjmp loop


;--------------------------------------------------
timer0:
dec counter
brne restart
ldi counter, loops
com leds
out PORTC, leds
restart:
ldi temp, start
out TCNT0, temp ; Timer fängt wieder von vorn an
reti

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
Noch kein Account? Hier anmelden.