Forum: Compiler & IDEs 2 Frequenzen einstellen und ausgeben +Display Anzeige


von Liloba (Gast)


Lesenswert?

Hallo,
ich hab ein Problem mit einer Augenscheinlich einfachen Aufgabe. Ich 
möchte gern zwei Frequenzen mit dem µC ausgeben lassen (ATMega8). Diese 
möchte ich auch einstellen können. Von 1 (besser 0Hz) bis 300 oder 
500Hz.

Wie ich es versucht hab:
Ich hab ein Display welches mir in Zeile1 Freuenz1 anzeigt und in Zeile2 
Frquenz2. Mit 6 Pins an Port-C stell ich die Frquenz ein. + und - 100, 
10 oder 1  ...
An dem PortB Pin 5 kann ich zwischen den beiden Kanälen zum einstellen 
wechseln. Ich berechne die Zeit Zwischen den Tackten und gebe dann ein 
kurzes HIGH auf PINB1 oder 2 aus.

Meine Probleme:
Ich kann keine PullUps einschalten sonnst kann ich nicht über 17Hz 
kommen da das auslesen lange dauert. --> ok mach ich das halt mit der 
Hardware. Gehts auch Eleganter?

Die Frequenzen werden nicht genau eingestellt, durch rundungsfehler, das 
kann man noch verbessern und nach messen aber damit muss ich so wohl 
leben. Oder?

Wenn ich auf dem MyAVR MK2 USB Bord die Verbindungen ziehe und auch das 
Display dran hab kann ich nicht mehr den µC Brennen. Er wird dann nicht 
mehr erkannt.

Alles im allen ist es es ne doofe baustelle und ich glaub das kann man 
auch eleganter lösen. Hab alle Freiheitsgrade ... kann mehr als einen µC 
Verwenden, kann, noch schalter hinzufügen oder was auch immer. Wie 
würdet ihr die Sache angehen.

Aufgabe: zwei Simulta verdenete Frquenzen einstellen und ausgeben. + 
Display.

Hat jemand eine Lösung?
Gruß Liloba

Hier mein Code:
1
/*
2
 * Display.c
3
 *
4
 * Created: 12.09.2011 15:49:44
5
 *  Author: *****
6
 */ 
7
#define F_CPU 16000000ul
8
#include <avr/io.h>
9
//#include <stdlib.h>
10
#include <string.h>
11
//#include <avr/interrupt.h>
12
#include "lcd.h"
13
//#include <util/delay.h>
14
15
typedef enum {FALSE,TRUE} logic;
16
17
void Start_Screen(void);
18
void upDate_Diplay(int Frequenz1, int Frequenz2);
19
void ToggelChannel(logic*ChannelToggle);
20
void delay_42P_8xXus(unsigned long Time);
21
void out_H(char PinNr);
22
void out_L(char PinNr);
23
void init(void);
24
25
unsigned long FrequenzUpDate(int*frequenz);
26
unsigned int calc_delay(int*frequenz);
27
28
void Start_Screen(void){
29
  lcd_clrscr();                      // clear display and home cursor
30
  lcd_puts("Hallo \n");      // put string to display (line 1) with linefeed
31
  lcd_puts("Line2");
32
  delay_42P_8xXus(55500);
33
}
34
unsigned long FrequenzUpDate(int*frequenz){  
35
  unsigned int delay=0;
36
    if ((PINC & (1<<PINC0)))  *frequenz=(*frequenz)+1;
37
    if ((PINC & (1<<PINC1)))  *frequenz=(*frequenz)-1;
38
    if ((PINC & (1<<PINC2)))  *frequenz=(*frequenz)+10;
39
    if ((PINC & (1<<PINC3)))  *frequenz=(*frequenz)-10;                  
40
      if ((PINC & (1<<PINC4)))  *frequenz=(*frequenz)+100;
41
    if ((PINC & (1<<PINC5)))  *frequenz=(*frequenz)-100;
42
    
43
    if (*frequenz<1)  //abfangen bei Bereichsüberscheitung der Frequenz
44
       {*frequenz=1;}    
45
    if (*frequenz>500)  *frequenz=500;  
46
      
47
    delay=calc_delay(frequenz);
48
  return delay;
49
}
50
51
void ToggelChannel(logic*ChannelToggle){  
52
  *ChannelToggle=~(*ChannelToggle);
53
  if (*ChannelToggle) 
54
    {lcd_gotoxy(10,1);lcd_puts("*");}
55
  else 
56
    {lcd_gotoxy(10,0);lcd_puts("*");}
57
  delay_42P_8xXus(44400); //33300 = ca. 300ms
58
  }
