Variable besichtigen

Gast #1468370
Lesenswert?

Hallo

ich benutze AVR Studio mit WinAVR.

Ich habe einen 8 Prescaler mit einem OCR0A-Wert.

Das Problem ist dass es den Interrupt immer bei 256 auslöst.

Mich würde interessieren wie ich bei AVR Studio die Variablen 
besichtigen kann um zu sehen welcher Wert zugewiesen wurde.

MfG
Gast #1468463
Lesenswert?

Wie meinst du das?

Das Programm wird in diesen Zeilen ausgeführt.

Meine Vermutung ist dass man Register nicht in Dez. ausgeben kann.
1
unsigned int variable
2

3
zahl =   TIME*1000/(8*125);
4
funktion(8, zahl);
5

6

7
funktion(...., unsigned int zahl)
8
{
9
  OCR0A= zahl;
10
}

Ich vermute der Fehler liegt bei der zahl. Sie wird in INT berechnet und 
dann weise ich die Zahl dem Register OCR0A zu.

Brauchen Register eine HEX-Zahl. Gibt es einen Befehl zur umformung von 
DEZ in HEX
Gast #1468494
Lesenswert?

Zunächst mal Dez und Hex ( und auch binär) sind nur verschiedene 
Darstellungen für das selbe Bitmuster. Ist also nur einen andere 
schreibweise.


Die Variable Zahl wird in der Tat wegoptimiert, da der Compiler erkennt, 
dass sie nicht benötigt wird, weil der Wert konstant ist. Also der 
Compilier verwendet statt der Variable direkt den Wert, den du 
zugewiesen hast. Das darf der Compiler machen, solange die Funktion des 
Programms die selbe bleibt. Das einzige was du von der Optimierung 
(neben einem kleineren Programm) mitbekommst, ist eben, dass du die 
Variable nicht mehr im debugger anschauen kannst.  Dafür gibt es nun 2 
lösungen:

1) du schaltest in den Projekteinstellungen die Optimierung komplett aus 
(-O0). Dadurch wird nichts mehr wegoptimiert, aber das Programm wird 
auch größer.

2) du deklarierst die Variable zum Debuggen als volatile. Das verhindert 
unter anderem, dass die Variable wegoptimiert wird.
Moderator (Firma: Titel) Persönliche Seite #1468502
Lesenswert?

Hex, Dezimal und Binär ist alles nur eine jeweils andere Darstellung 
einer Zahl. Ich kann jede ganze Zahl in allen Schreibweisen 
darstellen.
Als char betrachtet gibt es dafür nur 8 Bit. Schön ist, dass diese 8 Bit 
in 2 Nibble passen, von denen wieder jedes einzelne die Hälfte einer 
Hex-Zahl ist.
0xff = 0b11111111 = 255 =   -1
0x07 = 0b00000111 =   7 =   +7
0xf0 = 0b11110000 = 248 =  -16
usw. usf.

Ein short (=int bei AVR) sind dann nur 2 Bytes hintereinander und 
demnach 4 Hex-Zeichen.
0xffff = 0b1111111111111111 = 65535 =   -1
0x0007 = 0b0000000000000111 =     7 =   +7
0xfff0 = 0b1111111111110000 = 65520 =  -16
Gast #1468590
Lesenswert?

TIME ist ein irgendein Wert in us.

Irgendwas stimmt mit der Berechnung nicht.

Habe zb. 90 genommen. Beim Prescaler 8 sollte der OCR0A Wert auch 90 
sein.

Bei 8MHz

OCR0A= 90*1000/ (8*125)= 90

Zugewiesen wird aber 0x18
#1468604
Lesenswert?

90*1000 ist ein bischen zu groß, als das diese Berechnung im Zahlenraum 
int durchgeführt werden könnte.
int endet bei 32767. Sobald du drüberkommst und sei aus auch nur bei 
einem Zwischenergebnis, hast du verloren :-)

Berechnung ein wenig umstellen und schon geht sich alles aus.
#1468955
Lesenswert?

Stefan Ernst schrieb:
> Karl heinz Buchegger schrieb:
>
>> Berechnung ein wenig umstellen und schon geht sich alles aus.
>
> "Umstellen"? Wie wäre es mit "weglassen"? ;-)

Er wird schon seinen Grund haben :-)
Und sei es nur, daß er den Vorteiler einfach wechseln kann, was ja 
grundsätzlich nicht schlecht ist.
Gast #1469564
Lesenswert?

Danke für die Hilfe. Das int war der Fehler.

Für unterschiedliche Werte brauche ich unterschiedliche Prescaler.

Das einzige was ich noch machen könnte ist alle zb. 10us einen Interrupt 
auslösen.

