Forum: Mikrocontroller und Digitale Elektronik Mit AVR "BEEP" generieren


von Axel Hermann (Gast)


Lesenswert?

Mikrocontroller: ATMega 8
Programmierumgebung: WinAVR und myAVR ProgTool

Hallo,
versuche gerade eine "Beep" über einen Piezo-Schallwandler bei einem 
Tastendruck zu generieren.

Ich habe hierzu den Timer0 aktiviert:
1
(TCCR0 = (1 << CS00 | 1 << CS01);)

Nun habe ich in der While Schleife im Main den Ausgang Q_C5 im Toggle 
Betrieb durch eine EXOR Verknüpfung. Diese wird durch die If-Bedingung 
und dem Timerregister mit Übereinstimmung des Vorgegebenen Bitmusters 
getoggelt ( if (TCNT0 & 0x07) ). Eine Vorgeschaltete if Bedingung 
wiederrum aktiviert diesen Vorgang ( if (Taster2) -> Taster2 ist so 
definiert: #define Taster2 !(PINB & (1<<PINB4)) ).

Nun habe ich das Problem, dass die Frequenz des Beeps unterschiedlich 
wird, wenn ich noch mehrere Unterprogramme aufrufe... Liegt das dann an 
der Zykluszeit oder habe ich einen anderen Denkfehler?
Ist der Gedanke einen Beep so zu generieren Grundsätzlich falsch oder 
macht man so etwas normalerweise über einen Interupt?

Ein weiteres komisches Phänomen ergibt sich dadurch, wenn ich im else 
Teil der Tasterabfrage den Ausgang Q_C5 durch Q_C &= ~(1 << Q_C4 | 1 << 
Q_C5); auf FALSE bringe, verändert sich die Frequenz auch. Nehme ich den 
Zusatz " | 1 << Q_C5 " aus der Programmierung, ist die Frequenz höher. 
Der else sollte doch normalerweise nur Wirksam sein, wenn der Taster2 
wieder "aus" ist.
1
int main(void)
2
{
3
  initialisierung();  
4
  while (1)
5
  {       
6
  unsigned char FP2;
7
  MatrixEinlesen();
8
9
  if (Taster2) 
10
  { 
11
    Q_C |= (1 << Q_C4);
12
      
13
    if (TCNT0 & 0x07)
14
    {
15
      Q_C ^= (1 << Q_C5);
16
    }
17
    
18
  } 
19
  else
20
  {
21
    Q_C &= ~(1 << Q_C4 | 1 << Q_C5); 
22
  }
23
  }
24
  return 0;  
25
}

von Karl H. (kbuchegg)


Lesenswert?

> Nun habe ich das Problem, dass die Frequenz des Beeps
> unterschiedlich wird, wenn ich noch mehrere Unterprogramme
> aufrufe... Liegt das dann an der Zykluszeit oder habe ich einen
> anderen Denkfehler?

Beides.
Was du hörst ist tatsächlich auf unterschiedliche Luafzeiten deiner 
Hauptschleife zurückzuführen.
Und du hast (wahrscheinlich) einen Denkfehler.
Hier

    if (TCNT0 & 0x07)
    {
      Q_C ^= (1 << Q_C5);
    }

das toggelt nicht den Ausgang bei jedem 7.ten Timertick sondern 
eigentlich ständig mit AUsnahme wenn der Timer 0 oder ein Vielfaches von 
8 ist. Was immer du mit deinem & hier erreichen wolltest, du hast es 
nicht erreicht.

Und ja. Sowas macht man am besten und am einfachsten in einer Interrupt 
Routine.

von Axel Hermann (Gast)


Lesenswert?

Mit der if Bedingung:

 if (TCNT0 & 0x07)
    {
      Q_C ^= (1 << Q_C5);
    }

wollte ich erreichen, das Q_C5 immer dann Toggelt, wenn TCNT den Wert 
0x00000110 hat. Im Prinzip sollte das eine Ausmaskierung sein... Muss 
man in einer if Bedingung dies mit && Realisieren?

von Karl H. (kbuchegg)


Lesenswert?

Axel Hermann schrieb:
> Mit der if Bedingung:
>
>  if (TCNT0 & 0x07)
>     {
>       Q_C ^= (1 << Q_C5);
>     }
>
> wollte ich erreichen, das Q_C5 immer dann Toggelt, wenn TCNT den Wert
> 0x00000110 hat.

Dann überleg mal

Wert für TCNT0    nach dem &      logischer Wert
   00000            00000              FALSE
   00001            00001              TRUE
   00010            00010              TRUE
   00011            00011              TRUE
   00100            00100              TRUE
   00101            00101              TRUE
   00110            00110              TRUE
   00111            00111              TRUE
   01000            00000              FALSE
   01001            00001              TRUE
   01010            00010              TRUE
   ....


Wenn du bei einem bestimmten Wert etwas machen willst, dann nimm ein == 
und kein &

Aber auch das ist noch falsch. Denn du machst die Aktion dann immer WENN 
der Timer diesen Zählerstand hat und nicht nur einmal wenn der Zähler 
diesen Wert gerade erreicht hat.

Wenn deine AUfgabe darin besteht um 14 Uhr einmal aus dem Fenster zu 
springen und du schreibst das so
   if ( Stunde == 14 )
     spring

dann springst du in der Zeit von 14 Uhr bis 15 Uhr hunderte male aus dem 
Fenster. Denn jedesmal wenn dein Programm zu dieser Abfrage kommt, ist 
es immer 14 Uhr.

von Patrick (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> dann springst du in der Zeit von 14 Uhr bis 15 Uhr hunderte male aus dem
> Fenster

Naja, gut, ich würde mal sagen, das hängt ganz massiv von der Fallhöhe 
ab.

Ab einer bestimmten, kritischen Höhe bleibt das Ereignis einmalig (Das 
Programm "stürzt ab" ;)

von Paul Baumann (Gast)


Lesenswert?

Karl Heinz schrob:
>....dann springst du in der Zeit von 14 Uhr bis 15 Uhr hunderte male aus >dem 
Fenster.

Ich wußte doch, daß die Programmierung in der Sprache C die Leute
früher oder später dazu treibt, aus dem Fenster zu springen...

;-)
MfG Paul

von .... (Gast)


Lesenswert?

...und deshalb nehme ich BASCOM, wo man sowas einfach mit "sound" und 
mit Frequenz- und Dauer- Konstante  macht...

von Karl H. (kbuchegg)


Lesenswert?

Bis du dann irgendwann auf einen Prozessor kommst, auf dem es kein 
BASCOM gibt und du dastehst wie der Ochs vorm Tor :-)