59
void out_H(char PinNr){
60
PORTB |= (1 << PinNr);
61
}
62
void out_L(char PinNr){
63
PORTB &= ~(1<<PinNr);
64
}
65
void dualOUT_H (char PinNr){
66
PORTB |= (11 << PinNr);
67
}
68
void dualOUT_L (char PinNr){
69
PORTB &= ~(11<<PinNr);
70
}
71
72
unsigned int calc_delay(int* frequenz){
73
  unsigned int delay;
74
  delay = ((10000000/(*frequenz))-133)/88;    //wegen der genauigkeit wird mit 0,1µs gerechnet
75
  return delay;
76
}
77
78
void delay_42P_8xXus(unsigned long Time){for (int i=0;i<=Time;i++){  }}
79
80
void upDate_Diplay(int Frequenz1, int Frequenz2){
81
  char lcd_freque_str0 [6];
82
  char lcd_freque_str1 [6];
83
  itoa((Frequenz1),lcd_freque_str0,10);
84
  itoa((Frequenz2),lcd_freque_str1,10);  
85
  lcd_clrscr();        // clear display and home cursor      
86
  lcd_gotoxy(11,0);lcd_puts(lcd_freque_str0);lcd_puts("Hz");
87
  lcd_gotoxy(11,1);lcd_puts(lcd_freque_str1);lcd_puts("Hz");    
88
  delay_42P_8xXus(16000);    //5550 = ca 50ms
89
}  
90
91
void init(void){
92
  //Eingaenge/Ausgaenge
93
  DDRC  = 0x00;    // Steuerung
94
  //PORTC = 0xff;    // Pull-Ups an
95
  DDRB  = 0b11011111;
96
  //PORTB = 0b00100000;
97
  lcd_init(LCD_DISP_ON);  // initialize display, cursor off
98
}
99
100
int main(void)
101
{
102
init();  
103
Start_Screen();
104
105
int Frequenz1=250, Frequenz2=250;
106
int Delay1_Rest, Delay2_Rest;
107
unsigned long TimeDelay1,TimeDelay2;
108
logic ChannelToggle = FALSE;
109
110
upDate_Diplay(Frequenz1, Frequenz2);
111
112
TimeDelay1 = FrequenzUpDate(&Frequenz1);
113
TimeDelay2 = FrequenzUpDate(&Frequenz2);
114
Delay1_Rest = TimeDelay1;
115
Delay2_Rest = TimeDelay2;
116
117
  while(1){
118
  // Die tasten abfrage erfolgt ohne pullUp da es sonnst zu lang-------------------
119
  // dauert und keine höheren frequenzen möglich sind.
120
  if ((PINB & (1<<PINB5)))
121
    ToggelChannel(&ChannelToggle); 
122
  //-------------------------------------------------------------------------------
123
  if ((PINC & (111111<<PINC0))){ 
124
      if (ChannelToggle) {
125
      TimeDelay2 = FrequenzUpDate(&Frequenz2);
126
      upDate_Diplay(Frequenz1, Frequenz2);
127
      }    
128
      else {
129
      TimeDelay1 = FrequenzUpDate(&Frequenz1);
130
      upDate_Diplay(Frequenz1, Frequenz2);
131
      }
132
   }
133
         
134
  //wer ist als nächstes dran?-----------------------------------------------------  
135
  if (TimeDelay1==TimeDelay2) {
136
    dualOUT_H(1);
137
    dualOUT_L(1);
138
    delay_42P_8xXus(TimeDelay1);
139
    Delay2_Rest=Delay2_Rest-TimeDelay1-2;  //dies sind funktionslose zeilen, sie dienen 
140
    Delay2_Rest=TimeDelay2;          //der Synchronität mit den andern if cases
141
  }
142
  else if (Delay1_Rest<Delay2_Rest) {  
143
    out_H(1);
144
    out_L(1);
145
    delay_42P_8xXus(Delay1_Rest);
146
    Delay2_Rest=Delay2_Rest-Delay1_Rest-2;  //die "-2" diehnt dem Ausgleich der 14µs vom outH zu outL
147
    Delay1_Rest=TimeDelay1;
148
  }
149
  else {
150
    out_H(2);
151
    out_L(2);
152
    delay_42P_8xXus(Delay2_Rest);
153
    Delay1_Rest=Delay1_Rest-Delay2_Rest-2;
154
    Delay2_Rest=TimeDelay2;
155
  }
156
  }    
157
}

von Karl H. (kbuchegg)


Lesenswert?

Liloba schrieb:

> Wie
> würdet ihr die Sache angehen.

Wie immer, wenn es darum geht irgendwelche 'extern abzugebende Timings' 
möglichst gut einzuhalten:

Mit einem Timer.



> delay = ((10000000/(*frequenz))-133)/88;

wenn du das so naiv dahinrechnest, darfst du dich über Rundungsfehler 
nicht wundern!

Formel umformen! Die Divisionen so weit wie möglich im Rechengang nach 
rechts schieben! Dabei aber aufpassen, dass nicht Zwischenergebnisse 
überzulaufen drohen.


Das hier
> void delay_42P_8xXus(unsigned long Time){for (int i=0;i<=Time;i++){  }}
ist Müll. Jeder halbwegs brauchbare Compiler, der in den letzten 30 
Jahren entwickelt wurde, wird dir die Funktion zu einer 0-Operation 
zusammenstreichen, sobald man ihm die Erlaubnis im Sinne von 
'Optimierung einschalten' dazu gibt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Jeder halbwegs brauchbare Compiler, der in den letzten 30
> Jahren entwickelt wurde,

Naja, GCC hat noch recht lange (bis Version 2.x, glaub' ich), explizite
Delay-Schleifen erkannt und sie nicht wegoptimiert in der Annahme, dass
der Entwickler sich was dabei gedacht hat.  Aber selbst dort war das
wohl dann mal irgendwann einer verbesserten Optimierungsstrategie
im Weg und ist auf den Müllhaufen der Compilergeschichte geflogen.

von Liloba (Gast)


Lesenswert?

Hallo ihr beiden,

nun ich wollte das mit zuerst mit einem Timer machen aber die 2(+1) die 
ich im ATmega8 zur Verfügung hab benutzen den selben gemeinsamen 
Zählwert oder nicht? ich mein ich kann ihnen sagen das sie bis 100 
zählen sollen und dann den einen bei 10 und den andern bei 40 schalten 
lassen. aber was ich brauch sind zwei die immer bei 1 schalten und 
unterschiedlich lang sind... außerdem ist der Bereich von 1 bis 500Hz 
nicht so leicht mit 8Bit zu machen. aber ich würde mich freuen wenn mir 
jemand zeigt wie es geht. ich kann auch einen anderen µC nehmen aber 
dann hab ich nicht mal mehr ein Experimentierboard.
Das mit dem optimieren der Rechnung ist gut. Das werde ich mal versuchen 
aber lieber währe es mir wenn ich die Timer nutzen kann ...
wie sollte da die Initialisierung aussehen?
Wie kann man den Timer abschalten wenn man auch 0 Hz also keine Ausgabe 
haben will?

ich hatte auch schon mal mit dem delay_µs gearbeitet aber dann wird der 
Code zu lang und geht nicht mehr in den Speicher. Darum diese Schleife. 
...

Gruß
Liloba

von Peter D. (peda)


Lesenswert?

Es reicht T1, der hat 2 Compare-Interrupts und 2 Pins, die zyklusgenau 
vom Comparewert gesetzt oder gelöscht werden können.
Damit kannst Du 2 verschiedene Frequenzen erzeugen.
Und im Interrupt zählst Du die höherwertigen Byte(s) über den 16Bit des 
Timers.


Peter

von Peter D. (peda)


Lesenswert?

Liloba schrieb:
> (besser 0Hz)

0Hz geht nicht, dann müßtest Du unendlich lange warten.
Denk Dir eine sinnvolle untere Grenze aus.
Die Schrittweite kann natürlich kleiner sein.


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:
> ich hatte auch schon mal mit dem delay_µs gearbeitet aber dann wird der
> Code zu lang und geht nicht mehr in den Speicher.

Weil du eine der Randbedingungen der delay-Routinen missachtet hast:
sie funktionieren nur mit einem zur Compilezeit konstanten
Argument.

Anyway, delays sind keine sinnvolle Lösung zur Erzeugung einer halbwegs
genau einzustellenden Frequenz, das geht nur mit Hardware, also im
Rahmen eines Controllers mit einem Timer.

Wenn dein Controller davon wirklich nicht die für die Lösung der
Aufgabe notwendige Anzahl hat, dann solltest du dich nach einem anderen
umsehen.  Allerdings glaube ich das im vorliegenden Fall nicht.  Mir
ist deine Aufgabenstellung jedoch zu konfus formuliert, als dass ich
mir jetzt freiwillig eine Lösung für dein Problem ausdenken würde,
sorry.

von Liloba (Gast)


Lesenswert?

Hallo Jörg,
die aufgabe: mit einem ATmega8 zwei Frequenzen ausgeben. Einstellbar von 
1 bis 300Hz. Dauer des HighLevels ca 4-60µs.

Hallo Peter,
ich kann dem was du schreibst nicht folgen. Da ich zu wenig Anung hab...
was bedeutet Compare-Interrupts?
Sind es wirklich 2 Frequenzen die man nach deiner Methode einstellen 
kann oder sind es zwei Leistungsmodulationen?

Kann Einer von euch mal ein paar Zeilen Code hier zum Besten geben dann 
kann ich das mit dem Timer Testen.

Danke für die Geduld.
Liloba

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:
> mit einem ATmega8 zwei Frequenzen ausgeben. Einstellbar von
> 1 bis 300Hz. Dauer des HighLevels ca 4-60µs.

Klingt wie 'ne Hausaufgabe ... da wollte wohl jemand, dass du dich
mit dem Datenblatt eingehend beschäftigst.

> Da ich zu wenig Anung hab...
> was bedeutet Compare-Interrupts?

Schau dir doch einfach mal die Beschreibung der compare match unit
im Kapitel zu den Timern im Datenblatt an.  Du hast 3 Timer im
ATmega8, also kannst du 3 voneinander unabhängige Frequenzen damit
erzeugen.  Über irgendwelche Auflösungs- und Genauigkeitsforderungen
schreibst du nichts, insofern genügen für die Aufgabe durchaus auch
die 8-bit-Timer.

Und ja, all diese Parameter (sowohl Frequenz auch als Impulsbreite)
kann man dabei (mit endlicher Genauigkeit natürlich) voneinander
unabhängig rein durch die Timerhardware erzeugen lassen.  Damit ist
man vollständig unabhängig vom Zeitverhalten irgendwelcher Interrupts
oder dergleichen, und die Software kann sich rein auf die Bedienung
der Timerhardware konzentrieren.

von Karl H. (kbuchegg)


Lesenswert?


von Liloba (Gast)


Lesenswert?

Hallo schön das ich noch immer Infos bekomme! Ich versuch mich jetzt 
hier wirklich durchzubeißen und es handelt sich nicht um eine 
Hausaufgabe! Bin eigentlich Themen fremd. Danke für den Link!

zu Euren und meinen Fragen:

Die Auflösung soll 1Hz betragen ich dachte das Inkrement sein klar da 
die Einstellungen in 1Hz Schritten vorgenommen werden. - bitte um 
Entschuldigung. Die Genauigkeit ist mir recht egal wenn 300Hz nur 295 
oder aber auch 305Hz sind reicht das (1,5%).

Nun ehe ich aus diesen Infos des Datenblattes Fragen zusammenschuster 
hab ich mal versucht was zu schreiben. Aber es geht nur eine LED an. 
(Ich hab an Port B Pin 0, 1 und 2 je eine LED angeschlossen)

Kann mir jemand sagen wie ich während der Laufzeit die Timer werte 
ändere kann und welche es sind?
Ich ging jetzt davon aus das TCNT1/0 die Endwerte der Timer sind. Und 
TCCR1A/B die dazugehörigen Compare Wert?

Ist das Prinzip mit den Interruptus so richtig und sollten dies so 
Funktionieren?
1
/*
2
 * Frequenz.c
3
 *
4
 * Created: 27.09.2011 11:43:22
5
 *  Author: ******
6
 */ 
7
8
#include <avr/io.h>
9
#include <avr/interrupt.h>
10
11
void Init(void){
12
  DDRB = 0xff;      //PortB ist Ausgang
13
14
  //Timer Settings
15
  TCNT1 = 0b11111111;    //The Timer/Counter (TCNT1),
16
  TCNT0 = 0b11111111;
17
  
18
  TIMSK = (1<<OCIE1A)|(1<<OCIE1B);  //Output Compare A/B Match Interrupt Enable
19
  TIMSK = (1<<TOV0)  |(1<<TOV1);    //Timer Over Flow Interrupt Enable
20
  
21
  //Brauch man diese Einstellungen ?
22
  TCCR1A = (1<<COM1A1) | (1<<WGM11);              //PWM, Phase Correct, 9-Bit
23
  TCCR1B = (1<<WGM13) | (1<<WGM12)  | (1<<CS11);// | (1<<CS10);  //Teiler setzten      
24
  ICR1  = 0b00111111;    //TOP Wert //Ist der hier erforderlich da doch schon oben TCNT1/0 diesen wert darstellen
25
  
26
  //Output Compare Registers (OCR1A/B),
27
  OCR1A = 0b00011111;    //verglichswert für Timer (Abschaltungszeitpunkt)
28
  OCR1B = 0b00011111;  
29
  
30
  sei();
31
}
32
33
34
ISR(TIMER1_COMPA_vect){  }
35
ISR(TIMER1_COMPB_vect){}
36
37
ISR(TIMER1_OVF_vect){}
38
ISR(TIMER0_OVF_vect){}
39
  
40
41
42
int main(void)
43
{
44
  Init();
45
    while(1)
46
    {
47
        //TODO:: Please write your application code 
48
    }
49
}

von Karl H. (kbuchegg)


Lesenswert?

>   //Timer Settings
>  TCNT1 = 0b11111111;    //The Timer/Counter (TCNT1),
>  TCNT0 = 0b11111111;

Die TCNT Register gehen dich herzlich wenig an. Das sind die Register in 
denen der Timer zählt.


>  ICR1  = 0b00111111;    //TOP Wert //Ist der hier erforderlich da ...
>
>  OCR1A = 0b00011111;    //verglichswert für Timer (Abschaltungszeitpunkt)
>  OCR1B = 0b00011111;

Noch ungünstigere Schreibweisen als die binäre Schreibweisen für Zahlen 
sind dir nicht eingefallen?

Schreib doch einfach

   ICR1 = 63;

bzw

  OCR1A = 31;
  OCR1B = 31;

dann kann man das auch lesen.

Den Link hast du dir angesehen?
Mein Rat: bring erst mal mittels Timer EINE LED zum blinken. Zuerst 1Hz, 
dann 2Hz, dann 3Hz. Dann wirst du auch verstehen, wie die Dinge 
zusammenhängen und wenn du für diese kleinen Frequenzen die jeweiligen 
Registerwerte berechnen musst.

Du machst den Fehler schlechthin, den Anfänger machen. Sie haben nur 
Augen für ihr endgültiges Projekt und können noch nicht (für erste Tests 
und um ein Teilgebiet das sie bei ihrem Endprojekt brauchen werden) 
zunächst unwichtiges weglassen. Für dich ist momentan unwichtig: alles 
was mit Einstellung zu tun hat, alles was mit Ausgabe zu tun hat, alles 
was mit verändern der Frequenz zu tun hat. Für dich ist JETZT erst mal 
wichtig, dass du mit einem Timer überhaupt eine Frequenz zustande 
bringst und zwar so, dass du die Frequenz unter Kontrolle hast 
(Berechnung auf Papier und Bleistift) und dass du das einfach 
kontrollieren kannst. Daher die LED und 1Hz.

von Liloba (Gast)


Lesenswert?

Hi,
ich hab jetzt was versucht was sich an den link Text anlehnt! Aber es 
geht nicht! Ich kann keinen unterschied mehr sehen aber der interrupt 
geht nicht.
1
/*
2
 * Frequenz.c
3
 *
4
 * Created: 27.09.2011 11:43:22
5
 *  Author: ******
6
 */ 
7
8
#define F_CPU 4000000UL
9
#include <avr/io.h>
10
#include <avr/interrupt.h>
11
12
uint8_t swTeiler = 0;
13
14
void Init(void){
15
  DDRB = 0xff;      //PortB ist Ausgang
16
17
  //Timer Settings  
18
  TIMSK = (1<<OCIE1A);//Output Compare A Match Interrupt Enable
19
  OCR1A = 250-1;    //verglichswert für Timer, im CTC wird hier die oberGrenze eingestellt
20
  TCCR1A = 1<<WGM12;  //Modus CTC ober Grenze in OCR1A
21
  TCCR1A = 1<<CS01;  //clkI/O/8 (From prescaler)  //TCCR1A = (1<<CS01) | (1<<CS00);      //Teiler auf 64 gesetzt            
22
  sei();
23
}
24
25
ISR(TIMER1_COMPA_vect){
26
    swTeiler++;
27
    if( swTeiler == 2 ) {
28
    swTeiler = 0;
29
    PORTB = PORTB ^ 0xFF;
30
    }
31
}
32
33
/*
34
ISR(TIMER1_COMPB_vect){
35
}
36
ISR(TIMER1_OVF_vect){
37
}
38
ISR(TIMER0_OVF_vect){
39
}
40
*/
41
42
int main(void)
43
{
44
  Init();
45
    while(1)
46
    {
47
48
    }
49
}

von Karl H. (kbuchegg)


Lesenswert?

Liloba schrieb:
> Hi,
> ich hab jetzt was versucht was sich an den link Text anlehnt! Aber es
> geht nicht! Ich kann keinen unterschied mehr sehen aber der interrupt
> geht nicht.


Du hast keinen sei()

von Liloba (Gast)


Lesenswert?

Hallo Karl Heinz Buchegger,
ich hab es selber raus bekommen jetzt frag ich mich aber wofür TCCR1A 
bzw TCCR1B sind.
In B kann man scheinbar den Timer Modi und den Prescaler einstellen und 
was macht man mit TCCR1A ?
Danke

von Karl H. (kbuchegg)


Lesenswert?

Liloba schrieb:
> Hallo Karl Heinz Buchegger,
> ich hab es selber raus bekommen jetzt frag ich mich aber wofür TCCR1A
> bzw TCCR1B sind.
> In B kann man scheinbar den Timer Modi und den Prescaler einstellen und
> was macht man mit TCCR1A ?

Schau ins Datenblatt.

Beides zusammen sind die Konfigurationsregister des Timers.
Da kann man noch jede Menge mehr einstellen.

An dieser Stelle kann ich dir nur raten: Schau ins Datenblatt. Das ist 
deine Bibel. Ohne geht gar nichts.

Der für die praktische Arbeit wichtigste Teil ist bei jeder 
Hadrware-Komponente immer der letzte Abschnitt im jeweiligen Kapitel 
"Register Summary". Dort sind alle Konfigurationsregister aufgeführt, 
zusammen mit allen Bits und was sie bewirken. Die Abschnitte davor sind 
immer die ausführliche Erläuterung, wie die Funktionalität funktioniert. 
Wenn du also in der Register Summary etwas nicht verstehst, dann findet 
sich in den Abschnitten davor die Erklärung dazu.

Aber ohne Datenblatt bist du genauso aufgeschmissen, wie du es bei der 
Progammierung eines Videorekorders ohne Handbuch bist.

von dr.prof.schlau (Gast)


Lesenswert?

Was zum Teufel ist ein Videorekorder??  :-))