Bei 1000 us würde ich da aber viele Interrupts auslösen aber beinahe 
nichts machen.
Gast #1469724
Lesenswert?

Hallo

Ich habe wieder irgendwelche Probleme

1
define ZEIT 10000
2

3
main
4
{
5
funktion(ZEIT);
6
}
7

8

9
funktion(ZEIT)
10
{
11
  else if( (ZEIT > 8000) && (ZEIT <= 30000) )
12
  {  
13
    TCCR0B= 0x05;           //CS=5 => 1024
14
    nummer =  ZEIT*8/1024;
15
    unterfunktion (8, nummer);
16
  }
17

18
}
19

20
unterfunktion()
21
{
22
          if(xy == 8)
23
    CLKPR = 0x80; 
24
     CLKPR = 0x00;
25

26
      TCCR0A= 0x02; 
27
      TIMSK0= 0x02;
28
    
29

30
    OCR0A= nummer;
31
}

Laut Berechnung sollte "nummer==78 sein", OCR0A wird aber 0x0E 
zugewiesen.
#1469757
Lesenswert?

Selbes Problem

 else if( (ZEIT > 8000) && (ZEIT <= 30000) )
  {
    TCCR0B= 0x05;           //CS=5 => 1024
    nummer =  ZEIT*8/1024;


Wenn ZEIT minmial den Wert 8000 hat, dann ergibt 8000 * 8 ein 
Zwischenergebnis von 64000. Damit bist du über den magischen 32767 
drüber :-)

(Was sagt eigentlich dein C-Buch zum Thema 'long')

Und bitte: Übertrage deinen Code per Copy&Paste hier ins Forum. Es ist 
ziemlich mühselig, deine wirklichen Probleme von den Tippfehlern zu 
unterscheiden.
Gast #1469853
Lesenswert?

Es ist kein int-Fehler zumindest bei variable.

Vielleicht ist es ein Fehler hier
>variable = TIME*8/1024;
weil TIME ein Integer ist.
1
main
2
{
3
else if ( (ZEIT >= 1000) && (TIMER == 0) )
4
  delay_t0_ms(ZEIT);
5
}
6

7
void delay_t0_ms(unsigned int TIME)
8
{  
9
        unsigned long int variable;
10

11
  else if( (TIME > 8192) && (TIME <= 32767) )  //Prescaler 1024
12
  {  
13
    TCCR0B= 0x05;
14
    variable =   TIME*8/1024;
15
    init_t0(8, variable);
16
  }
17

18
}
19

20
void init_t0 (unsigned int MHZ, unsigned int num_us_tick)
21
{
22
  else if(MHZ==8)
23
  {
24
    CLKPR = 0x80; 
25
     CLKPR = 0x00;
26

27
      TCCR0A= 0x02; 
28
      TIMSK0= 0x02;
29
    
30

31
    OCR0A= num_us_tick;
32
  }
33

34
sei();
35
}
#1469883
Lesenswert?

AVR schrieb:
>
> Vielleicht ist es ein Fehler hier
>>variable = TIME*8/1024;
> weil TIME ein Integer ist.


Morgen früh, gleich als allererstes, gehst du in die nächste 
Buchhandlung und besorgst dir ein C-Buch.

Das sind alles Grundlagen. Und zwar von der Sorte, die in jedem noch so 
grindigen C-Buch in den ersten 4 Kapiteln (von 25) erklärt werden.

>     TCCR0B= 0x05;
>     variable =   TIME*8/1024;

Zu dem Zeitpunkt, zu dem an 'variable' zugewiesen wird, ist das Kind 
längst in den Brunnen gefallen.

   TIME * 8
interessiert nicht die Bohne, dass du das Endergebnis an einen unsigned 
long zuweist. TIME ist ein unsigned int, 8 ist ein int. Also wird in 
unsigned int gerechnet und das Ergebnis ist wieder ein unsigned int.

Was anderes ist allerdings

   TIME * 8L
TIME ist ein unsigned int, 8 ist jetzt ein long. Also wird in long 
gerechnet.

   TIME * 8UL
Jetzt ist 8 ein unsigned long und es wird im Zahlenraum unsigned long 
gerechnet.


Wieso hältst du dich eigentlich nicht an die übliche Konvention, dass 
Namen, welche komplett in Grossbuchstaben geschrieben sind, 
ausschliesslich für Makros reserviert sind.
Moderator (Firma: Titel) Persönliche Seite #1470065
Lesenswert?