Auch wenn wir heutzutage gerne Taschenrechner benutzen, ist es immer 
noch hilfreich ein wenig Kopfrechnen zu beherrschen. Und so einen Sound 
auszugeben ist ja dann nicht gerade Raketentechnik. Ist wie LED-Blinken 
- nur schneller. Wenn man es nicht diskret hinkriegt, zeigt das eher von 
einer gewissen Verständnisschwäche, als von irgendetwas anderem. Und 
Verständnisschwäche ist immer schlecht.

von Axel Hermann (Gast)


Lesenswert?

Hallo,

wollte mich noch bedanken...

Habe die Geschichte nun über einen Timer Interupt laufen:

[/c]
...
ISR (TIMER0_OVF_vect )

  {
  TCNT0 = 256 - 8;
  Q_B ^= (1 << Q_B5);    //<--- Testweise!

  }
...

 if (Taster1)
  {
    TIMSK |= (1 << TOIE0);
  }
  else
  {
    TIMSK &= ~(1 << TOIE0);
    Q_B &= ~(1 << Q_B5);
  }


[/c]

Ich habe irgendwo einmal gelesen, dass man versuchen sollte Interupts zu 
vermeiden wenn diese nicht zwingend notwendig sind. Daher kam der 
Gedanke, den Zählwert in der Main - While Schleife Auszumaskieren (ist 
nun auch klar...) und auszugeben...

Eine Frage bleibt noch:

Warum muss man in einer if Bedingung Variablen mit && bzw. || 
Verknüpfen,  reicht hier nicht & bzw |? Was hat das für 
Programmiertechnische Hintergründe?

Mfg
Axel

von C-Freak (Gast)


Lesenswert?

Axel Hermann schrieb:

> Ich habe irgendwo einmal gelesen, dass man versuchen sollte Interupts zu
> vermeiden wenn diese nicht zwingend notwendig sind.

Das scheint mir kein guter Rat zu sein. Die Lernkurve ist natürlich 
etwas steiler, wenn man Timer einsetzt, aber die Vorteile überwiegen 
deutlich (zB weniger Komplexität in main(), sehr stabile Frequenz).

> Warum muss man in einer if Bedingung Variablen mit && bzw. ||
> Verknüpfen,  reicht hier nicht & bzw |? Was hat das für
> Programmiertechnische Hintergründe?

Das eine sind logische/boolsche, das andere "bitwise" (wie heisst das 
übersetzt?) Verknüpfungen. Konsultiere dein C Buch bzw. den C Standard.

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.