von Liloba (Gast)


Lesenswert?

Hallo, Ich hab mich jetzt die letzten stunden mit diesen Timer befasst.
Ich glaub das ein CTC Mode mit nur 8 Bit gut für mein vorhaben ist darum 
wollte ich den Timer2 für den Anfang verwenden. (Bei den anderen hab ich 
das eine oder andern hinbekommen)
Um erstmal was zu Testen dacht eich an eine normale PWM.
Der Compare-Wert in OCR2 steht auf 50 und soll den TIMER2_COMP_vect 
Interrupt auslösen welche für kurze zeit (11,1µs) alle Pins an PortB auf 
1 setzt. Der Pin3 sollte davon nicht betroffen sein da er von der PWM 
gesteuert wird.

Kurz um: Ich dachte ich hätte es jetzt begriffen aber es geht so nicht.
Was ist jetzt der Fehler?

PS: Das Datenblatt bringt mir hier jetzt nichts. Aber es war bis hierher 
sehr Sinnvoll und Nützlich.

Gruß Liloba
1
void Init(void){
2
  DDRB = 0xff;      //PortB ist Ausgang
3
  
4
  //Timer2 Settings
5
  TIMSK = (1<<TOV2)|(1<<TOIE2);
6
  OCR2 = 50;      
7
  TCCR2 = 1<<CS00;
8
  TCCR2 = (1<<WGM20);
9
  //TCCR2 = (1<<WGM21);  //Modus CTC Obergrenze in OCR2
10
  sei();
11
}
12
13
ISR(TIMER2_COMP_vect){
14
PORTB = PORTB ^ 0xFF;
15
PORTB = PORTB ^ 0xFF;
16
}
17
ISR(TIMER2_OVF_vect){
18
//PORTB = PORTB ^ 0xFF;
19
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:

> Der Compare-Wert in OCR2 steht auf 50 und soll den TIMER2_COMP_vect
> Interrupt auslösen welche für kurze zeit (11,1µs) alle Pins an PortB auf
> 1 setzt.

Woraus schlussfolgerst du, dass dies gerade 11,1 µs lang wäre?

Pins setzen und wieder löschen wäre übrigens:
1
  PORTB = 0xff;
2
  PORTB = 0;

Das müsste einen Impuls ergeben, der (bei eingeschalteter Optimierung)
genau einen CPU-Takt lang ist, also 1 µs beim Default-Takt.

Du toggelst sie stattdessen, was ein wenig langsamer ist, weil du
die CPU zwingst, jeweils die alten Werte erstmal einzulesen.

>   TCCR2 = 1<<CS00;
>   TCCR2 = (1<<WGM20);

Das macht die CS00-Einstellung der vorherigen Zeile wieder zunichte,
damit hat dein Timer keinen Takt.  Entweder so:
1
  TCCR2 = 1<<CS00;
2
  TCCR2 |= 1<<WGM20;

besser jedoch gleich in einer Zeile, denn es gibt keinen Grund, das
aufzutrennen:
1
  TCCR2 = (1<<CS00) | (1<<WGM20);

von Uwe (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> TCCR2 = (1<<CS00) | (1<<WGM20);

ich habe noch eine kleine Korrektur:
1
TCCR2 = (1<<CS20) | (1<<WGM20);

CS00 könnte mal != C20 werden.

von Liloba (Gast)


Lesenswert?

Hi,
die 11.1µs hab ich gemessen mit dem Ossi.
das toggeln war nur zur Anschauung und sollte nicht die Endvariante 
sein. Ich versuch einfach nur die beiden Interruptus zu nutzen ... aber 
es geht nicht.
Wie kann ich denn die Optimierung eingeschaltet? Ich nutze Studio5 ...
ist noch ein andere Schnitzer im Code so das der Timer nicht arbeite?

Gruß
Liloba

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:

> die 11.1µs hab ich gemessen mit dem Ossi.

Dann hast du keine Optimierung eingeschaltet.  So eine Operation
sollte schneller gehen.

Hat übrigens nichts mit den östlichen Deutschen zu tun ;-), sondern das
Teil heißt "Oszi(lloskop)".

> Ich versuch einfach nur die beiden Interruptus zu nutzen ... aber
> es geht nicht.

Wofür willst du denn die Interrupts noch haben?  Für mehr als eine
Demonstration brauchst du die nicht, denn die PWM (und damit die
Ausgabe der Impulse) wird komplett von der Timer-Hardware
erledigt — und das ist das Beste, was dir in dieser Hinsicht
passieren kann.  Beim Erreichen des OCRx-Wertes wird der Ausgang
in die eine Lage gesetzt, beim Erreichen des Zählerüberlaufs wird
er wieder rückgesetzt (zum Beispiel; dies wäre ein "fast PWM mode").

> Wie kann ich denn die Optimierung eingeschaltet? Ich nutze Studio5 ...

Keine Ahnung, ich nicht. :)

> ist noch ein andere Schnitzer im Code so das der Timer nicht arbeite?

Hast du das kaputte TCCR2 denn korrigiert?

von Liloba (Gast)


Lesenswert?

Warum wir kein Compare Interrupt ausgelöst?

von Karl H. (kbuchegg)


Lesenswert?

Liloba

Bitte gewöhn dir an:
Wenn du Fragen hast, zeige deinen Code. Und zwar alles!

Wenn in deinem Code Fehler moniert wurden und du daher deinen Code 
geändert hast, zeig bei weiteren Fragen wieder deinen Code.

Auf dieser Seite deines Monitors sehen wir dein Programm nicht in seiner 
jetzigen Form und wir wissen auch nicht welche Änderungen du alle 
gemacht hast.

Die Forensoftware macht dir das einfach. Du brauchst nur auf "Datei 
auswählen" bei Dateianhang klicken und dein C-File, so wie es ist, 
auswählen. Das ist für dich kaum Arbeit und hier muss keiner im Nebel 
stochern und raten.

von Peter D. (peda)


Lesenswert?

dr.prof.schlau schrieb:
> Was zum Teufel ist ein Videorekorder??  :-))

Ein Gerät, um die Privaten ansehen zu können, ohne von der Werbung zu 
verblöden (Timeshift-Funktion).


Peter

von Liloba (Gast)


Angehängte Dateien:

Lesenswert?

Hi,

also hier mein neuer Code ... ;)

ich habe gehofft das ich 2 Timer genau gleich konfigurieren kann aber 
seht selber.
Timer1 Mode 1
Timer2 Mode 1

Damit die Interruptus sich nicht in die quere kommen hab ich die 
Timerzeiten um 127 Zähler versetzt.

Komplett gleich bekomme ich die nicht.

Das Problem besteht noch immer. Wie kann ich 2 Frequenzen in 1Hz 
schritten von 1 bis 300Hz ausgeben? Das Gittern sollte nur wenige (<30) 
µs sein.

Wie kann ich die Code-Optimierung einschalten?

Gruß Liloba

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:

> Das Problem besteht noch immer.

Ja.  Weil du immer noch nicht begriffen hast, dass man derartige Dinge
von der Timer-Hardware erledigen lässt und nicht irgendwo in den
Interrupt-Routinen.

Bitte versuche als erstes zu verstehen, wie der Timer eine PWM
erzeugt.  Du brauchst dafür keinen Interrupt.  Für eine konstante
Frequenz (als ersten Schritt) kannst du nach dem Konfigurieren der
Ports und der Timer-Hardware die CPU schlafen legen (aber natürlich
nicht den IO-clock, also sleep mode "idle"), die hat dann nichts
mehr zu tun.

Dann jittert da auch rein gar nichts.

Wenn du deine beiden Timer dann soweit hast, dass sie jeder ihr
PWM-Signal ausgeben, dann denkst du das nächste Mal drüber nach,
wie du die Frequenz eines Timers änderst.  Bis dahin ist dieses
Thema erstmal tabu.

von Liloba (Gast)


Lesenswert?

Guten Morgen,

also ich hab mir auf die Zunge gebissen und weiter gemacht! Danke, dass 
ihr mir noch immer schreibt! ;)

also mein neuer Code:
1
#include <avr/io.h>
2
3
void Init(void);
4
5
int main(void)
6
{
7
  DDRB = 0xff;            //PortB ist Ausgang
8
  TCCR1A = (1<<COM1A1) | (1<<WGM11);        
9
  TCCR1B = (1<<WGM13) | (1<<WGM12)  | (1<<CS11);    
10
  ICR1  = 123;  //TOP Wert
11
  OCR1A = 0;    //Verglichswert
12
  
13
  do{ }  while(1);
14
}

Die kleinste Frequenz liegt hier bei ca. 2Hz. mit ICR1=65535.
Mit dem Prescale kann ich da noch was machen aber dann wird der Puls 
länger, aber bis 64µs ist schon noch OK.

Wie kann ich jetzt aber die zweite Frequenz erzeugen wenn ich keinen 16 
Bit Timer mehr habe. Wo doch schon 65535 grenzwertig ist.

Das mit dem idle hab ich nicht überlesen aber ich brauch die CPU später 
noch für andere Dinge.

Gruß
Liloba

von Karl H. (kbuchegg)


Lesenswert?

Liloba schrieb:

> Die kleinste Frequenz liegt hier bei ca. 2Hz. mit ICR1=65535.
> Mit dem Prescale kann ich da noch was machen aber dann wird der Puls
> länger

Jetzt hast du es.

> aber bis 64µs ist schon noch OK.

Uff

> Wie kann ich jetzt aber die zweite Frequenz erzeugen wenn ich keinen 16
> Bit Timer mehr habe. Wo doch schon 65535 grenzwertig ist.

Das Problem:
In deinem Eröffnungsposting war von einer Pulslänge noch nicht die Rede.
Als du 300Hz gesagt hast, ist wohl jeder davon ausgegangen, dass es sich 
da um eine symetrische Rechteckschwingung handelt. Das wäre kein Problem 
gewesen.

Ich frag mich gerade, ob du nicht die Pulslänge mit einem extern 
flankengetriggerten Monoflop machen solltest. Einen kurzen Puls kriegst 
du mit dem Mega8 hin. Aber 2 wird schwer. Zumindest wüsste ich jetzt auf 
Anhieb nicht, wie da das mit einem 8 Bit Timer machen könntest.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> Zumindest wüsste ich jetzt auf
> Anhieb nicht, wie da das mit einem 8 Bit Timer machen könntest.

Ja, ich auch nicht so recht.  Naja, man hat natürlich alle Zeit der
Welt, den Timer zwischen normalem Zählen (für einen Umlauf) und
PWM-Modus (nach dem Overflow) umzuschalten ... aber optimal fände
ich das nicht.

Eine Chance, auf einen moderneren Controller umzuschwenken (insbe-
sondere einen, der zwei 16-bit-Timer hat), gibt's wohl nicht, oder?

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:
> Karl Heinz Buchegger schrieb:
>> Zumindest wüsste ich jetzt auf
>> Anhieb nicht, wie da das mit einem 8 Bit Timer machen könntest.
>
> Ja, ich auch nicht so recht.  Naja, man hat natürlich alle Zeit der
> Welt, den Timer zwischen normalem Zählen (für einen Umlauf) und
> PWM-Modus (nach dem Overflow) umzuschalten ... aber optimal fände
> ich das nicht.

Was ist schon optimal?

Ich finde die Idee jetzt gar nicht mal so schlecht. PeDa macht in seiner 
genauen Sekunde im Grunde ja auch nichts anderes. Nur das hier halt ein 
Modus-Wechsel des Timers noch mit inkludiert ist. Ich denke, das wäre 
machbar, zumal die zu erzeugenden Frequenzen ja jetzt so hoch auch 
wieder nicht sind. Interruptmässig sollte da noch alles im grünen 
Bereich sein. Ohne ISR wirds sowieso nicht gehen, weil man mit dem 
Prescaler nicht weit genug hochkommt für die kleinen Frequenzen.

Wurde das eigentlich schon mal gefragt oder gabs dazu eine Erklärung? 
Warum eigentlich so kurze Pulse? Ich finde das schon ungewöhnlich: 150Hz 
mit einer Pulslänge im µs Bereich.

von Liloba (Gast)


Lesenswert?

hallo,
den kurzen Impuls brauch ich für einen andere aperatur welche nur 2µs 
bis 60µs (da würde ich mit 64µ schon drüber kommen) verträgt.

Weil ich ja schon wusste das es so nicht geht hab ich doch die Sache mit 
dem Interrupts versucht. Das ging mit dem Timer2 recht gut und auch 
jitter stabil.
1
ISR(TIMER2_COMP_vect){
2
  if( swTeiler2 >= 0 ) {
3
  PORTB = 1<<PB2;
4
  TCNT2 = 0;    
5
    swTeiler2 = 0;
6
    PORTB &= ~(1<<PB2);
7
  }
8
  else swTeiler2++;
9
}
Mit dem Code sollte der µC nicht viel zu tun haben und jetzt da der eine 
Takt vom Timer gemacht wird sollten die Interrupts auch nicht zum 
jittern führen. Oder?

Ich könnte auch andere µC verwenden. Dieser hat sich nur angeboten da er 
auf dem Einsteiger Board sitzt. Ich könnte auch 2 µC verwenden nur weiß 
ich nicht wie ich die Infos welche Frequenz einstellt werden soll von 
einem µC zu dem anderen bekomme.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:

> Mit dem Code sollte der µC nicht viel zu tun haben und jetzt da der eine
> Takt vom Timer gemacht wird sollten die Interrupts auch nicht zum
> jittern führen. Oder?

Ein wenig Jitter hast du trotzdem, da die Interruptannahmezeiten nicht
völlig konstant sind.  Ein Programmfluss kann immer nur unterbrochen
werden, nachdem ein Befehl vollständig abgearbeitet ist, und die
Befehle können unterschiedlich lange für die Abarbeitung benötigen.

Außerdem wird es spätestens dann brenzlig, wenn du für dein Bedien-
programm auch noch Interrupts brauchst (und sei es nur für einen
weiteren Timer, bspw. für eine Tastaturentprellung).

Ich würde dann eher die skizzierte Hardwarelösung implementieren.
Die braucht zwar auch Interrupts, aber das Interrupt-Timing hat
(sofern die Interrupts überhaupt brauchbar schnell bedient werden)
dann keinen Einfluss mehr auf die Genauigkeit der Impulsgenerierung.

Nochmal die Gedanken:

. du lässt den Timer "eine Runde" im CTC-Modus laufen; beim
  Erreichen des compare match wird er einerseits durch die Hardware
  neu gestartet, andererseits wird ein Interrupt ausgelöst

. die ISR programmiert den laufenden Timer um auf PWM-Betrieb,
  die Zählweite wird damit für diesen Umlauf 256 (8 bit), das
  OCR2 wird umprogrammiert, sodass es kurz vor Erreichen des
  Überlaufs den nötigen kurzen Impuls generiert; beim Überlauf
  wird dann ein Overflow-Interrupt ausgelöst

. die ISR für den Overflow programmiert alles wieder auf den
  CTC-Modus zurück.

Damit ergibt sich die Frequenz als f_IO ÷ prescaler ÷ (OCR2 + 256).

Prinzipiell sind auch mehrere Umläufe im Normalmodus denkbar,
bevor man auf PWM schaltet.  Damit sollte man selbst bei etwas
kleineren Prescaler-Werten (zur Erreichung kurzer Impulse im
PWM-Modus) noch auf niedrige Frequenzen kommen.

> Ich könnte auch andere µC verwenden.

Das wäre zumindest meine Vorzugsvariante.  Ein ATmega1284P hat
zwei 16-bit-Timer, oder aber halt die "Klassiker"-Linie ATmega128
bzw. der modernere Nachfolger ATmega1281.

von Stefan E. (sternst)


Lesenswert?

Ich würde es noch etwas anders machen:
Timer im PWM-Modus laufen lassen, mit ICR als Top. Duty-Cycle 
entsprechend der gewünschten Pulslänge, Frequenz ein ganzzahliger Teiler 
der gewünschten Frequenzen. Im Interrupt dann Mitzählen für die gewählte 
Frequenz und den OC-Pin nur für einen PWM-Zyklus lang mit dem Timer 
verbinden.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan Ernst schrieb:
> Timer im PWM-Modus laufen lassen, mit ICR als Top.

Kann der Timer 2 im ATmega8 nicht.

von Stefan E. (sternst)


Lesenswert?

Jörg Wunsch schrieb:
> Stefan Ernst schrieb:
>> Timer im PWM-Modus laufen lassen, mit ICR als Top.
>
> Kann der Timer 2 im ATmega8 nicht.

Man kann mit der beschriebenen Methode doch beide Signale mit Timer 1 
machen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan Ernst schrieb:
> Man kann mit der beschriebenen Methode doch beide Signale mit Timer 1
> machen.

Ich verstehe nicht ganz, wie du deren Frequenzen dann voneinander
unabhängig in 1-Hz-Schritten zwischen 1 Hz und 300 Hz einstellen
willst.

von Liloba (Gast)


Angehängte Dateien:

Lesenswert?

ich glaub ich hab so was gemacht wie Stefan Ernst meint.

aber zusammen mit dem Display kommen die Probleme die oben beschrieben 
werden ... der µC ist beschäftigt der Interrupt kommt und dann wandert 
der Displaytext. Oder ligt es an was anderem?

der ATmega1284P scheint ganz gut zu sein ... ich hab zur Display 
Ansteuerung von einem Kollegen eine lcd.c unc lcd.h bekommen. 
wahrscheinlich muss ich da mit dem andern µc Änderungen vornehmen oder?

das Display ist das "Displaytech162". Denn da jetzt die Zeichen 
stillstehen würde mir es reichen! Sicher die Zeiteinstellungen müsste 
ich dann noch machen.

Gruß und danke
Liloba

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:
> ich glaub ich hab so was gemacht wie Stefan Ernst meint.
>
> aber zusammen mit dem Display kommen die Probleme die oben beschrieben
> werden ... der µC ist beschäftigt der Interrupt kommt und dann wandert
> der Displaytext. Oder ligt es an was anderem?

An lcd.c. ;-)

Das hier:
1
  if ((PINC & (111111<<PINC0))){
wird wohl nicht das tun, was du willst.  111111 ist eine ziemlich
große Zahl.  Vermutlich meinst du 0b111111, aber dann kannst du
das auch gleich als 0x3F hinschreiben.  Noch besser, sowas packt
man in ein #define obendrüber und gibt ihm damit einen sinnvollen
Namen:
1
#define BUTTONMASK 0x3f /* mask of button input pins on port C */
2
...
3
  if ((PINC & BUTTONMASK) != 0) {
4
    ...

> wahrscheinlich muss ich da mit dem andern µc Änderungen vornehmen oder?

Irgendwo vermutlich schon, hängt davon ab, an welchen Portpins das
Display hängt.

> Denn da jetzt die Zeichen
> stillstehen würde mir es reichen!

Dazu müsste man erstmal wissen, warum sie dies nicht tun.

von Karl H. (kbuchegg)


Lesenswert?

Liloba schrieb:
> ich glaub ich hab so was gemacht wie Stefan Ernst meint.
>
> aber zusammen mit dem Display kommen die Probleme die oben beschrieben
> werden ... der µC ist beschäftigt der Interrupt kommt und dann wandert
> der Displaytext.

?
Wie muss man sich das vorstellen?

Das hier

void upDate_Diplay(int Frequenz1, int Frequenz2){
  char lcd_freque_str0 [6];
  char lcd_freque_str1 [6];
  itoa((Frequenz1),lcd_freque_str0,10);
  itoa((Frequenz2),lcd_freque_str1,10);
  lcd_clrscr();
  lcd_gotoxy(11,0);lcd_puts(lcd_freque_str0);lcd_puts("Hz");
  lcd_gotoxy(11,1);lcd_puts(lcd_freque_str1);lcd_puts("Hz");
}

ist nicht so prickelnd.

Durch den lcd_clrscr wird dir die Anzeige flimmern, wenn upDate_Diplay 
in schneller Folge aufgerufen wird.
Zumindest mich würde es auch enorm stören, wenn die Zahl ständig hin und 
her wandert, nur eil ich von 99 auf 100 weitergeschaltet habe. Besser 
ist es wenn man
* die Anzeige so einrichtet, dass alle Teile immer an der gleichen
  Stelle auftauchen und man ganz einfach überschreiben kann anstelle
  dass man das LCD dauernd löschen muss. Wird ein Text mit dem gleichen
  Text überschrieben, merkt das kein Mensch. Wird aber das LCD
  gelöscht, so hat man kurzzeitig ein leeres LCD vor sich, auf welches
  dann wieder neue Ausgaben kommmen. Das ist nicht zu übersehen
  und wird, wenn es oft genug in der Sekunde passiert als Flimmern
  wahrgenommen.
* Zahlenausgaben so einrichtet, dass die Einerstelle immer an der
  gleichen Anzeigeposition auftaucht. Das ergibt ein angenehmeres
  Ablesen, als wie wenn man das Gefühl hat, die Zahl wandert einem
  während des Ablesens ständig links und rechts davon.

von Stefan E. (sternst)


Lesenswert?

Jörg Wunsch schrieb:
> Stefan Ernst schrieb:
>> Man kann mit der beschriebenen Methode doch beide Signale mit Timer 1
>> machen.
>
> Ich verstehe nicht ganz, wie du deren Frequenzen dann voneinander
> unabhängig in 1-Hz-Schritten zwischen 1 Hz und 300 Hz einstellen
> willst.

Ja, Denkfehler von mir. :-(
Ich dachte eigentlich daran die PWM-Frequenz entsprechend hoch 
anzusetzen, und dann mit zwei Zählern im Interrupt zu arbeiten. Aber das 
gemeinsame Vielfache der 300 möglichen Frequenzen ist halt doch verdammt 
hoch. ;-)

von Liloba (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> die Anzeige so einrichtet, dass alle Teile immer an der gleichen
>   Stelle auftauchen und man ganz einfach überschreiben kann anstelle
>   dass man das LCD dauernd löschen muss.

Das eigentliche schreiben passiet auch immer an der selben Stelle. Aber 
die Dargestellten Frequenzen (zahlen) sind halt mal einstellig und mal 3 
stellig, ... beim normalen überschreiben werden immer nur die neuen 
Digits überschrieben und so bleiben die Nullen der 100 stehen auch wenn 
nur noch 9Hz eingestellt sind... durch die Angehängte Einheit "Hz" 
werden dann die Nullen überschreiben aber dann Steht 9HzHz auf dem 
Display.
ich Müsste die String länge die geschrieben werden soll Definieren. Oder 
nur Teilbereiche des nachträglich löschen.

Kann das PullUp ein Problem sein?
Da die Pins abgefragt werden und diese Abfrage durch den Interrupt 
unterbrochen wird ... kann so was sein?

@Jörg Wunsch, danke für den hinweiß hab die sache übernommen!

Gruß
Liloba

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:
> beim normalen überschreiben werden immer nur die neuen
> Digits überschrieben und so bleiben die Nullen der 100 stehen auch wenn
> nur noch 9Hz eingestellt sind

Rechtsbündig schreiben.  Hast du vielleicht noch Platz für ein
sprintf() (statt des itoa())?  Da wäre sowas ganz einfach.

von bobtheworker (Gast)


Lesenswert?

hat der Baustein keine PWM ? wäre doch viel einfacher ?

von Karl H. (kbuchegg)


Lesenswert?

> Kann das PullUp ein Problem sein?

Welcher Pullup?

Ein LCD wird einfach nur direkt, Pin für Pin mit dem µC verbunden. Kein 
Pullup, kein Pulldown, gar nichts.
Der Rest ist Software.

> Da die Pins abgefragt werden und diese Abfrage
> durch den Interrupt unterbrochen wird ... kann so was sein?

Am LCD?

Nein. LCD sind insofern zeitkritisch, als man ein Mindesttiming 
einhalten muss. Ein Interrupt an der falschen Stelle macht dir das 
Timing aber höchstens länger. Das ist alles nicht kritisch.

von Liloba (Gast)


Angehängte Dateien:

Lesenswert?

Hallo alle zusammen,
solangsam siehts schon gut aus.

Diese stelle hier macht Probleme:
1
if ((PINB & (0<<PINB5))){ ... }

Ursprünglich stand da
1
if ((PINB & (1<<PINB5))){ ... }

jedoch macht der PullUP ja automatisch die 1 und ich möcht mit einem 
Taster den Pin auf Low ziehen worauf der µC dann reagiert.

Dasselbe ist bei den andern Pins.
Die Frequenz bei den selbst gebastelten Timer ist nicht richtig aber das 
schau ich mir gleich an. Die Pin Abfrage ist jetzt mein Problem.

Liloba

von Karl H. (kbuchegg)


Lesenswert?

Liloba schrieb:
> Hallo alle zusammen,
> solangsam siehts schon gut aus.
>
> Diese stelle hier macht Probleme:
>
1
> if ((PINB & (0<<PINB5))){ ... }
2
>


Das geht nicht.
Nach Auswertung der Verschiebung steht da

   if (( PINB & 0 ) )

und das ist ziemlich sicher nicht das was du willst.
Eine 0 kannst du schieben sooft und so weit du willst. Das Ergebnis 
bleibt trotzdem immer 0.

> Ursprünglich stand da
>
1
> if ((PINB & (1<<PINB5))){ ... }
2
>

das ist schon richtig

> jedoch macht der PullUP ja automatisch die 1 und ich möcht mit einem
> Taster den Pin auf Low ziehen worauf der µC dann reagiert.

dann musst du die Bedingung umdrehen

  if( !( PINB & ( 1<<PINB5 ) )

Die Maskierung mit & sorgt ja nur dafür, dass das interessierende Bit 
übrig bleibt. Und das kann entweder 0 oder nicht 0 sein.

Im Original wurde abgefragt ob es nicht 0 ist. Jetzt drehst du die 
Bedingung um und fragst ab ob es 0 ist.

(aber hüte dich an dieser Stelle vor Vergleichen mit == oder !=
 Einfacher ist es, die C Regel anzuwenden, dass jedes Ergebnis ungleich 
0 automatisch als logisch WAHR gewertet wird. Dein originales

   if ((PINB & (1<<PINB5)))

benutzt das, um die Langform

  if ( (PINB & (1<<PINB5)) != 0 )
zu vermeiden.
Erstens ist das kürzer, zweitens ist es weniger fehleranfällig in der 
Schreibweise.

von Liloba (Gast)


Lesenswert?

ok, das hab ich. ... uns sogar verstande ;)

warum kann ich OCR2 welches nach der Init auf 72 steht nicht mehr in der 
laufzeit verändern? Dardurch ist mein ganzer Timer2 fast nutzlos.

von Liloba (Gast)


Angehängte Dateien:

Lesenswert?

Also ich hab das jetzt mal ne ein bisschen durchgetestet und es muss mit 
der Pin abfrage in der Main zusammen hängen. Sobald ich diese ausschalte 
steht die Anzeige still.

Kann ich irgendwie die Timer oder auch nur die Interrupts 
unterbrechen/anhalten solang eine Änderung der Einstellungen 
durchgeführt wird?

Schönes Wochenende euch allen und danke für die Hilfe!
Liloba

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:
> warum kann ich OCR2 welches nach der Init auf 72 steht nicht mehr in der
> laufzeit verändern?

Wer sagt denn sowas?

von Liloba (Gast)


Lesenswert?

naja, da die Bedienung noch nicht geht ... hab ich das nur simuliert 
aber dabei ging es nicht !
Nun denn, ... ich mach am Dienstag weiter.
Danke noch mal.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Liloba schrieb:
> hab ich das nur simuliert
> aber dabei ging es nicht !

Simulatoren sind Schall und Rauch.  Nur die Praxis zählt.

Wenn du statt des ältlichen ATmega8 wenigstens einen ATmega88
benutzen würdest, hättest du einige Vorteile:

. Upgrade-Pfad auf ATmega168 oder gar ATmega328 möglich, sodass
  du bspw. auf jeden Fall Platz für sprintf() und damit eine
  ordentlich formatierte Ausgabe ohne weitere Verrenkungen.

. Online-Debug-Möglichkeit via debugWIRE (bspw. mit einem AVR
  Dragon).

. Im AVR Studio meines Wissens dann den "Simulator V2", bei dem
  prinzipbedingt sichergestellt ist, dass der Digitalteil des
  Controllers auch genau so simuliert wird, wie er sich im IC
  verhält.  Beim alten Simulator (meines Wissens ist das beim
  ATmega8 die einzige Möglichkeit) ist das nämlich keinesfalls
  so sicher.

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.