Forum: Mikrocontroller und Digitale Elektronik Frequenz eines Rechtecksignal manipulieren


von Jürgen F. (snipor)


Lesenswert?

Hallo Leute,

ich suche eine möglichst einfache Schaltung um die Frequenz eines 
Rechtecksignals (duty cycle 50%, 50-150Hz, Ampl ~3,6V) in der Art zu 
manipulieren dass ich einen positiven Offset von 20Hz habe. Also z.B. 
120 Hz statt 100 Hz.
Einen Microcontroller möchte ich möglichst vermeiden.

Hat jemand einen Vorschlag?

Danke

: Bearbeitet durch User
von Sascha W. (sascha-w)


Lesenswert?

Hallo,

also in der HF-Technik würde man das mit einem Mischer machen, aber 
50-150Hz sind da eher Gleichspannung.
Eine PLL-Lösung scheidet aus, denn damit kannst die Frequenz nur um 
einen bestimmten Faktor ändern.
folgendes würde gehen:
1) ein Frequenz-Spannung-Umsetzer
  macht aus deiner Eingangsfrequenz eine analoge Spannung
2) ein Spannungsgesteuerter Generator der dann deine neue Frequenz 
erzeugt
Scheint mir aber recht aufwendig und mit Abgleich verbunden.

Mit einem µC sollte das gehen, man müsste dann nur sehen (a) mit welcher 
Genauigkeit sich die Frequenz messen lässt und (b) wie die Genauigkeit 
bei der Erzeugung ist.

Sascha

von Jürgen F. (snipor)


Lesenswert?

Ja vieles scheidet leider aus.
Ich vermute fast dass die Realisierung mit einem µC wohl den besten 
Kompromiss darstellen wird.

Die Erzeugung sollte noch relativ gut machbar sein, aber ob die Messung 
der Frequenz so genau sein wird?

Es käme auch nur ein kleiner µC z.B. Attiny 13 in Frage.

von Wolfgang (Gast)


Lesenswert?

Jürgen F. schrieb:
> Ich vermute fast dass die Realisierung mit einem µC wohl den besten
> Kompromiss darstellen wird.

Wieso Kompromiss?
Du weißt nach jeder Periode des Eingangssignals die aktuelle Frequenz, 
kannst daraus die Periodendauer des Ausgangssignals ausrechnen und 
verwendest den Wert zur Steuerung eines unabhängig von der Software 
laufenden Timers. Viele direkter geht das doch eigentlich nicht.

von Jonathan S. (joni-st) Benutzerseite


Lesenswert?

Jürgen F. schrieb:
> Die Erzeugung sollte noch relativ gut machbar sein, aber ob die Messung
> der Frequenz so genau sein wird?
>
> Es käme auch nur ein kleiner µC z.B. Attiny 13 in Frage.

Ist problemlos auch mit noch kleineren µCs möglich. Und genau wird das 
auch, wenn man es richtig macht.


Gruß
Jonathan

von Wolfgang (Gast)


Lesenswert?

Jürgen F. schrieb:
> Die Erzeugung sollte noch relativ gut machbar sein, aber ob die Messung
> der Frequenz so genau sein wird?

Wie genau? Für einen µC mit einem Timer ist es doch ein leichtes, die 
Zeit zwischen zwei Flanken auszumessen. Und dann muß er halt mal 
rechnen.

Wofür braucht man eigentlich so einen Frequenzverschieber?

von c-hater (Gast)


Lesenswert?

Jürgen F. schrieb:

> ich suche eine möglichst einfache Schaltung um die Frequenz eines
> Rechtecksignals (duty cycle 50%, 50-150Hz, Ampl ~3,6V) in der Art zu
> manipulieren dass ich einen positiven Offset von 20Hz habe. Also z.B.
> 120 Hz statt 100 Hz.

Addition von zwei Frequenzen. Exakt das gleiche Thema hatten wir doch 
vor nicht allzu langer Zeit hier schon einmal. Ist das an irgendeiner 
Schule jetzt eine Standard-Hausaufgabe?

> Einen Microcontroller möchte ich möglichst vermeiden.

Das ist aber blöd, denn das stellt die einfachste Lösung dar, denn schon 
die einfachste alternative Lösung kostet mindest zwei CMOS-ICs und 
etliches Hühnerfutter drum herum.

von Jürgen F. (snipor)


Lesenswert?

Ich merke schon hier wird keine Alternative zu einem µC mehr kommen.
Mit einfache Schaltung war übrigens eine Schaltung mit möglichst wenigen 
Bauteilen gemeint.

Also werde ich es mal mit einem Attiny 13 versuchen.
Mal schauen wie ich da die Zeitmessung realisiere, einen Input Capture 
Pin hat er ja nicht.
Vorschläge?

Nein eine Hausaufgabe oder ähnliches ist es nicht, sondern für die 
"Manipulation" der Drehzahlauswertung eines Lüfters.

von Wolfgang (Gast)


Lesenswert?

Jürgen F. schrieb:
> Vorschläge?

Keinen ATtiny13

von Ulrich (Gast)


Lesenswert?

Wenn es nur um ein Lüftersignal geht, sollten die Anforderungen an die 
Genauigkeit wohl nicht so hoch sein. Da ginge dann wohl auch der Weg 
über die Spannung als zwischenwert, etwa mit 2 mal 4046.

Der Tiny13 wird das auch schon irgendwie hinbekommen, aber ein Tiny25 
mit 2 Timern ist vermutlich einfacher.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Ulrich schrieb:
> Der Tiny13 wird das auch schon irgendwie hinbekommen, aber ein Tiny25
> mit 2 Timern ist vermutlich einfacher.

Bei höheren Frequenzen seh ich das auch so. Aber bei der Anforderung von 
um die 150 Hz ist eine rein softwaretechnische Lösung wahrscheinlich 
sogar am einfachsten. Das heißt, man braucht gar keinen Timer.

Es reicht ein Billigst-Mikrocontroller, z.B. ATtiny13A, ATtiny10, 
8-Bit-PIC usw.

von Jürgen F. (snipor)


Lesenswert?

Was meinst du mit, man braucht keinen Timer?

von Bernie (Gast)


Lesenswert?

Würde da auch einen Tiny25 nehmen. - Mir täten
10 Cent mehr auch nicht so wehtun....