1
void init_t0 (unsigned int MHZ, unsigned int num_us_tick)
2
{
3
  else if(MHZ==8)   //  sosososo... 
4
  {
5
      :
6
      :
Was sagt eigentlich dein Compiler dazu?

> Morgen früh, gleich als allererstes, gehst du in die nächste
> Buchhandlung und besorgst dir ein C-Buch.
Ja, das wäre wohl das Beste...

BTW:
Es ist oft einfacher, das C-Programmieren am PC zu lernen. Und wenns 
dort klappt, dann erst in die Einschränkungen der uC-Welt einzusteigen.
Gast #1476366
Lesenswert?

Hallo

Könnte einen Denkanstoß gebrauchen. Es heißt man soll möglichst viel in 
den Hauptcode verlagern und nicht im ISR lassen. Habe es so versucht 
aber der Timer wird nicht richtig ausgeführt.

delay_t1_s geht das Programm nur einmal durch und bleibt dann in der 
ISR-Funktion.

Ich wollte dass alle 100ms die innere for-Schleife um 1 hochzählt. Wenn
1
if( (a == time) && (b == 10) )
 soll die ISR-Funktion ausgeführt werden.
1
void delay_t1_s(unsigned long int time)
2
{
3
  unsigned long int variable;
4
  int i, a, b;
5
  
6
  timer_init(7);
7

8
  if(MHZ == 1)
9
  {
10
    variable= 12;
11

12
     if( (time >= 1) && (time <= 999) )
13
    {
14
      for(a=1; a <= time; a++)
15
      {
16
        for(b=1; b <=10; b++)
17
        {
18
          if( (a == time) && (b == 10) )
19
          {
20
            //init_t1(MHZ, variable);
21
          }
22
        }
23
      }
24
    }
25
  }
26
}
27

28

29

30
void init_t1 (unsigned int mhz, unsigned int num_us_tick)
31
{
32
  if(mhz==1)
33
  {
34
      TCCR1A= 0x00; 
35
      TIMSK1= 0x02;
36
    
37

38
    OCR1A= num_us_tick;
39
  }
40

41
sei();
42
}
43

44

45
ISR (TIMER1_COMPA_vect) 
46
{
47
  PORTB^= 0x04; 
48
}

MfG
#1476787
Lesenswert?

Da scheint ein grundsätzliches Misverständnis vorzuliegen.

Der Timer arbeitet völlig unabhängig von allem anderen.
Wenn du also etwas alle 100ms ausführen lassen willst, dann setzt du den 
Timer so auf, dass er dir alle x Millisekunden einen Interrupt auslöst 
(zb. weil der Timer einen Overflow generiert). In der ISR zählst du mit, 
wie oft die ISR aufgerufen wurde und leitest davon die 100 Millisekunden 
ab.

Wird dein Timer zb alle 0.5 Millisekunden aufgerufen, dann muss 
innerhalb der ISR eine Variable bis 200 zählen, damit 100 Millisekunden 
vergangen sind.
Gast #1477769
Lesenswert?

Hallo Karl Heinz

hast du gemeint dass der Code ca. so zu programmieren wäre. Mein Problem 
ist dass ich nicht schauen kann wieviel Zeit vergeht weil AVR Studio in 
der Zeile if(zaehler == 2) hängen bleibt und im us-Takt weiter zählt. Es 
springt komischer Weise nicht ins ISR und berechnet die Zeit.

Gibt es hier irgendwo Infos zur Programmierung eines Callbacks.

1
volatile int zaehler;
2
volatile int sek;
3

4
void delay_t1_s(unsigned long int time)
5
{
6
  unsigned long int variable;
7
  int i;
8
  
9

10
  timer_init(7);                      //Prescaler 8
11

12
  if(MHZ == 1)
13
  {
14
    variable= 62500;            //OCRB1=62500 = 500ms
15
    init_t1(MHZ, variable);     //initialisiert Timer 
16

17
     if( (time >= 1) && (time <= 999) )
18
    {
19
      while(1)
20
      {
21
        if (zaehler == 2)
22
        {
23
          zaehler=0;
24
          sek++;
25
          
26
          if(sek==time)
27
          {
28
            PORTB^= 0x01;
29
            b=0;
30
          }
31
        }
32

33
      }
34
    }
35
  }
36
}
37

38

39
ISR (TIMER1_COMPA_vect) 
40
{
41
    if (fehler == 1)
42
  {
43
      PORTB= ~PORTB;
44
  }
45

46
  else if(1)
47
  {
48
    zaehler++;
49
  }
50

51
  else
52
  {
53
    PORTB^= 0x01;  
54
  }
55
}

Danke für die Hilfe
MfG
Gast #1478697
Lesenswert?

>Und was zum T.... verbirgt sich hinter all den timer Funktionen?

Dachte du wolltest wissen was die Funktionen machen.


Habe jetzt länger getestet. Der Simulator hat sehr lange gebraucht beim 
hochzählen deshalb blieb er bei der Zeile "if (zaehler == 2)" die ganze 
Zeit hängen.

Danke für die Hilfe.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren