www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Frequenzmessung über ICP


Autor: frankparker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
ich möchte eine Frequenz(10k-20k) über PB0(ICP) beim Atmega8 messen.

Das Programm steht soweit - kuckt mal bitte drüber und sagt mir ob das 
so richtig ist. Ich weis auch nicht wie ich das ganze jetzt umwandle 
damit ich herz angáben aufs display bekomme:


;----------------------------------------------------------------------- 
---
; Title         : Assembler Grundgerüst für myAVR-Board
;----------------------------------------------------------------------- 
---
; Funktion      : ...
; Schaltung     : ...
;----------------------------------------------------------------------- 
---
; Prozessor     : ATmega8
; Takt          : 3,6864 MHz
; Sprache       : Assembler
; Datum         : ...
; Version       : ...
; Autor         : ...
;----------------------------------------------------------------------- 
---
.include "AVR.H"
;----------------------------------------------------------------------- 
----
; Reset and Interrupt vector                Beschreibung
begin:   rjmp    main                       ;POWER ON RESET
         reti                               ;Int0-Interrupt
         reti                               ;Int1-Interrupt
         reti                               ;TC2 Compare Match
         reti                               ;TC2 Overflow
       rjmp  onTC1                       ;TC1 Capture
         reti                               ;TC1 Compare Match A
         reti                               ;TC1 Compare Match B
         reti  ;rjmp  TC1Over                     ;TC1 Overflow
         reti                               ;TC0 Overflow
         reti                               ;SPI, STC Serial Transfer 
Complete
         reti                               ;UART Rx Complete
         reti                               ;UART Data Register Empty
         reti                               ;UART Tx complete
         reti                               ;ADC Conversion Complete
         reti                               ;EEPROM Ready
         reti                               ;Analog Comparator
         reti                               ;TWI (I²C) Serial Interface
         reti                               ;Store Program Memory Redy
;----------------------------------------------------------------------- 
----
; Start, Power ON, Reset



main:    ldi     r16, lo8(RAMEND)
         out     SPL, r16
         ldi     r16, hi8(RAMEND)
         out     SPH, r16

       rcall   timer
        rcall   LCD_init
        rcall   LCD_clear
        rcall  Sensor

        rcall   begruessung


mainloop:
      rcall   LCD_line2

      mov    r16,r20

      rcall   LCD_data
      mov    r16,r21
      rcall   LCD_data



loop:    cp    r21,r5
      cp    r20,r4
      brne  mainloop
      rjmp loop





;----------------------------------------------------------------------- 
----
begruessung:
      rcall  wait
      rcall  LCD_home
      ldi    r16,'E'
      rcall   LCD_data
      ldi    r16,'R'
      rcall   LCD_data
      ldi    r16,'K'
      rcall   LCD_data
      ldi    r16,'A'
      rcall   LCD_data
      ldi    r16,'N'
      rcall   LCD_data
      ldi    r16,'N'
      rcall   LCD_data
      ldi    r16,'T'
      rcall   LCD_data
      ldi    r16,'E'
      rcall   LCD_data
      ldi    r16,' '
      rcall   LCD_data
      ldi    r16,'F'
      rcall   LCD_data
      ldi    r16,'A'
      rcall   LCD_data
      ldi    r16,'R'
      rcall   LCD_data
      ldi    r16,'B'
      rcall   LCD_data
      ldi    r16,'E'
      rcall   LCD_data
      ldi    r16,':'
      rcall   LCD_data
      rcall LCD_line2
      ret




;----------------------------------------------------------------------- 
----
onTC1:    cli
      in  r20,ICR1L
      sub r20,TCNT1H
      in  r21,ICR1H
      ldi  r22,0b00000000
      out  ICR1H,r22
      out  ICR1L,r22
      out  TCNT1H,r22
      out  TCNT1L,r22
      ldi  r26,0b00100000
      out  TIMSK,r26
      sei
      reti
;----------------------------------------------------------------------- 
----

Autor: frankparker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
achja hier noch das Timer-Init-Prog:
timer:  cli
    ldi  r26,0b00000000
    out TCCR1A, r26
    ldi  r26,0b11000001
    out  TCCR1B,r26

    ldi  r27,0b00000000

    out  TCNT1H,r27
    out  TCNT1L,r27


    out  ICR1H,r27
    out  ICR1L,r27

    ldi  r26,0b00100000
    out  TIMSK,r26
    sei
    ret

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie genau soll denn die Messung werden?

