Hallo
Mein Name ist Max und ich mache gerade Abitur mit dem Schwerpunkt
Elektrotechnik. in Informatik arbeiten wir deswegen auch mit
µControllern.
zurzeit arbeiten wir (und warscheinlich auch bis zum ende der 13) mit
einem Phillips 80c552. unsere jetzige aufgabe besteht darin ein Programm
zu schreiben mit denen wir Töne erzeugen können. momentan bin ich soweit
dass ich eine Funktion ( beep(int frequenz, int länge) ) aufrufen kann
bei der mann die Parameter für die Frequenz (Tonhöhe) und Dauer (in ms)
angeben kann.
soweit so gut... leider ist mir beim Testen mit verschiedenen frequenzen
aber der selben tondauer aufgefallen dass umso höher die Frequenz ist
umso kürzer ist auch die Dauer. Natürlich liegt das am Aufbau meines
Programms und ich könnte mir vorstellen wie man das Problem besser lösen
könnte allerdings haben wir Interrupts noch nicht besprochen :(
Hier habt ihr erstmal meinen Programmcode
1
#include<REG552.H>
2
3
intTonAn=0;
4
voidBeep(intf,intl);
5
6
voidmain(void)
7
{
8
TMOD=0x11;
9
while(1)
10
{
11
Beep(100,1000);
12
Beep(200,1000);
13
Beep(300,1000);
14
Beep(400,1000);
15
Beep(500,1000);
16
Beep(600,1000);
17
Beep(700,1000);
18
Beep(800,1000);
19
Beep(900,1000);
20
Beep(1000,1000);
21
Beep(1100,1000);
22
Beep(1200,1000);
23
}
24
}
25
26
voidBeep(intf,intl)
27
{
28
intx;
29
30
for(x=0;x<l;x++)
31
{
32
TR1=0;
33
TH1=0xFC;
34
TL1=0x18;
35
TF1=0;
36
TR1=1;
37
38
do
39
{
40
TR0=0;
41
TH0=(65536-(1000000/(f*2)))>>8;
42
TL0=(65536-(1000000/(f*2)))&0x00FF;
43
TF0=0;
44
TR0=1;
45
while(TF0==0);
46
47
if(TonAn==0)
48
{
49
TonAn=1;
50
P4=0xFF;
51
}
52
else
53
{
54
TonAn=0;
55
P4=0x00;
56
}
57
58
}while(TF1==0);
59
}
60
}
Meine vermutung ist dass das Überlauf Flag TF1 schon auf 1 gesetzt wird
bevor mein Programmcode überhaupt ans ende der "do-schleife" kommt.
dadurch
sind niedrigere Frequenzen etwas länger und höhere genauer.
Am liebsten würde ich ja die do-schleifen bedingung (x<l) setzen und
sobald das überlauf Flag von Timer1 auf 1 gesetzt ist ein x++ machen.
ich hoffe ihr versteht was ich meine.... ansonsten bin ich natürlich für
alle vorschläge und jede Hilfe sehr dankbar
Max Dirkschneider schrieb:> 09.02.2015 12:00:> Bearbeitet durch Moderator
(Ist nicht an den Mod gerichtet)
Bitte keine Tabs in Sourcecode verwenden.
Einrückungen konsistent machen damit es lesbar(er) wird.
Max Dirkschneider schrieb:> soweit so gut... leider ist mir beim Testen mit verschiedenen frequenzen> aber der selben tondauer aufgefallen dass umso höher die Frequenz ist> umso kürzer ist auch die Dauer. Natürlich liegt das am Aufbau meines> Programms
Nicht wirklich. D.h. Ja, es liegt schon am Aufbau des Programms. Aber
wenn wir den mal als so gegeben hinnehmen, ist das Problem leicht
einzusehen.
Hz bedeutet Schwingungen pro Sekunde.
Wenn du also eine Schwingung mit 440Hz erzeugst, dann macht die in 1
Sekunde 440 Schwingungen. Logisch?
Gut. Wenn du aber eine Schwingung mit 880Hz erzeugst, dann jast du
logischerweise in 1 Sekunde 880 Schwingungen. Machst du hier ebenfalls
nur 440 Schwingungen, dann ist der Ton nur eine halbe Sekunde lang.
Auf einen Nenner gebracht: Wenn du deine Funktion die 'Zeit' in der Form
angibst, dass du der Funktion mitgibst wieviele Schwingungen sie
erzeugen soll, dann musst du in dieser Anzahl auch die Frequenz
einrechnen, damit du auf Zeiten kommst. Einfach immer nur 1000
hinschreiben ist zu wenig.
Edit: Ich zieh den Einwand zurück.
Ein genauerer Blick zeigt, dass da 2 Timer im Spiel sind, von denen
einer als echter Zeitzähler benutzt wird.
Karl Heinz
vielen vielen Dank für diese elegante Lösung dadurch brauche ich ja
nicht einmal einen zweiten Timer.(wenn ich das richtig verstanden habe)
Ich versuche mich mal daran und melde mich wenn ich es geschaft habe
oder noch am verzweifeln bin.
:)
Edit: wieso wurde jetzt die Antwort von Karl Heinz gelöscht !?
Max Dirkschneider schrieb:> Karl Heinz>>> vielen vielen Dank für diese elegante Lösung
Ich habs zurück gezogen.
Du benutzt offenbar 2 Timer, wobei einer die echte Zeit abzählt.
Im Moment denke ich, deine Analyse des Problems ist korrekt.
Was ich ändern würde: den Timer 1 10 mal so weit zählen lassen und dafür
die Zeiten durch 10 dividieren.
Dann läufst du nicht so schnell Gefahr, dass dir der Timer 1 von 0xFC18
bis zum Überlauf hochzählt, während der andere Schwingungen erzeugt, die
du jeweils abwartest.
Du kannst natürlich auch einfach Schwingungen zählen. Geht auch.
Man könnte natürlich auch die beiden Schleifen ineinander schachteln und
somit nur 1 Schleife haben, die sich an der Spieldauer orientiert und
den 2-ten Timer nach dem Portumschalten jeweils wieder neu startet.
> Edit: wieso wurde jetzt die Antwort von Karl Heinz gelöscht !?
Wer kann das wissen, warum er seine Antwort löscht....
Vielleicht war sie falsch, vielleicht hat er aus Versehen
Urheberrechtlich geschützten Code publiziert, wer weiß .......
Er wird schon seinen Grund haben.
Edit: Zu spät....
Ulrich F. schrieb:>> Edit: wieso wurde jetzt die Antwort von Karl Heinz gelöscht !?> Wer kann das wissen, warum er seine Antwort löscht....> Vielleicht war sie falsch
Sie war nicht angemessen. Aber ich war zu langsam und die Antwort wurde
schon gelesen.
Hallo nochmal
Dank Karl Heinz habe ich mich dafür entschieden einen Timer wegzulassen
um dann einfach die Tondauer durch die Zyklenanzahl festzulegen.
Leider habe ich jetzt ein genau umgekehrtes Problem.
Aus irgendeinem Grund der mir verborgen bleibt sind jetzt höhere
Frequenzen
wesentlich länger als tiefe. Dabei hatte ich zu Beginn genau das
gegenteilige Problem.
Hatt jemand ne Ahnung was ich da wieder falsch gemacht habe ?
Hallo Max,
der Mikrocontroller braucht für jede Verarbeitung eines Befehls eine
gewisse Anzahl von Zyklen. Deine Berechnung der Timer-Vorbelegung ist
relativ rechenintensiv. Je höher die Frequenz wird, desto häufiger muss
deine Schleife durchlaufen werden, um auf die theoretisch gleiche
Ton-Dauer bei unterschiedlichen Frequenzen zu kommen. Durch die ständige
Neuberechnung wird die Dauer der Schleifen also proportional länger.
Daher werden die hohen Töne auch länger abgespielt. Darüber hinaus hören
sich dich Töne auch nicht mehr korrekt an.
Pro Ton/Frequenz musst du die Timerbelegung nur einmal berechnen und
zwar außerhalb der Schleife. Dann hören sich die Töne auch korrekt an.
Ich habe noch ein paar zusätzliche Optimierungen eingefügt, damit die
Anzahl der Befehle innerhalb der Schleife möglichst gering ist (Weil
jeder Befehl eine zusätzliche ungewollte Verzögerung bewirkt).
MfG
Andreas Wolff
1
#include<REG552.H>
2
3
voidBeep(intf,intl);
4
5
voidmain(void)
6
{
7
TMOD=0x01;
8
TR0=1;
9
while(1)
10
{
11
Beep(50,1000);
12
Beep(200,1000);
13
Beep(600,1000);
14
Beep(1200,1000);
15
}
16
}
17
18
voidBeep(intf,intl)
19
{
20
intx=f/5*(l/100);// Divisor 5, da 100ms als Basis gewählt wurde. l in ms