Timer0 um die Frequenz über ExtInt0 zu erfassen,
... etwas rechnen lassen ...
Timer1 um die Frequenz-mit-Offset auszugeben.

Man müsste sich jetzt Gedanken machen, ob man
beim Einschalten mit der Ausgabe einer maximalen,
oder einer minimalen (Vorgabe?) Frequenz anfängt...

Müsste man sich aber auch bei einer µC-freien
Konstruktion machen...

von Wolfgang (Gast)


Lesenswert?

Bernie schrieb:
> Man müsste sich jetzt Gedanken machen, ob man
> beim Einschalten mit der Ausgabe einer maximalen,
> oder einer minimalen (Vorgabe?) Frequenz anfängt...

Und warum nicht mit einer mittleren?

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Was meinst du mit, man braucht keinen Timer?

Dass man keinen Timer braucht. :-)

Aber – wie Bernie schon schrieb – mit Timer ist es einfacher. Man 
braucht sich dann weniger Gedanken über die Ausführungszeiten von 
Befehlen zu machen und muss nicht mit einer Reihe von NOPs fürs 
Gleichgewicht sorgen.

Ich würde dann aber nur einen einzigen Timer verwenden und den Rest in 
der Timer-ISR awickeln: Zeit zwischen zwei Flankenwechseln am Eingang 
mitzählen, diese umrechnen (z.B. *0,75) und damit den Zähler für die 
Flankenabstände des Ausgangs versorgen.

von Jürgen F. (snipor)


Lesenswert?

Markus Weber schrieb:
> Jürgen F. schrieb:
>> Was meinst du mit, man braucht keinen Timer?
>
> Dass man keinen Timer braucht. :-)
>
> Aber – wie Bernie schon schrieb – mit Timer ist es einfacher. Man
> braucht sich dann weniger Gedanken über die Ausführungszeiten von
> Befehlen zu machen und muss nicht mit einer Reihe von NOPs fürs
> Gleichgewicht sorgen.
>
> Ich würde dann aber nur einen einzigen Timer verwenden und den Rest in
> der Timer-ISR awickeln: Zeit zwischen zwei Flankenwechseln am Eingang
> mitzählen, diese umrechnen (z.B. *0,75) und damit den Zähler für die
> Flankenabstände des Ausgangs versorgen.

Habe unter anderem mal Attiny10 bei Dir geordert. Mal sehen ob sich das 
damit zufriedenstellend realiseren lässt.
Wäre halt von der Bauform optimal für meinen Fall.

: Bearbeitet durch User
von Jürgen F. (snipor)


Lesenswert?

Ich habe mal etwas mit einem Attiny10 herumgespielt.

Leider scheint da irgendwas nicht richtig zu funktionieren.

Um sicher zu gehen keinen Fehler gemacht zu haben, habe ich jetzt mal 
einen fertigen Code zur Frequenzmessung hier aus dem Forum benutzt.
Aber leider tritt hier auch ein Fehler auf.

Ich möchte mit der If Abfrage ganz unten den Pin PB0 auf High setzen 
sobald die Frequenz größer als 50 Hz ist.

Beim Compilieren mit dem aktuellen AVR Studio 6.1 erhalte ich allerdings 
folgende Fehlermeldung.

ld returned 1 exit status  collect2.exe

Es scheint an der Variablen in der If Abfrage zu liegen.
Weiße ich Freq einfach einen Wert und nicht Erg zu funktioniert es.
Normal sollte er doch einfach einen Integer daraus machen?

1
/*
2
3
/////////////////////////////////////////////////////////////////////
4
// Frequenzmesser
5
//
6
// Holger Brenner
7
//
8
// Das zu messende Signal wird an den Input Capture Pin des Prozessors
9
// angelegt. Zur Freqenzbestimmung wird mittels Timer1 die Perioden-
10
// dauer des Signals von einer steigenden Flanke bis zur naechsten
11
// steigenden Flanke ermittelt. Daraus laesst sich dann die Frequenz
12
// errechnen.
13
//
14
// Das Beispiel benutzt die LCD Funktionen von ....
15
// Für andere Ausgabemedien muss das entsprechend angepasst werden
16
//
17
// 8. Feb. 2007
18
/////////////////////////////////////////////////////////////////////
19
20
//
21
// Prozessor Taktfrequenz einstellen sofern es nicht eine Vorgabe
22
// beim Aufruf des C Compilers gab.
23
//
24
#ifndef F_CPU
25
#define F_CPU 4000000
26
#endif
27
28
29
#include <avr/io.h>
30
#include <avr/interrupt.h>
31
#include <util/delay.h>
32
33
#include <stdlib.h>
34
35
36
#ifndef TRUE
37
#define TRUE 1
38
#define FALSE 0
39
#endif
40
41
42
volatile unsigned char NrOverflows = 0; // Anzahl der Timer Overflows die während der Messung passiert sind
43
volatile unsigned int  StartTime = 0;   // ICR-Wert bei 1.High-Flanke speichern
44
volatile unsigned int  EndTime = 0;     // ICR-Wert bei 2.High-Flanke speichern
45
volatile unsigned char JobFlag;   // Job Flag
46
47
48
49
ISR( TIM0_CAPT_vect )
50
{
51
  static unsigned char ErsteFlanke = TRUE;
52
53
  if( JobFlag )          // Das Display wurde mit den Ergebnissen der vorhergehenden
54
  return;                    // Messung noch nicht upgedated. Die naechste Messung
55
  // verzögern, bis die Start und EndTime Variablen wieder
56
  // gefahrlos beschrieben werden koennen
57
58
  //
59
  // Bei der ersten Flanke beginnt die Messung, es wird der momentane
60
  // Timer beim Input Capture als Startwert gesichert
61
  //
62
  if( ErsteFlanke )
63
  {
64
    StartTime = ICR0;
65
    NrOverflows = 0;
66
    ErsteFlanke = FALSE;       // Die naechste Flanke ist das Ende der Messung
67
  }
68
69
  //
70
  // das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
71
  //
72
  else
73
  {
74
    EndTime = ICR0;
75
    JobFlag = TRUE;      // Eine vollständige Messung. Sie kann ausgewertet werden
76
    ErsteFlanke = TRUE;        // Bei der naechsten Flanke beginnt der naechste Messzyklus
77
  }
78
}
79
80
81
ISR( TIM0_OVF_vect )
82
{
83
  NrOverflows++;
84
}
85
86
int main()
87
{
88
  
89
  double Erg = 0.0;
90
  uint8_t Freq;
91
92
  
93
  TCCR0A = (1<<ICES0)  | (1<<CS00); // Input Capture Edge, kein PreScale
94
  TIMSK0 = (1<<ICIE0) | (1<<TOIE0); // Interrupts akivieren, Capture + Overflow
95
  
96
    DDRB |=(1<<DDB0);
97
  
98
  
99
  sei();
100
  
101
  while(1)
102
  {
103
    //
104
    // liegt eine vollständige Messung vor?
105
    //
106
    if( JobFlag )
107
    {
108
109
      //
110
      // Die Zeitdauer zwischen den Flanken bestimmen
111
      // Da EndTime und StartTime unsigned sind, braucht nicht
112
      // darauf Ruecksicht genommen werden, dass EndTime auch
113
      // kleiner als StartTime sein kann. Es kommt trotzdem
114
      // das richtige Ergebnis raus.
115
      // Allerdings muss die Anzahl der Overflows in der Messperiode
116
      // beruecksichtigt werden
117
      //
118
      // Die Zeitdauer wird als Anzahl der Taktzyklen zwischen den
119
      // beiden gemessenen Flanken berechnet ...
120
      Erg = (NrOverflows * 65536) + EndTime - StartTime;
121
122
      // ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
123
      Erg = F_CPU / Erg;       // f = 1 / t
124
125
      Freq = Erg;
126
      
127
      
128
    if (Freq>50)
129
    {
130
      PORTB |= (1<<PORTB0);
131
    }
132
  
133
    
134
135
      // die naechste Messung kann starten
136
      //
137
      JobFlag = FALSE;
138
    }
139
  }
140
}

: Bearbeitet durch User
von Andreas (Gast)


Lesenswert?

Die fehlt die Floating Point Library.
Hier müsste stehen wie es konfiguriert werden kann:

http://www.mikrocontroller.net/articles/FAQ

(Kapitel "Aktivieren der Floating Point Version von sprintf bei WinAVR 
bzw AVR-Studio")

von Jürgen F. (snipor)


Lesenswert?

Ich habe mal versucht in Abhänigkeit der gemessenen Frequenz ein neues 
Signal mit 20Hz höherer Frequenz zu erzeugen.

Leider funktioniert das so wie ich es gemacht habe nicht.
1. Die ausgegebene Frequenz schwankt dauernd sehr stark.
2. Die zusätzlichen Hz sind gar nicht bemerkbar.

Hat jemand eine Idee wie ich das stabil hinbekommen kann?
1
/////////////////////////////////////////////////////////////////////
2
// Frequenzmesser
3
//
4
// Holger Brenner
5
//
6
// Das zu messende Signal wird an den Input Capture Pin des Prozessors
7
// angelegt. Zur Freqenzbestimmung wird mittels Timer1 die Perioden-
8
// dauer des Signals von einer steigenden Flanke bis zur naechsten
9
// steigenden Flanke ermittelt. Daraus laesst sich dann die Frequenz
10
// errechnen.
11
//
12
// Das Beispiel benutzt die LCD Funktionen von ....
13
// Für andere Ausgabemedien muss das entsprechend angepasst werden
14
//
15
// 8. Feb. 2007
16
/////////////////////////////////////////////////////////////////////
17
18
//
19
// Prozessor Taktfrequenz einstellen sofern es nicht eine Vorgabe
20
// beim Aufruf des C Compilers gab.
21
//
22
//#ifndef F_CPU
23
#define F_CPU 1000000
24
//#endif
25
26
27
#include <avr/io.h>
28
#include <avr/interrupt.h>
29
#include <util/delay.h>
30
31
#include <stdlib.h>
32
33
34
#ifndef TRUE
35
#define TRUE 1
36
#define FALSE 0
37
#endif
38
39
40
volatile unsigned char NrOverflows = 0; // Anzahl der Timer Overflows die während der Messung passiert sind
41
volatile unsigned int  StartTime = 0;   // ICR-Wert bei 1.High-Flanke speichern
42
volatile unsigned int  EndTime = 0;     // ICR-Wert bei 2.High-Flanke speichern
43
volatile unsigned char JobFlag = FALSE;   // Job Flag
44
volatile signed long int Erg = 0;
45
volatile signed long int Mittelwert = 0;
46
47
48
ISR( TIM0_CAPT_vect )
49
{
50
  static unsigned char ErsteFlanke = TRUE;
51
52
  if( JobFlag )          // Das Display wurde mit den Ergebnissen der vorhergehenden
53
  return;                    // Messung noch nicht upgedated. Die naechste Messung
54
  // verzögern, bis die Start und EndTime Variablen wieder
55
  // gefahrlos beschrieben werden koennen
56
57
  //
58
  // Bei der ersten Flanke beginnt die Messung, es wird der momentane
59
  // Timer beim Input Capture als Startwert gesichert
60
  //
61
  if( ErsteFlanke )
62
  {
63
    StartTime = ICR0;
64
    NrOverflows = 0;
65
    ErsteFlanke = FALSE;       // Die naechste Flanke ist das Ende der Messung
66
  }
67
68
  //
69
  // das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
70
  //
71
  else
72
  {
73
    EndTime = ICR0;
74
    JobFlag = TRUE;      // Eine vollständige Messung. Sie kann ausgewertet werden
75
    ErsteFlanke = TRUE;        // Bei der naechsten Flanke beginnt der naechste Messzyklus
76
    
77
        //
78
        // liegt eine vollständige Messung vor?
79
        //
80
        if( JobFlag )
81
        {
82
83
84
          //
85
          // Die Zeitdauer zwischen den Flanken bestimmen
86
          // Da EndTime und StartTime unsigned sind, braucht nicht
87
          // darauf Ruecksicht genommen werden, dass EndTime auch
88
          // kleiner als StartTime sein kann. Es kommt trotzdem
89
          // das richtige Ergebnis raus.
90
          // Allerdings muss die Anzahl der Overflows in der Messperiode
91
          // beruecksichtigt werden
92
          //
93
          // Die Zeitdauer wird als Anzahl der Taktzyklen zwischen den
94
          // beiden gemessenen Flanken berechnet ...
95
          Erg = (NrOverflows * 65536) + EndTime - StartTime;
96
97
          // ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
98
          Erg = ((F_CPU/8) / Erg);       // f = 1 / t
99
                }
100
      }
101
102
}
103
104
ISR( TIM0_OVF_vect )
105
{
106
  NrOverflows++;
107
108
}
109
110
int main()
111
{
112
  int i=0;
113
  int j=10;
114
   
115
  CCP=0xD8;
116
    CLKMSR=0x00;
117
  CCP=0xD8;
118
  CLKPSR=0x03;
119
  
120
  TCCR0B |= ((1<<ICES0) | (1<<CS00)); // Input Capture Edge, kein PreScale
121
  TIMSK0 |= ((1<<ICIE0) | (1<<TOIE0)); // Interrupts akivieren, Capture + Overflow
122
    TCCR0A |= ((1<<WGM01) | (1<<WGM00) | (1<<COM0A0) | (0<<COM0A1));
123
    TCCR0B |= ((1<<WGM03) | (1<<WGM02)| (1<<ICNC0) | (1<<CS01));
124
                                                                          //Fast PWM Mode 15 auf Pin OC0A, Taktteiler 8,  Noise Canceler 
125
    DDRB=0x00;  
126
    DDRB |=(1<<DDB0);
127
    
128
  
129
  
130
  
131
  sei();
132
  
133
134
  
135
  while(1)
136
  {
137
     for( i=0; i<j; i++)  
138
            {
139
      Mittelwert = Mittelwert+Erg;
140
      }
141
        
142
      Mittelwert = Mittelwert/j;
143
      
144
      OCR0A =(F_CPU/8)/(2*(Mittelwert+20));
145
      
146
      
147
      Mittelwert=0;
148
      
149
        JobFlag=FALSE;
150
      //
151
      // Das wars: Display ist wieder up to date
152
      // die naechste Messung kann starten
153
      //
154
      
155
    }
156
157
}

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Hat jemand eine Idee wie ich das stabil hinbekommen kann?

Ich tendier bei sowas dazu, es in Assembler zu programmieren. Aber das 
ist Geschmacksache. Ich werde mir mal Gedanken drüber machen.

Deine Anforderung "+20 Hz" - lässt sich die auch abändern in "Frequenz 
um 25 % höher" (oder so ähnlich)? Dann könnte man Multiplikationen und 
Divisionen einsparen.

von Jürgen F. (snipor)


Lesenswert?

Markus Weber schrieb:
> Deine Anforderung "+20 Hz" - lässt sich die auch abändern in "Frequenz
> um 25 % höher" (oder so ähnlich)? Dann könnte man Multiplikationen und
> Divisionen einsparen.

Wenn es stabil laufen würde ging das zur Not auch.

von Jürgen F. (snipor)


Lesenswert?

Ich habe herausgefunden dass die Frequenzmessung über den Capture Pin 
nicht mehr funktioniert sobald ich Fast PWM Mode 15 aktiviere.
Kann mir jemand sagen weshalb das dann nicht mehr richtig arbeitet?

Geht Fast PWM und Input Capture nicht gleichzeitig?

: Bearbeitet durch User
von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Geht Fast PWM und Input Capture nicht gleichzeitig?

Habe ich nie probiert, müsste aber im Datenblatt ersichtlich sein... 
hoffentlich. :-)

Ich hab grad ein kleines Assembler-Programm geschrieben, das muss ich 
aber erst noch ausprobieren.

Und dazu brauche ich einen Breadboard-Adapter für den ATtiny10. Um den 
zu kriegen, muss ich eine Platine sägen. Um die Platine sägen zu können, 
muss ich die Säge aufbauen. Um die Säge aufbauen zu können, muss ich 
Platz schaffen. Und dazu schließlich muss ich aufräumen. Kann also noch 
ein paar Minuten dauern. ;-)

von Jürgen F. (snipor)


Angehängte Dateien:

Lesenswert?

Ok, also man sollte das Datenblatt doch mal genau lesen :)

Die Zeitmessung ging ja davon aus dass der Zähler erst bei 65536
überläuft.
Da ich ja aber im Fast PWM Mode 15 mit OCR0A vorgebe bis wie weit er
zählen soll muss ich natürlich auch für die Zeitmessung mit diesem Wert
rechnen.

Jetzt habe ich das Problem dass sich das ganze natürlich aufschauckelt,
und dann bis hoch in den kHz ausgibt.

Wie gehe ich da am besten vor um ein aufschauckeln zu vermeiden?

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

So, ATtiny10-Breadboard-Adapter ausgesägt und verwendet. :-)

Jürgen F. schrieb:
> Jetzt habe ich das Problem dass sich das ganze natürlich aufschauckelt,
> und dann bis hoch in den kHz ausgibt.

Ich geb zu, ich habe mich nicht getraut, Input Capture und PWM mit dem 
selben Timer zu erledigen. Zudem waren mir die 16 Bit Zählerbreite zu 
gering, jedenfalls dann, wenn man auch mal höhere oder niedrigere 
Frequenzbereiche nutzen will. Deswegen habe ich mit dazu entschlossen, 
grundsätzlich mit 24 Bits zu zählen.

Der Timer dient bei meiner Lösung nur noch als Zeitbasis und gibt den 
Takt für die Verarbeitung vor (hier 100 kHz).

Eine Abfrage musste noch ergänzt werden, damit beim plötzlichen 
Ausbleiben der Input-Flanken und damit nicht messbarer Einfangsfrequenz 
nicht weiter fröhlich der Ausgang vor sich hin togglet.
Und eine weitere Abfrage, die dafür sorgt, dass bei plötzlicher Erhöhung 
der Eingangsfrequenz der Ausgang nicht erst noch auf das Ende der 
aktuellen Schwingung wartet.

Deswegen wurde das Programm dann doch länger als gedacht...

1
; fq 2013-11-23 20:00
2
; version 0.1
3
; target: ATtiny10
4
;
5
; This program reads the frequency of the input signal at PB1
6
; and provides a similar signal at PB2 with frequency which
7
; has been increased by 25 %.
8
; operating range: 0.02 Hz .. ca. 10 kHz (resolution is 10 µs)
9
;
10
.include "tn10def.inc"
11
12
; register allocation
13
  .def temp=r16
14
  .def zero=r18  ; constant 0
15
  .def one=r19  ; constant 1
16
  .def inlevel=r31  ; level of input signal
17
  .def intime0=r20  ; 24-bit value for time between
18
  .def intime1=r21  ;   edges of input signal
19
  .def intime2=r22  ;   0..0x3f0000
20
  .def outtime0=r24  ; 24-bit value for time between
21
  .def outtime1=r25  ;   edges of output signal
22
  .def outtime2=r26  ;
23
  .def cache0=r28  ; 24-bit buffer for last input timer
24
  .def cache1=r29  ;   0..0xfeffff
25
  .def cache2=r30  ;   0xffxxxx: marked as invalid
26
27
  rjmp init
28
.org OC0Aaddr  ; timer ISR
29
30
  ; check if input signal has changed
31
  in temp,PINB
32
  eor temp,inlevel
33
  andi temp,0b0010
34
    breq countup  ; no change in input signal
35
  eor inlevel,temp  ; toggle singal level bit
36
37
  ; write decreased input counter value to buffer
38
  ; we multiply by 0b0.11 (decimal 0.75)
39
  mov cache0,intime0
40
  mov cache1,intime1
41
  mov cache2,intime2
42
  lsr cache2
43
  ror cache1
44
  ror cache0
45
  add cache0,intime0
46
  adc cache1,intime1
47
  adc cache2,intime2
48
  lsr cache2
49
  ror cache1
50
  ror cache0
51
52
  ; initialize input counter
53
  clr intime0
54
  clr intime1
55
  clr intime2
56
57
  ; check if output counter value is too high
58
  cp cache0,outtime0
59
  cpc cache1,outtime1
60
  cpc cache2,outtime2
61
  brsh countup  ; output counter value <= buffer value
62
63
  ; cut output counter value (set it to buffer value)
64
  mov outtime0,cache0
65
  mov outtime1,cache1
66
  mov outtime2,cache2
67
68
countup:
69
  cpi intime2,0x3f
70
  breq care_for_output  ; counter already at maximum
71
72
  ; increment input counter
73
  add intime0,one
74
  adc intime1,zero
75
  adc intime2,zero
76
77
  ; check if input counter value is too high
78
  mov temp,cache2
79
  cpi temp,0xff
80
    breq care_for_output  ; buffer value is not valid
81
  lsl cache0  ; temporarily multiply buffer by 4
82
  rol cache1
83
  rol cache2
84
  lsl cache0
85
  rol cache1
86
  rol cache2
87
  cp cache0,intime0
88
  cpc cache1,intime1
89
  cpc cache2,intime2
90
  brsh input_counter_ok  ; input counter <= buffer*4
91
    ldi cache2,0xff  ; mark buffer value as invalid
92
    rjmp care_for_output
93
  input_counter_ok:
94
  lsr cache2  ; divide buffer by 4
95
  ror cache1
96
  ror cache0
97
  lsr cache2
98
  ror cache1
99
  ror cache0
100
101
care_for_output:
102
103
  mov temp,outtime0
104
  or temp,outtime1
105
  or temp,outtime2
106
  breq new_countdown
107
108
  ; countdown
109
  sub outtime0,one
110
  sbc outtime1,zero
111
  sbc outtime2,zero
112
  brne finished
113
114
  ; toggle output pin
115
  ldi temp,0b0100
116
  out PINB,temp
117
118
new_countdown:
119
  ; check if buffer value is valid
120
  mov temp,cache2
121
  cpi temp,0xff
122
  breq finished  ; buffer value is not valid
123
124
  ; reload timer counter from buffer
125
  mov outtime0,cache0
126
  mov outtime1,cache1
127
  mov outtime2,cache2
128
129
finished:
130
  sei  ; shortcut for reti because there is no main program
131
  rjmp pc
132
133
init:
134
  ; Port initialization
135
  ldi temp,0b0000
136
  out PORTB,temp
137
  ldi temp,0b0100
138
  out DDRB,temp
139
140
  ; initialization of constants and variables
141
  ldi zero,0
142
  ldi one,1
143
  in inlevel,PINB
144
  clr intime0
145
  clr intime1
146
  ldi intime2,0x3f
147
  clr outtime0
148
  clr outtime1
149
  clr outtime2
150
  ldi cache2,0xff
151
152
  ; set CPU clock to 8 MHz
153
  ldi temp,0b0000  ; CPU prescaler 1
154
  out CLKPSR,temp
155
156
  ; timer initialization
157
  ldi temp,0
158
  out OCR0AH,temp
159
  ldi temp,80-1  ; maximum number of cycles of ISR
160
  out OCR0AL,temp
161
  ldi temp,1<<OCIE0A
162
  out TIMSK0,temp
163
  ldi temp,1<<WGM02|1<<CS00  ; prescaler 1
164
  out TCCR0B,temp
165
  sei
166
167
  ; let ISR do its job
168
  rjmp pc

von Jürgen F. (snipor)


Lesenswert?

Vielen Dank für das Programm. Es funktioniert natürlich sehr gut :)
Lässt sich die Frequenz auch z.B. auch um 30% erhöhen? Oder wären dafür 
grundlegende Änderungen nötig?

Ich bin aber trotzdem etwas enttäuscht weil ich das mit dem 
Aufschwingverhalten in C nicht hinbekomme.
Wäre hier für weitere Tipps sehr dankbar.

von Amateur (Gast)


Lesenswert?

Einen Spatz mit einer Kanone zu treffen scheint die 
Lieblingsbeschäftigung von einigen hier zu sein.

Einen 08/15 555, auf einen Bereich (Poti) von 100 bis 300 Hz und 
dahinter einen einfachen Teiler durch zwei.
Ist aber wahrscheinlich zu einfach und übersichtlich.
Und dann erst die Ausgangsspannung mit einem Poti auf 3,6 V zu trimmen, 
ist wohl der totale Overkill.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Lässt sich die Frequenz auch z.B. auch um 30% erhöhen? Oder wären dafür
> grundlegende Änderungen nötig?

Ich merk grad, dass das Assembler-Programm nicht die Frequenz um 25 % 
erhöht, sondern die Periodendauer um 25 % verkürzt. Das entspricht einer 
Frequenzerhöhung um 33 %. Im Prinzip sind auch andere Werte möglich, da 
aber die ATtinys keinen Multiplizierer besitzen, muss man sich mit 
Softwaremultiplikation behelfen. Und die klappt am besten, wenn es sich 
beim Faktor um eine Binärzahl mit möglichst wenig Nachkommastellen 
handelt (im Programm die Zahl 0b0.11, die dem Faktor 0,75 entspricht).

Hier der verantwortliche Teil:

1
  ; write decreased input counter value to buffer
2
  ; we multiply by 0b0.11 (decimal 0.75)
3
  mov cache0,intime0
4
  mov cache1,intime1
5
  mov cache2,intime2
6
  lsr cache2
7
  ror cache1
8
  ror cache0
9
  add cache0,intime0
10
  adc cache1,intime1
11
  adc cache2,intime2
12
  lsr cache2
13
  ror cache1
14
  ror cache0

> Ich bin aber trotzdem etwas enttäuscht weil ich das mit dem
> Aufschwingverhalten in C nicht hinbekomme.
> Wäre hier für weitere Tipps sehr dankbar.

Hier fällt mir leider nichts ein, aber vielleicht liest jemand mit, der 
einen Tipp geben kann...?

P.S.: Wenn du einen anderen Faktor als 1,33 brauchst, sag Bescheid, ich 
schreib dir ein Code-Beispiel.

: Bearbeitet durch User
von m.n. (Gast)


Lesenswert?

Vielleicht ist das Thema noch aktuell.
Da ich fertige Programme zur Frequenzmessung und Frequenzerzeugung für 
AVRs in der 'Schublade' habe, habe ich diese einmal kombiniert.

Um nicht zu kleckern, kommt nur ein AVR mit input-capture-Funktion in 
Betracht, wobei ein ATmega48 schon ausreicht.
Ferner ist es viel einfacher, ein Programm in C zu verwenden, bei dem 
die Eingangsfrequenz als float-Variable vorliegt und beliebig verrechnet 
werden kann. Ob jetzt die Eingangsfrequenz mit einem konstanten Offset 
versehen wird oder ein Teiler mit dem Faktor 2,5 bei beliebigen 
Tastverhältnis benötigt wird, in C kann man es sehr einfach formulieren 
und programmieren.

Quellcode sowie ein fertiges Beispiel f2f_konverter.hex sind hier zu 
finden. http://www.mino-elektronik.de/Generator/takte_impulse.htm#bsp4

von Jürgen F. (snipor)


Lesenswert?

Markus Weber schrieb:
> P.S.: Wenn du einen anderen Faktor als 1,33 brauchst, sag Bescheid, ich
> schreib dir ein Code-Beispiel.

Ich hätte noch eine kurze Frage, wäre es ohne große Änderung auch 
möglich dass nur die Frequenzen bis z.B. 90Hz verändert werden, und 
alles was darüber liegt einfach direkt 1:1 weitergegebn wird?

Danke

von Reinhard Kern (Gast)


Lesenswert?

Jürgen F. schrieb:
> dass nur die Frequenzen bis z.B. 90Hz verändert werden, und
> alles was darüber liegt einfach direkt 1:1 weitergegebn wird?

Meinst du das wirklich so:

90 -> 120
91 -> 91

??

Gruss Reinhard

von m.n. (Gast)


Lesenswert?

Jürgen F. schrieb:
> dass nur die Frequenzen bis z.B. 90Hz verändert werden, und
> alles was darüber liegt einfach direkt 1:1 weitergegebn wird?

...
if(f <= 90.0) f = f + 20.0;
erzeuge(f);
...

Reinhard Kern schrieb:
> ??

:-)

von Jürgen F. (snipor)


Lesenswert?

Reinhard Kern schrieb:
> Meinst du das wirklich so:
>
> 90 -> 120
> 91 -> 91
>
> ??
>
> Gruss Reinhard

Ja das meine ich tatsächlich so ;)

m.n. schrieb:
> ...
> if(f <= 90.0) f = f + 20.0;
> erzeuge(f);
> ...

Ja, wenn ich jetzt nur wüsste wie ich das in das Assemblerprogramm 
einbauen muss.... :(

Ich denke das C-Programm welches Du weiter oben als Beispiel genannt 
hast lässt sich nicht mit dem Attiny 10 realisieren.

: Bearbeitet durch User
von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Moin! :-)

Wie oben schon geschrieben, ist dieser Teil für die Umrechnung 
verantwortlich:
1
  ; write decreased input counter value to buffer
2
  ; we multiply by 0b0.11 (decimal 0.75)
3
  mov cache0,intime0
4
  mov cache1,intime1
5
  mov cache2,intime2
6
  lsr cache2
7
  ror cache1
8
  ror cache0
9
  add cache0,intime0
10
  adc cache1,intime1
11
  adc cache2,intime2
12
  lsr cache2
13
  ror cache1
14
  ror cache0

Für die Fälle, in denen die Periodenlänge kleiner als 10 ms ist und 
deswegen keine Frequenzänderung erfolgen soll, müsste die Multiplikation 
durch eine reine Zuweisung ersetzt werden:
1
  mov cache0,intime0
2
  mov cache1,intime1
3
  mov cache2,intime2

Wäre also noch eine entsprechende Abfrage notwendig.

Ich kanns leider grad nicht probieren, weil ich den Versuchsaufbau nicht 
mehr da habe.

Testen muss man das auf alle Fälle, denn wenn ich mich recht erinnere, 
begrenzt das Programm den Faktor auf den Bereich zwischen 1/4 und 1/1. 
Keine Ahnung, was passiert, wenn man dann direkt an der 1,0-Grenze dran 
ist. Wahrscheinlich funktionierts ohne Probleme - aber ich würds besser 
ausprobieren.

von m.n. (Gast)


Lesenswert?

Jürgen F. schrieb:
> Ich denke das C-Programm welches Du weiter oben als Beispiel genannt
> hast lässt sich nicht mit dem Attiny 10 realisieren.

So ist es. Minimal wäre ein ATtiny2313 notwendig. Dafür macht er dann 
alles, was Du möchtest.
Es mit einem ATtiny10 zu machen ist auf jeden Fall sehr 'interessant'.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Ich hätte noch eine kurze Frage, wäre es ohne große Änderung auch
> möglich dass nur die Frequenzen bis z.B. 90Hz verändert werden, und
> alles was darüber liegt einfach direkt 1:1 weitergegebn wird?

Ach so, was mir grad noch einfällt, nach deiner Beschreibung wäre das 
z.B. so:

aus 90 Hz wird 120 Hz
aus 91 Hz wird 91 Hz

Du hättest dann einen Sprung in der Kennlinie. Ist das so gewollt?

von Jürgen F. (snipor)


Lesenswert?

Markus Weber schrieb:
> Wäre also noch eine entsprechende Abfrage notwendig.
>
> Ich kanns leider grad nicht probieren, weil ich den Versuchsaufbau nicht
> mehr da habe.
>
> Testen muss man das auf alle Fälle, denn wenn ich mich recht erinnere,
> begrenzt das Programm den Faktor auf den Bereich zwischen 1/4 und 1/1.
> Keine Ahnung, was passiert, wenn man dann direkt an der 1,0-Grenze dran
> ist. Wahrscheinlich funktionierts ohne Probleme - aber ich würds besser
> ausprobieren.

Testen wäre kein Problem, leider weiß ich nicht wie eine entsprechende 
Abfrage zu implementieren wäre.

Markus Weber schrieb:
> Ach so, was mir grad noch einfällt, nach deiner Beschreibung wäre das
> z.B. so:
>
> aus 90 Hz wird 120 Hz
> aus 91 Hz wird 91 Hz
>
> Du hättest dann einen Sprung in der Kennlinie. Ist das so gewollt?

In diesem Fall ja, da auch das Eingangssignal nicht kontinuierlich ist 
sondern Sprünge hat.
Die Eingangsfrequenz springt also z.B. von 70Hz auf 81Hz usw.



m.n. schrieb:
> Jürgen F. schrieb:
>> Ich denke das C-Programm welches Du weiter oben als Beispiel genannt
>> hast lässt sich nicht mit dem Attiny 10 realisieren.
>
> So ist es. Minimal wäre ein ATtiny2313 notwendig. Dafür macht er dann
> alles, was Du möchtest.
> Es mit einem ATtiny10 zu machen ist auf jeden Fall sehr 'interessant'.

Ja, durch den von mir verwendeten Attiny10 ist das ganze natürlich 
programmiertechnisch nicht so einfach umzusetzen, zumindest nicht für 
mich.
Aber das Programm von Markus funktioniert ja hervorragend mit dem 
Attiny10, das wäre ja jetzt nur eine Erweiterung zur ursprünglich 
genannten Anforderung.

Danke

: Bearbeitet durch User
von Reinhard Kern (Gast)


Lesenswert?

Markus Weber schrieb:
> Du hättest dann einen Sprung in der Kennlinie. Ist das so gewollt?

Das hatte ich auch schon gefragt, aber m.n. fand das dann furchtbar 
lächerlich. Anscheinend ist genaueres Nachdenken und Hinterfragen nicht 
nur unerwünscht, sondern einfach unbekannt.

Gruss Reinhard

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Reinhard Kern schrieb:
> Das hatte ich auch schon gefragt, aber m.n. fand das dann furchtbar
> lächerlich. Anscheinend ist genaueres Nachdenken und Hinterfragen nicht
> nur unerwünscht, sondern einfach unbekannt.

Mach dir keine Gedanken, hier kursieren eben unterschiedliche Ansichten. 
Manche Leute bringen ihre Ansichten schüchtern rüber, manche weniger 
schüchtern. ;-)

Und es ist ja wirklich so, dass der Weg, für diese Aufgabe einen 
ATtiny10 zu verwenden, eher ungewöhnlich ist, da hat m.n. schon Recht. 
Aber wenn die Größe eine Rolle spielt, dann ist SOT-23 sicher keine 
schlechte Wahl. Billig ist das Teil schließlich auch.

Ich hab das Programm mal ergänzt, hier die Änderungen:
1
*** fq_old.asm
2
--- fq.asm
3
***************
4
*** 1,5 ****
5
! ; fq 2013-11-23 20:00
6
! ; version 0.1
7
  ; target: ATtiny10
8
--- 1,5 ----
9
! ; fq 2013-12-15 10:30
10
! ; version 0.2
11
  ; target: ATtiny10
12
***************
13
*** 8,15 ****
14
  ;
15
  ; This program reads the frequency of the input signal at PB1
16
  ; and provides a similar signal at PB2 with frequency which
17
! ; has been increased by 25 %.
18
! ; operating range: 0.02 Hz .. ca. 10 kHz (resolution is 10 µs)
19
  ;
20
  .include "tn10def.inc"
21
  
22
--- 8,16 ----
23
  ;
24
  ; This program reads the frequency of the input signal at PB1
25
  ; and provides a similar signal at PB2 with frequency which
26
! ; has been increased by 33 % (if fq < 90 Hz).
27
! ; operating range: 0.02 Hz .. ca. 10 kHz (resolution is
28
! ; isrcpucycles/8MHz)
29
  ;
30
  .include "tn10def.inc"
31
  
32
***************
33
*** 28,33 ****
34
--- 29,37 ----
35
    .def cache1=r29  ;   0..0xfeffff
36
    .def cache2=r30  ;   0xffxxxx: marked as invalid
37
  
38
+ ; constant
39
+   .equ isrcpucycles= 100  ; maximum number of cycles of ISR
40
+ 
41
    rjmp init
42
  .org OC0Aaddr  ; timer ISR
43
  
44
***************
45
*** 40,48 ****
46
--- 44,57 ----
47
  
48
    ; write decreased input counter value to buffer
49
    ; we multiply by 0b0.11 (decimal 0.75)
50
+   ; if fq< 90 Hz
51
    mov cache0,intime0
52
    mov cache1,intime1
53
    mov cache2,intime2
54
+   cpi cache0,LOW(8000000/isrcpucycles)
55
+   ldi temp,HIGH(8000000/isrcpucycles)
56
+   cpc cache1,temp
57
+     brlo mul_end
58
    lsr cache2
59
    ror cache1
60
    ror cache0
61
***************
62
*** 52,57 ****
63
--- 61,67 ----
64
    lsr cache2
65
    ror cache1
66
    ror cache0
67
+   mul_end:
68
  
69
    ; initialize input counter
70
    clr intime0
71
***************
72
*** 160,166 ****
73
    ; timer initialization
74
    ldi temp,0
75
    out OCR0AH,temp
76
!   ldi temp,80-1  ; maximum number of cycles of ISR
77
    out OCR0AL,temp
78
    ldi temp,1<<OCIE0A
79
    out TIMSK0,temp
80
--- 170,176 ----
81
    ; timer initialization
82
    ldi temp,0
83
    out OCR0AH,temp
84
!   ldi temp,isrcpucycles-1
85
    out OCR0AL,temp
86
    ldi temp,1<<OCIE0A
87
    out TIMSK0,temp
Aber ungetestet, also Vorsicht! :-)

von m.n. (Gast)


Lesenswert?

Reinhard Kern schrieb:
> aber m.n. fand das dann furchtbar
> lächerlich.

Nein, so war das garnicht gemeint. Manche Aufgaben mögen einem 
Aussenstehenden so merkwürdig vorkommen, dass die Stirn Falten wirft.
Da ist es dann besser, mit einem Lächeln darüber hinweg zu sehen, als 
ernsthaft nachzufragen und es am Ende doch nicht zu verstehen.

Du weißt doch sicherlich aus dem Maschinenbau, dass dort teilweise 
Sachen so gemacht werden wie vor zig Jahren: Das machen wir immer so. Da 
hat es dann keinen Sinn, groß zu diskutieren, sondern man 'fügt' sich 
den Gegebenheiten und die Anwender sind glücklich.

von Jürgen F. (snipor)


Angehängte Dateien:

Lesenswert?

Markus Weber schrieb:
> Aber ungetestet, also Vorsicht! :-)

Ich habe es mal getestet, leider werden nun alle Frequenzen ungeändert 
1:1 durchgereicht.

Ich habe den Code nochmal angehängt, vielleicht ist ja noch ein Fehler 
drin.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Ich habe es mal getestet, leider werden nun alle Frequenzen ungeändert
> 1:1 durchgereicht.
>
> Ich habe den Code nochmal angehängt, vielleicht ist ja noch ein Fehler
> drin.

Ja, da ist ein Fehler drin, ich hab vergessen, die 90 Hz mit in die 
Berechnung reinzunehmen, sorry. :-)

Bitte ändere in beiden Fällen das "8000000/isrcpucycles" um zu 
"8000000/isrcpucycles/90".

von Jürgen F. (snipor)


Lesenswert?

Markus Weber schrieb:
> Ja, da ist ein Fehler drin, ich hab vergessen, die 90 Hz mit in die
> Berechnung reinzunehmen, sorry. :-)
>
> Bitte ändere in beiden Fällen das "8000000/isrcpucycles" um zu
> "8000000/isrcpucycles/90".

Hat leider noch immer keine Auswirkung auf das Ausgangssignal.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Markus Weber schrieb:
>> Bitte ändere in beiden Fällen das "8000000/isrcpucycles" um zu
>> "8000000/isrcpucycles/90".
>
> Hat leider noch immer keine Auswirkung auf das Ausgangssignal.

OK, Programmierung auf Raten. ;-)

Du redest von der Frequenz (90 Hz), das Programm aber misst die Zeit 
zwischen zwei Flankenwechseln. Und diese Zeit beträgt dann nicht 1/90 s, 
sondern nur die Hälfte davon, weil eine volle Schwingung ja zwei 
Flankenwechsel hat. Folglich:

8000000/isrcpucycles/90/2

von Jürgen F. (snipor)


Lesenswert?

Markus Weber schrieb:
> 8000000/isrcpucycles/90/2

Leider immer noch 1:1

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Markus Weber schrieb:
>> 8000000/isrcpucycles/90/2
>
> Leider immer noch 1:1

:-(

Dann müsste man nun Schritt für Schritt nach einem Fehler suchen. Zuerst 
z.B. statt "brlo mul_end" ein "nop" schreiben, um den Zustand des alten 
Programms zu simulieren usw.

von Jürgen F. (snipor)


Lesenswert?

Markus Weber schrieb:
> Dann müsste man nun Schritt für Schritt nach einem Fehler suchen. Zuerst
> z.B. statt "brlo mul_end" ein "nop" schreiben, um den Zustand des alten
> Programms zu simulieren usw.

Ja mit einem "nop" werden aus 100Hz wieder 134Hz.

Ich habe spaßeshalber hier mal 80 statt 100 probiert.

1
.equ isrcpucycles= 100

Ändert rein gar nichts.

: Bearbeitet durch User
von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Seltsam...

Das hier wäre noch eine Ecke ausführlicher, hätte gedacht, dass die 
Abfrage funktioniert. Vielleicht fällt jemand anderem noch etwas auf?
1
  mov cache0,intime0
2
  mov cache1,intime1
3
  mov cache2,intime2
4
  cpi cache0,LOW(8000000/isrcpucycles/90/2)
5
  ldi temp,HIGH(8000000/isrcpucycles/90/2)
6
  cpc cache1,temp
7
  cpc cache2,zero
8
  brlo mul_end

Läuft das Teil wirklich mit 8 MHz? Testhalber könntest du noch ein "/8" 
anhängen...

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Ha!

Das CLKPSR-Register ist geschützt - wie bei den anderen AVRs auch. Beim 
ATtiny10 jedoch über das CCP-Register.
1
 ; set CPU clock to 8 MHz
2
  ldi temp,0xd8
3
  out CCP,temp
4
  ldi temp,0b0000  ; CPU prescaler 1
5
  out CLKPSR,temp

von Jürgen F. (snipor)


Lesenswert?

Funktioniert nun wie gewünscht, super.

Vielen Dank für Deine Bemühungen :)

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Jürgen F. schrieb:
> Funktioniert nun wie gewünscht, super.

Freut mich. :-)

Durch so kleine Projekte lern ich selber auch immer wieder etwas.
Mit dem Zwerg ATtiny10 hab ich noch nicht viele Erfahrungen, aber er 
gefällt mir immer besser.

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.