Mit der Taktfrequenz und Messfrequenz wird die Auflösung mit einer 
Messung EINER Periodendauer maximal auf ca. 40Hz genau! -Aber nicht mit 
dieser Timerroutine, denn ein löschen des Zählers in der 
Interruptroutine bringt unnötige Fehler durch die Ausführungszeiten. 
Wenn, dann musst du den Zähler laufen lassen, und die Differenz aus 2 
ICR Werten berechnen. Genauer wirds, wenn du über mehrere Perioden 
misst.
Alternativ - Das Messsignal über einen Counter zählen (bei der Frequenz 
noch zusätzlich mit Software) und das über eine mit dem 2. Timer 
vorgegebene Zeit.


Sascha

Autor: frankparker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
auf 40Hz genau würde mir völlig reichen - das Programm dient nachher zur 
Auswertung eines Farbsensors.

Das mit der different aus 2ICR Werten hab ich auch schon öfter gelesen - 
ich weis aber nicht wie ich das realisieren soll

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal ein Bsp.

onTC1:
  in r20,ICR1L
  in r21,ICR1H    ;Wert bei INT-Auslösung

  mov r12,r20
  mov r13,r21     ;aktuellen Wert merken

  sub r20,r10
  sbc r21,r11     ;Zeit = neuer Wert - letzter Wert (r10:r11)

;wenn neuer Wert < alter Wert, dann ist ein Überlauf aufgetreten
 -> wenn bis zum Überlauf der Register gezählt wird, so braucht nichts 
zu korr. werden

  ;Messwert in r20:r21

  mov r10,r12
  mov r11,r13     ;bis zum nächsten mal merken

  reti

Diese Funktion liefert nur bei der 1. Messung einen falschen Wert, da 
die Register r10:11 ja noch keinen aktuellen Wert haben, was aber nicht 
stören sollte.
Das cli/sei in der INT-Routine brauchst du nicht, denn mit Aufruf einer 
Interruptroutine sind automatisch alle INT's gesperrt, bis mit reti der 
vorherige Zustand wiederhergestellt wird!

Sascha

Autor: frankparker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dank dir schonmal

ich hab das jetzt mal eingefügt:

onTC1:
      in  temp,ICR1L
      in  temp2,ICR1H

      mov  ZL,temp    ;ZL mit temp(ICR1L) laden
      mov  ZH,temp2  ;ZH mit temp2(ICR1H) laden
      sub temp,YL    ;temp(ICR1L) minus YL(zuerst 0 dann letzter 
Messwert)
      sbc  temp2,YH  ;temp2(ICR1H) minus YH(zuerst 0 dann letzter 
Messwert)

      mov YL,ZL    ;YL mit ZL(temp(ICR1L)) laden
        mov YH,ZH    ;YH mit ZH(temp2(ICR1H)) laden

        CP  temp,XL
        BRNE  ausgabe
        CP  temp2,XH
        BRNE  ausgabe

        mov  XL,temp
        mov  XH,temp2



      reti

Ich hab noch einen Vergleich eingefügt - der kontrollieren soll ob die 
selben Werte wie beim letzten mal gelesen wurden. Wenn dieses nicht der 
Fall ist soll der Wert auf dem Display ausgegeben werden.
Das funktioniert aber noch nicht...vll kuckt mal einer drüber.

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

was geht nicht ?

Auf keinen Fall kannst du die "ausgabe" mit br.. aus der INT-Routine 
aufrufen, denn bei 20kHz hast du nur 50µs (185 Takte) bis zum nächsten 
INT.

Lade in der INT-Rounine den Messwert nach X, und mache im Hauptprogramm 
folgendes:

;....
    clr xl
    clr xh
    sei

loop:
    tst  xl
    brne m00
    tst  xh
    brne m00   'warten bis Messwert vorliegt

'hier was sonst noch so zu tun ist ...

    rjmp loop

m00:
     'speichere die Werte von xl,xh noch mal zwischen, damit sie
      sich während der Ausgabe der beiden Register nicht durch
      den nächsten INT verändern können
    rcall  ausgabe
    cli     'damit der INT nicht beim löschen dazwischenfunkt
    clr xl
    clr xh
    sei
    rjmp loop


Sascha

Autor: frankparker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm

das sieht soweit schon ganz gut aus.
Mich wundert nur warum ich bei gleichbleibender Frequenz immer einen 
anderen Zählerstand rausbekomme

Theoretisch sollte das Programm bei gleicher Frequenz doch das selbe 
messen oder nicht ?

Autor: Sascha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie ändern sich die Messwerte? - wandern/springen - wie viel ??
Wie oder woraus entsteht das Signal was du mißt?
Ist es ein rechteckförmiges Signal??

Sascha

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.