xmega: Frequenz messen per Interrupt und Timer

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • xmega: Frequenz messen per Interrupt und Timer

      Hallo,
      nach langer Zeit beschäftige ich mich mal wieder mit Bascom, grad eine frische Version gekauft. Ich möchte die Frequenz eines Rechtecksignals messen. Dieses hat eine Frequenz zwischen 1 und 30 Hz. Theoretisch stelle ich mir das so vor:
      Ein Timer läuft hoch, wird per Interrupt resettet. Ich lese dann das CCA register aus, in dem eine Zahl zwischen 0 und 65535 steht, die rechne ich in die Frequenz um. Der xmega läuft mit 32 MHz, also müsste ich mit einem Prescaler von 1024 Frequenzen zwischen 0.93 und 35 Hz einigermaßen gut messen können.
      Nur finde ich die Hilfe zu den Timern extrem verwirrend, auch bin ich ziemlich überrascht, dass es in den Samples nicht ein Beispiel dazu gibt, so exotisch ist das ja nun nicht....
      Ich weiß auch gar nicht an welchem Pin denn nun mein Rechtecksignal anliegen müsste....
      Hier stehen einige gute Infos, aber die kann ich nicht selber auf Bascom übertragen:
      kampis-elektroecke.de/mikrocontroller/xmega-timer/

      Folgenden Code habe ich bisher, der ist Murks, aber ich komme nicht weiter:

      Quellcode

      1. $regfile = "xm128A4Udef.dat"
      2. $crystal = 32000000
      3. $framesize = 100
      4. $hwstack = 100
      5. $swstack = 100
      6. $lib "xmega.lib"
      7. Config Osc = Disabled , 32mhzosc = Enabled
      8. Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
      9. Config Tcc0 = normal , Prescale = 1024 , Capturec = Enabled , Event_source = e0 , Event_action = capture , Event_delay = Disabled , Resolution = 16
      10. enable interrupts
      11. Config Com1 = 38400 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 'PC2
      12. Open "com1:" For Binary As #1
      13. Config Priority = Static , Vector = Application , Lo = Enabled , Med = Enabled
      14. Config Pinc.0 = Output
      15. config pinc.2=input
      16. Portc.2=1 'Aktiviert das den Pullup...?
      17. Do
      18. Print #1 , TCC0_CCA
      19. Waitms 100
      20. Toggle Portc.0
      21. Loop
      22. End
      Alles anzeigen
      Es wäre tll wenn ihr mir helfen könntet.....
    • Ich habs:

      BASCOM-Quellcode

      1. $regfile = "xm128A4Udef.dat"
      2. $crystal = 32000000
      3. $framesize = 100
      4. $hwstack = 100
      5. $swstack = 100
      6. $lib "xmega.lib"
      7. Config Osc = Disabled , 32mhzosc = Enabled
      8. Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
      9. dim cntr as word
      10. dim freq as single
      11. On Porta_int0 A0_a7_isr : Enable Porta_int0 , Lo
      12. Config Porta.7 = Input : Config Xpin = Porta.7 ,Sense = rising , outpull=pullup
      13. Porta_int0mask = &B1000_0000 ' Assign pin a7 to Porta_int0
      14. Config Tcc0 = Normal , Prescale = 1024
      15. Tcc0_per = 65535
      16. start tcc0
      17. Enable Interrupts
      18. Config Priority = Static , Vector = Application , Lo = Enabled , Med = Enabled , Hi = Enabled
      19. cntr=0
      20. freq=0
      21. Config Com1 = 38400 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 'PC3
      22. Open "com1:" For Binary As #1
      23. Do
      24. 'f=32000000/1024/cntr
      25. freq= 31250/cntr
      26. Print #1 , freq
      27. Waitms 24
      28. Loop
      29. End
      30. A0_a7_isr:
      31. cntr=tcc0_CNT
      32. tcc0_CNT=0
      33. Return
      Alles anzeigen
      Jetzt Erzeuge ich mit der Gabellichtschranke einen Interrupt und lese den Timer aus, setze ihn auf null. Damit bekomme ich meine Frequenz. Wenn meine Gabellichtscranke aber mal besonders langsam ist, und kein Interrupt kommt bevor der timer überläuft, dann bekomme ich natürlich ein falsches ergebnis.
      Kann man den Timer so konfigurieren, dass er nicht überläuft, sondern stehenbleibt....? Manuell stoppen und starten?
    • Damit ich feststellen kann, ob die Messung zulässig ist, muss ich einen Interrupt für den Timer overflow anspringen, und dort z.B. ein Bit setzen. Aber ich schaffe es nicht den Timer overflow festzustellen. Der T1_overflow wird niemals angesprungen, warum denn nicht...?

      BASCOM-Quellcode

      1. $regfile = "xm128A4Udef.dat"
      2. $crystal = 32000000
      3. $framesize = 100
      4. $hwstack = 100
      5. $swstack = 100
      6. $lib "xmega.lib"
      7. Config Osc = Disabled , 32mhzosc = Enabled
      8. Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1
      9. On Porta_int0 A0_a7_isr : Enable Porta_int0 , Lo
      10. Config Porta.7 = Input : Config Xpin = Porta.7 ,Sense = rising , outpull=pullup
      11. Porta_int0mask = &B1000_0000 ' Assign pin a7 to Porta_int0
      12. Config Tcc0 = Normal , Prescale = 1024
      13. Tcc0_per = 65535
      14. On Tcc0_ovf T1_overflow
      15. Enable Tcc0_ovf, Lo
      16. start tcc0
      17. Enable Interrupts
      18. Config Priority = Static , Vector = Application , Lo = Enabled , Med = Enabled , Hi = Enabled
      19. dim dataout as word
      20. dim freq as single
      21. dim cntr as word
      22. dim valid_measure as bit
      23. Config Com1 = 38400 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8 'PC3
      24. Open "com1:" For Binary As #1
      25. cntr=0
      26. freq=0
      27. Do
      28. 'f=32000000/1024/cntr
      29. freq= 31250/cntr
      30. Print #1 , freq
      31. Waitms 24
      32. Loop
      33. End
      34. A0_a7_isr:
      35. cntr=tcc0_CNT
      36. tcc0_CNT=0
      37. Return
      38. T1_overflow:
      39. print #1, "Ich bin übergeflossen."
      40. return
      Alles anzeigen
    • Hallo Willa
      Bei XMega läuft alles etwas anders als beim Mega.
      Da bin ich jetzt nicht der Experte. Aber in Grunde müsste es bis auf die Konfiguration genauso gehen wie beim Mega.

      Wie gesagt ich bin nicht der XMega Experte.

      Beim Mega würde ich das Taktsignal auf den ICP1-Pin legen.
      Der Timer1 lässt man einfach durchlaufen.

      Wenn nun eine Flanke am ICP1-Pin auftrit, wird der Timer1-Wert in das ICP1-Register umkopiert.
      Wenn du dir dann auf den ICP1 einen Interrupt auslösen lässt, kannst du in der ISR das ICP1-Register auslesen.
      Du musst dann nur die Differenz zum vorherigen Timerwert (ICP1) berechnen und anhand der Frequenz des Timers kann dann die Frequenz ermittelt werden.

      Timer 1 = Referenz-Takt.
      ICP1-Flanke kopiert automatisch Timer1-Wert in das ICP1-Register.
      Ein Interrupt auf ICP1-Flanke liest das ICR1-Register aus.

      Differenz der Timerwerte * Periodendauer des Timer1-Taktes ergibt die Periodendauer der gemessenen Frequenz.

      Ich gehe davon aus, dass der XMega auch ein ICP1-Register hat und einen solchen Pin.

      Das Datenblatt des XMEGA ist sicher auch eine gute Info-Quelle.