Forum: Mikrocontroller und Digitale Elektronik Attiny45, timer tut nichts?


von A. F. (elagil)


Lesenswert?

Hallo,

ich habe ein einfaches Programm zum Testen geschrieben:
1
#include <avr/io.h> 
2
3
int main (void) 
4
{ 
5
   DDRB |= (1 << PB0);
6
   PORTB ^= (1 << PB0);
7
8
   TCCR1 |= ((1 << CS13) | (1 << CS12)); // ps 4096 -> 2kHz
9
10
   for (;;) 
11
   { 
12
     
13
      if (TCNT1 >= 200) // ca 10 Hz
14
      { 
15
         PORTB ^= (1 << PB0); // Toggle
16
17
         TCNT1 = 0;
18
      } 
19
   } 
20
}

es soll eine led an PB0 flackern lassen, es passiert aber nichts. nach 
dem einschalten ändert sich nichts an der led. mit "_delay_ms" 
funktioniert das togglen einwandfrei, wo liegt denn da der fehler?

der attiny läuft bei 8Mhz mit internem oszillator.

von Electronics'nStuff (Gast)


Lesenswert?

Naja was soll da schon passieren?
CTC Mode einstellen vergessen!

von Electronics'nStuff (Gast)


Lesenswert?

BTW: Ist ein Bit im TCCR1 Register, welches musst du selber nachschauen, 
das weiss ich nicht auswendig.

von Karl H. (kbuchegg)


Lesenswert?

Adrian Figueroa schrieb:


>    TCCR1 |= ((1 << CS13) | (1 << CS12)); // ps 4096 -> 2kHz


das sind aber keine 4096, sondern 2048.

Deine 10Hz sind also eher 20Hz. Und wenn man nicht so genau schaut, dann 
ist das nicht so sehr ein kräftiges Flackern, sondern schon fast ein 
gleichmässiges Leuchten.

von A. F. (elagil)


Lesenswert?

> CTC Mode einstellen vergessen!

Aber ich setze doch den counter manuell zurück? Ich möchte selbst 
steuern, wann er sich zurücksetzt.

> das sind aber keine 4096, sondern 2048.

ok, ich hab mal vier bits gesetzt (CS10 bis 13) -> ca. 16k Prescaler
Da sollte ich doch eigentlich was sehen.

von Stefan H. (hohmi)


Lesenswert?

schau mal Datenblatt des ATtiny45 ab seite 89. es fehlen noch ein paar 
register einträge.

mfg
Hohmi

Edit: war der falsche Controller^^, jetzt stimmts

von Electronics'nStuff (Gast)


Lesenswert?

Ich würde das trotzdem so machen:
1
#include <avr/io.h> 
2
3
int main (void) 
4
{ 
5
   DDRB |= (1 << PB0);
6
   PORTB ^= (1 << PB0);
7
   OCR1 = 200;  //Max. Zählwert
8
   TCCR1 |= ((1 << CS13) | (1 << CS12) | (1<< WGM13)); // ps 4096 -> 2kHz
9
   sei(); //Globale Interrupts erlauben
10
11
   for (;;) 
12
   { 
13
     
14
    _delay_ms(1); //Irgend ein Befehl    
15
16
    } 
17
   
18
}
19
20
ISR (TIMER1_COMP_vect)
21
{
22
   PORTB ^= (1 << PB0); // Toggle
23
}

von A. F. (elagil)


Lesenswert?

> Ich würde das trotzdem so machen:

das ist ja nur ein beispielprogramm ;) ich möchte später IR-Sequenzen 
auslesen, dazu wird der empfänger einen interrupt erzeugen, der dann den 
aktuellen zählerstand ausliest und dann wieder nullt! dafür muss ich ihn 
manuell setzen können.

> schau mal Datenblatt des ATtiny45 ab seite 89. es fehlen noch ein paar
> register einträge.

ich habe mal alles zu timer1 gelesen. :)

mir fällt kein versäumnis auf. ich will weder vergleichsregister setzen, 
noch pwm nutzen. Ich brauche keine interrupts, auch keinen fast mode 
oder sowas. der zähler soll nur zählen und ich möchte ihn manuell 
auslesen.

von Electronics'nStuff (Gast)


Lesenswert?

Adrian Figueroa schrieb:
> ok, ich hab mal vier bits gesetzt (CS10 bis 13) -> ca. 16k Prescaler

CS13? Reden wir vom gleichen Controller?
Der Attiny45 hat nur CS10-CS12 in diesem Register.

von A. F. (elagil)


Lesenswert?

auf seite 92 im datenblatt http://www.atmel.com/Images/doc2586.pdf sehe 
ich auch cs13 an bit3

von Electronics'nStuff (Gast)


Lesenswert?

Oh Shit, sorry hatte das DB des Attiny48 angekuckt.

von A. F. (elagil)


Lesenswert?

ah das erklärt die syntaxfehler beim kompilieren von deinem quelltext ;) 
die register heißen alle anders...

von Electronics'nStuff (Gast)


Lesenswert?

Ne, die heissen schon so, müsstest einfach noch:

#include <avr/interrupt.h>   //interrupt library

einbinden.

Und statt OCR1 -> OCR1A.

von A. F. (elagil)


Lesenswert?

Ich verstehe es nicht! Timer0 läuft einwandfrei, Timer1 nicht... ich 
habe zwei LEDs dran..
1
#include <avr/io.h> 
2
#include <avr/interrupt.h> 
3
4
int main(void) 
5
{ 
6
  
7
8
  DDRB |= (1 << PB0) | (1 << PB1);
9
  PORTB |= (1 << PB0)| (1 << PB1);
10
  
11
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
12
  TCCR0B |= (1<<CS02) | (1<<CS00);
13
14
15
  while(1) { 
16
  if(TCNT0 > 200) {
17
    DDRB ^= (1 << PB0);
18
    TCNT0 = 0;
19
  }
20
  }
21
  
22
   while(1) { 
23
  if(TCNT1 > 200) {
24
    DDRB ^= (1 << PB1);
25
    TCNT1 = 0;
26
  }
27
  }
28
}

von dosi (Gast)


Lesenswert?

Was sollen die zwei while-Schleifen?

von Nico (nico123)


Lesenswert?

Der Controller kommt ja auch nicht aus der ersten while-Schleife raus!!!

von Electronics'nStuff (Gast)


Lesenswert?

Erstaunt jetzt nicht wirklich, du hast 2 Endlosschleifen.

von A. F. (elagil)


Lesenswert?

oha :D ja das war wirklich dumm

von A. F. (elagil)


Lesenswert?

wie auch immer, das hier geht nicht:
1
#include <avr/io.h> 
2
#include <avr/interrupt.h> 
3
4
int main(void) 
5
{ 
6
  
7
8
  DDRB |= (1 << PB0) | (1 << PB1);
9
  PORTB |= (1 << PB0)| (1 << PB1);
10
  
11
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
12
  TCCR0B |= (1<<CS02) | (1<<CS00);
13
14
15
  while(1) { 
16
17
  if(TCNT1 > 200) {
18
    DDRB ^= (1 << PB0);
19
    TCNT1 = 0;
20
  }
21
  }
22
}

das hier schon:
1
#include <avr/io.h> 
2
#include <avr/interrupt.h> 
3
4
int main(void) 
5
{ 
6
  
7
8
  DDRB |= (1 << PB0) | (1 << PB1);
9
  PORTB |= (1 << PB0)| (1 << PB1);
10
  
11
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
12
  TCCR0B |= (1<<CS02) | (1<<CS00);
13
14
15
  while(1) { 
16
17
  if(TCNT0 > 200) {
18
    DDRB ^= (1 << PB0);
19
    TCNT0 = 0;
20
  }
21
  }
22
}

von Nico (nico123)


Lesenswert?

Adrian Figueroa schrieb:
> DDRB ^= (1 << PB0);

So setzt/toggelt man keinen Port!
Sondern so: PORTB ^= (1 << PB0);

Und das funktioniert im zweiten Beispiel?

von Spess53 (Gast)


Lesenswert?

Hi

>Und das funktioniert im zweiten Beispiel?

Wahrscheinlich nicht. Aber

PINB = (1 << PB0);

toggled einen Pin beim ATTiny45.

MfG Spess

von dgps (Gast)


Lesenswert?

du schmeißt die Timer-Bezeichnungen durcheinander!

Du musst überalle entweder Timer0 ODER Timer1 benutzen.

von A. F. (elagil)


Lesenswert?

> So setzt/toggelt man keinen Port!
> Sondern so: PORTB ^= (1 << PB0);

oh ja... hat bei timer0 geklappt, weil ich den ja pin vorher schon 
eingeschaltet habe, ich schalte also zwischen ein- und ausgang hin und 
her, also einmal mit internem pullup und einmal ohne.

> du schmeißt die Timer-Bezeichnungen durcheinander!

naja, wenn ich den timer nicht benutze, ist das ja nicht schlimm, oder?

..die konzentration lässt nach.. neuer versuch ;) das hier läuft 
jedenfalls nicht.
1
#include <avr/io.h> 
2
#include <avr/interrupt.h> 
3
4
int main(void) 
5
{ 
6
  
7
8
  DDRB |= (1 << PB0) | (1 << PB1);
9
  PORTB |= (1 << PB0)| (1 << PB1);
10
  
11
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
12
13
14
  while(1) { 
15
  if(TCNT1 > 200) {
16
    PORTB ^= (1 << PB0);
17
    TCNT1 = 0;
18
  }
19
  }
20
}

von Fred S. (kogitsune)


Lesenswert?

Was erwartest Du? Du benutzt einen Vorteiler von 1024, bekommst bei 8 
MHz Systemtakt also eine AN/AUS-Dauer von jeweils 25,6 ms -- also 
nichts, was man als Blinken identifizieren würde!

von A. F. (elagil)


Lesenswert?

Ich zähle erst noch bis 200!
Mit dem Timer0, den ich auch auf 1024er Prescaler gestellt habe und 
einem Counter von 200, konnte ich das Blinken klar sehen, mit Timer1 
bekomme ich nur ein dauerleuchten!

von Fred S. (kogitsune)


Lesenswert?

Adrian Figueroa schrieb:
> Ich zähle erst noch bis 200!
Genau davon bin ich auch ausgegangen:
200*(1024/8000000Hz)= 25,6 ms

> Mit dem Timer0, den ich auch auf 1024er Prescaler gestellt habe und
> einem Counter von 200, konnte ich das Blinken klar sehen, mit Timer1
> bekomme ich nur ein dauerleuchten!
Natürlich kann man ein "Blinken" von 20 Hz wahrnehmen; genau das 
bekommst Du mit Deinem zuletzt oben gezeigten Programm. Schau aber mal 
nach, ob mit der Hardware alles OK ist, also die LED wirklich an PB0 
hängt usw.

von A. F. (elagil)


Lesenswert?

Ja, die Hardware stimmt soweit. Ich kann alles schalten.

Wie gesagt, wenn ich TCNT1 durch TCNT0 ersetze und entsprechend den 
Timer0 auf Prescaler 1024 einstelle, klappt alles einwandfrei!

von Fred S. (kogitsune)


Lesenswert?

Deine Terminologie finde ich etwas seltsam. 20 Hz "Flimmern" nennst Du 
"Blinken"?

Du zeigst uns wirklich Dein aktuelles Programm (also ohne Setzen der 
PSR1/PCKE Bits)? CKSEL Fuse?

von A. F. (elagil)


Lesenswert?

> Du zeigst uns wirklich Dein aktuelles Programm

Ja.

> also ohne Setzen der PSR1/PCKE Bits

ich habe sonst nichts gesetzt. ich habe auch mal zuvor die register zu 
null initialisiert.

> CKSEL Fuse?

CKSEL = 0010, SUT=10, den Taktteiler habe ich ausgeschaltet (CKDIV8=1 
[active low?]).

Die Fuses sind also 0xE2(low) 0xDF(high) 0xFF(ext.)

von Fred S. (kogitsune)


Lesenswert?

Die genannten Fuses stimmen. Du bist Dir sicher, dass Du den aktuellen 
Code im Flash stehen hast? Und dass der Compiler für den Attiny45 
kompiliert? Und dass an PB0 sonst nichts mehr hängt? Mal einen anderen 
Pin versucht?

Versuche doch auch einmal einen größeren Divisor als 1024; beim Timer1 
kann man doch bis 16384 gehen.

von A. F. (elagil)


Lesenswert?

Hm.. Ja, gerade nochmal neu geflasht.

PB0 funktioniert einwandfrei mit Timer0! Ich habe auch schon PB1 und PB3 
getestet, immer das selbe. Die if Bedingung wird nie erfüllt. Wenn ich 
sowas reinschreibe wie "PORTB |= (1<<PB0)" und die LED vorher aus war, 
geht sie dann nicht an.

Ich habe schon alle möglichen Prescaler benutzt.. fürs erste werde ich 
wohl bei Timer0 bleiben, ich weiß nicht was falsch sein soll.

Ein anderer attiny45 zeigt übrigens das gleiche verhalten ;)

von Digitalism (Gast)


Lesenswert?

Ich glaube nicht, dass man dir noch helfen kann wenn ich ehrlich bin.

- Der Code ist fehlerfrei
- Der Controller ist nicht defekt
- Der Systemtakt scheint zu stimmen

Was anderes kommt gar nicht in Frage, ausser dass dein Compiler aus 
irgend einem komischen Grund den Timer1 nicht kennt..

Was benutzt du eig. für eine Entwicklungsumgebung?
Womit flasht du den Controller?

Oder du verarscht uns einfach :P

von A. F. (elagil)


Lesenswert?

Wenn ich in die if-Bedingung TCNT1==0 einsetze, dann dimmt er die led, 
ich muss also davon ausgehen, dass der zähler nicht hochzählt.

> Was benutzt du eig. für eine Entwicklungsumgebung?
> Womit flasht du den Controller?

Winavr/avrdude mit einem china-usbasp..

so sieht das aus: ;)
1
Compiling C: rffb.c
2
avr-gcc -c -mmcu=attiny45 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./rffb.lst  -std=gnu99 -MMD -MP -MF .dep/rffb.o.d rffb.c -o rffb.o 
3
4
Linking: rffb.elf
5
avr-gcc -mmcu=attiny45 -I. -gdwarf-2 -DF_CPU=8000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=rffb.o  -std=gnu99 -MMD -MP -MF .dep/rffb.elf.d rffb.o --output rffb.elf -Wl,-Map=rffb.map,--cref     -lm
6
7
Creating load file for Flash: rffb.hex
8
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock rffb.elf rffb.hex
9
10
Creating load file for EEPROM: rffb.eep
11
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
12
  --change-section-lma .eeprom=0 --no-change-warnings -O ihex rffb.elf rffb.eep || exit 0
13
avrdude -p attiny45 -P usb -c usbasp    -U flash:w:rffb.hex 
14
15
avrdude: AVR device initialized and ready to accept instructions
16
17
Reading | ################################################## | 100% 0.00s
18
19
avrdude: Device signature = 0x1e9206
20
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
21
         To disable this feature, specify the -D option.
22
avrdude: erasing chip
23
avrdude: reading input file "rffb.hex"
24
avrdude: input file rffb.hex auto detected as Intel Hex
25
avrdude: writing flash (86 bytes):
26
27
Writing | ################################################## | 100% 0.05s
28
29
avrdude: 86 bytes of flash written
30
avrdude: verifying flash memory against rffb.hex:
31
avrdude: load data flash data from input file rffb.hex:
32
avrdude: input file rffb.hex auto detected as Intel Hex
33
avrdude: input file rffb.hex contains 86 bytes
34
avrdude: reading on-chip flash data:
35
36
Reading | ################################################## | 100% 0.02s
37
38
avrdude: verifying ...
39
avrdude: 86 bytes of flash verified
40
41
avrdude done.  Thank you.

> Oder du verarscht uns einfach :P

Ich hab besseres zu tun :D

von Fred S. (kogitsune)


Lesenswert?

Seh' ich so wie "Digitalism".

Zeig vielleicht auch mal die *.lss Datei (Du hast noch nicht gesagt, 
welche Winavr Version Du verwendest. Ich weiß nicht, ob alte 
Compiler-Versionen jemals mit dem Timer1 Probleme hatten... aber 
trotzdem.).

von A. F. (elagil)


Lesenswert?

ich benutze Winavr 20100110 (wohl die neueste).

hier die gewünschte datei:
1
rffb.elf:     file format elf32-avr
2
3
Sections:
4
Idx Name          Size      VMA       LMA       File off  Algn
5
  0 .text         00000054  00000000  00000000  00000054  2**1
6
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
7
  1 .debug_aranges 00000020  00000000  00000000  000000a8  2**0
8
                  CONTENTS, READONLY, DEBUGGING
9
  2 .debug_pubnames 0000001b  00000000  00000000  000000c8  2**0
10
                  CONTENTS, READONLY, DEBUGGING
11
  3 .debug_info   00000076  00000000  00000000  000000e3  2**0
12
                  CONTENTS, READONLY, DEBUGGING
13
  4 .debug_abbrev 00000041  00000000  00000000  00000159  2**0
14
                  CONTENTS, READONLY, DEBUGGING
15
  5 .debug_line   00000088  00000000  00000000  0000019a  2**0
16
                  CONTENTS, READONLY, DEBUGGING
17
  6 .debug_frame  00000020  00000000  00000000  00000224  2**2
18
                  CONTENTS, READONLY, DEBUGGING
19
  7 .debug_str    00000083  00000000  00000000  00000244  2**0
20
                  CONTENTS, READONLY, DEBUGGING
21
22
Disassembly of section .text:
23
24
00000000 <__vectors>:
25
   0:  0e c0         rjmp  .+28       ; 0x1e <__ctors_end>
26
   2:  15 c0         rjmp  .+42       ; 0x2e <__bad_interrupt>
27
   4:  14 c0         rjmp  .+40       ; 0x2e <__bad_interrupt>
28
   6:  13 c0         rjmp  .+38       ; 0x2e <__bad_interrupt>
29
   8:  12 c0         rjmp  .+36       ; 0x2e <__bad_interrupt>
30
   a:  11 c0         rjmp  .+34       ; 0x2e <__bad_interrupt>
31
   c:  10 c0         rjmp  .+32       ; 0x2e <__bad_interrupt>
32
   e:  0f c0         rjmp  .+30       ; 0x2e <__bad_interrupt>
33
  10:  0e c0         rjmp  .+28       ; 0x2e <__bad_interrupt>
34
  12:  0d c0         rjmp  .+26       ; 0x2e <__bad_interrupt>
35
  14:  0c c0         rjmp  .+24       ; 0x2e <__bad_interrupt>
36
  16:  0b c0         rjmp  .+22       ; 0x2e <__bad_interrupt>
37
  18:  0a c0         rjmp  .+20       ; 0x2e <__bad_interrupt>
38
  1a:  09 c0         rjmp  .+18       ; 0x2e <__bad_interrupt>
39
  1c:  08 c0         rjmp  .+16       ; 0x2e <__bad_interrupt>
40
41
0000001e <__ctors_end>:
42
  1e:  11 24         eor  r1, r1
43
  20:  1f be         out  0x3f, r1  ; 63
44
  22:  cf e5         ldi  r28, 0x5F  ; 95
45
  24:  d1 e0         ldi  r29, 0x01  ; 1
46
  26:  de bf         out  0x3e, r29  ; 62
47
  28:  cd bf         out  0x3d, r28  ; 61
48
  2a:  02 d0         rcall  .+4        ; 0x30 <main>
49
  2c:  11 c0         rjmp  .+34       ; 0x50 <_exit>
50
51
0000002e <__bad_interrupt>:
52
  2e:  e8 cf         rjmp  .-48       ; 0x0 <__vectors>
53
54
00000030 <main>:
55
56
int main(void) 
57
{ 
58
  
59
60
  DDRB |= (1 << PB0);
61
  30:  b8 9a         sbi  0x17, 0  ; 23
62
  PORTB |= (1 << PB0)| (1 << PB1);
63
  32:  88 b3         in  r24, 0x18  ; 24
64
  34:  83 60         ori  r24, 0x03  ; 3
65
  36:  88 bb         out  0x18, r24  ; 24
66
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS12) | (1 << CS13);
67
  38:  80 b7         in  r24, 0x30  ; 48
68
  3a:  8f 60         ori  r24, 0x0F  ; 15
69
  3c:  80 bf         out  0x30, r24  ; 48
70
71
  while(1) { 
72
  if(TCNT1 == 100) {
73
    PORTB ^= (1 << PB0);
74
  3e:  91 e0         ldi  r25, 0x01  ; 1
75
  DDRB |= (1 << PB0);
76
  PORTB |= (1 << PB0)| (1 << PB1);
77
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS12) | (1 << CS13);
78
79
  while(1) { 
80
  if(TCNT1 == 100) {
81
  40:  8f b5         in  r24, 0x2f  ; 47
82
  42:  84 36         cpi  r24, 0x64  ; 100
83
  44:  e9 f7         brne  .-6        ; 0x40 <__SREG__+0x1>
84
    PORTB ^= (1 << PB0);
85
  46:  88 b3         in  r24, 0x18  ; 24
86
  48:  89 27         eor  r24, r25
87
  4a:  88 bb         out  0x18, r24  ; 24
88
    TCNT1 = 0;
89
  4c:  1f bc         out  0x2f, r1  ; 47
90
  4e:  f8 cf         rjmp  .-16       ; 0x40 <__SREG__+0x1>
91
92
00000050 <_exit>:
93
  50:  f8 94         cli
94
95
00000052 <__stop_program>:
96
  52:  ff cf         rjmp  .-2        ; 0x52 <__stop_program>

von Thomas E. (thomase)


Lesenswert?

Das läuft auf meinem Attiny 25 so, wie du es dir vorstellst:
1
#include <avr/io.h> 
2
#include <avr/interrupt.h> 
3
4
int main(void) 
5
{ 
6
  
7
8
  DDRB |= (1 << PB0) | (1 << PB1);
9
  PORTB |= (1 << PB0)| (1 << PB1);
10
  
11
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
12
  TCCR0B |= (1<<CS02) | (1<<CS00);
13
14
15
  while(1) 
16
  { 
17
    if(TCNT0 > 200) 
18
    {
19
      PORTB ^= (1 << PB0);
20
      TCNT0 = 0;
21
    }
22
23
    if(TCNT1 > 200) 
24
    {
25
      PORTB ^= (1 << PB1);
26
      TCNT1 = 0;
27
    }
28
  }
29
}

Mal eine ganz doofe Frage: Ziehst du eigentlich auch deinem Programmer 
ab, um zu testen? PB0 und PB1 liegen nämlich auf MISO/MOSI.

mfg.

von Jörg E. (jackfritt)


Lesenswert?

Timer0 hat CS00-02 und Timer1 hat CS10-13 und die Bits liegen auch 
anders. Ich denke hier liegt dein Problem?

von A. F. (elagil)


Lesenswert?

> Mal eine ganz doofe Frage: Ziehst du eigentlich auch deinem Programmer
> ab, um zu testen? PB0 und PB1 liegen nämlich auf MISO/MOSI.

Oh! :) den habe ich tatsächlich noch dran :D probier ich demnächst mal 
ohne ;)

> Timer0 hat CS00-02 und Timer1 hat CS10-13 und die Bits liegen auch
> anders. Ich denke hier liegt dein Problem?

nein, ich habe die richtigen bits gesetzt, siehe oben

von A. F. (elagil)


Lesenswert?

Ich habe einen attiny45 auf breadboard an ein oszilloskop gehängt (PB0). 
Hier die Bilder und zugehörigen Codes:
Oszi-Einstellung: immer 10ms Timebase (damit komme ich auf ca.40 
ms/Periode, rechnerisch kommen 39ms raus, passt also)
0,1V/cm mit 1:10 Tastkopf -> 1V/cm (passt ungefähr)

Die Timer sind so definiert wie schon immer:
DDRB |= (1 << PB0) | (1 << PB1);
PORTB |= (1 << PB0)| (1 << PB1);

TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
TCCR0B |= (1<<CS02) | (1<<CS00);

1................. ganz seltsames bild ...
http://www.abload.de/img/dsc06341qjujl.jpg

if(TCNT1 > 200)
    {
      PORTB ^= (1 << PB0);
    TCNT0=0;
    TCNT1=0;
    }

2................. keine auslenkung ...
http://www.abload.de/img/dsc063421purk.jpg

if(TCNT1 > 200)
    {
      PORTB ^= (1 << PB0);
    TCNT1=0;
    }

3................. das normale rechteck ...
http://www.abload.de/img/dsc06343oxuq3.jpg

if(TCNT0 > 200)
    {
      PORTB ^= (1 << PB0);
    TCNT0=0;
    }

von Fred S. (kogitsune)


Lesenswert?

Das *.lss Listing ist in Ordnung: Registeradressen und Code passen zum 
Attiny45.

"thomase" hat Dich auf den noch eingesteckten Programmer aufmerksam 
gemacht. Nachdem Du mir vorher geantwortet hattest, dass an PB0 sonst 
nichts mehr hängt, war wohl doch noch der Programmer dran... Ist er 
jetzt immer noch verbunden?

Bei praktisch jedem Deiner Code-Schnipsel hast Du ++mehrere++ Dinge 
geändert. In der *.lss Datei schreibst Du
1
 if (TCNT1 == 100)...
Jetzt wieder
1
 if(TCNT1 > 200)...
.
Mir ist zwar klar, dass das nicht ändern sollte, aber trotzdem ist das 
kein guter Stil für die Fehlersuche. Zusätzlich veränderst Du immer 
wieder den Wert für den Timer-Vorteiler. Das ist im Allgemeinen kein 
guter Ansatz, um einen Fehler einzugrenzen.

Was nötig ist, um hier weiterzukommen:
- Dein aktuelles Programm
- der Aufbau (gutes Foto, Schaltplan, am besten auch mit den 
Verbindungen zum Oszi sichtbar)

von Walter S. (avatar)


Lesenswert?

Adrian Figueroa schrieb:
> TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
> TCCR0B |= (1<<CS02) | (1<<CS00);

da stimmt doch was mit deinen Bildern nicht, du stellst hier zwei total 
unterschiedliche Teiler ein, aber die sich ergebende Frequenz ist 
gleich???

von Electronics'nStuff (Gast)


Angehängte Dateien:

Lesenswert?

Damit nicht alle immer nachsehe gehen nmüssen..

von Electronics'nStuff (Gast)


Lesenswert?

Walter S. schrieb:
> Du stellst hier zwei total unterschiedliche Teiler ein

Nein, beide Male 1024.

@TE Watchdog Fuse gesetzt beim Attiny?

von Fred S. (kogitsune)


Lesenswert?

Electronics'nStuff schrieb:
> @TE Watchdog Fuse gesetzt beim Attiny?

Weiter oben hat der TE geschrieben, dass die High Fuse 0xDF ist, also 
ist der WDT aus.

von A. F. (elagil)


Lesenswert?

> "thomase" hat Dich auf den noch eingesteckten Programmer aufmerksam
> gemacht. Nachdem Du mir vorher geantwortet hattest, dass an PB0 sonst
> nichts mehr hängt, war wohl doch noch der Programmer dran... Ist er
> jetzt immer noch verbunden?

nein, nicht mehr.


Hier bilder vom Aufbau mit dem Code:
1
#include <avr/io.h> 
2
#include <avr/interrupt.h> 
3
4
int main(void) 
5
{ 
6
  
7
8
  DDRB |= (1 << PB0) | (1 << PB1);
9
  PORTB |= (1 << PB0)| (1 << PB1);
10
11
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
12
  TCCR0B |= (1<<CS02) | (1<<CS00);
13
14
15
  while(1) 
16
  { 
17
18
19
    if(TCNT1 > 200) 
20
    {
21
      PORTB ^= (1 << PB0);
22
    TCNT1=0;
23
    }
24
  }
25
}

Timebase immer noch 10ms, lange belichtet, damit man die Linie sieht.
Ich bekomme 5V Gleichspannung am Ausgang PB0.

http://www.abload.de/img/dsc0634525urq.jpg
http://www.abload.de/img/dsc06349s6u3u.jpg

von Thomas E. (thomase)


Lesenswert?

Adrian Figueroa schrieb:
> Hier bilder vom Aufbau
Am Controller fehlt ein 100nF Stützkondensator.

mfg.

von Jörg E. (jackfritt)


Lesenswert?

Hiermit gehts dann. Scheint was wegoptimiert zu werden?
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
int main(void)
5
{
6
7
  DDRB |= (1 << PB0) | (1 << PB1);
8
  PORTB |= (1 << PB0)| (1 << PB1);
9
10
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
11
  TCCR0B |= (1<<CS02) | (1<<CS00);
12
13
  while(1)
14
  {
15
    asm volatile("NOP");
16
    if(TCNT1 > 200)
17
    {
18
      PORTB ^= (1 << PB0);
19
    TCNT1=0;
20
    }
21
  }
22
}

von Fred S. (kogitsune)


Lesenswert?

Thomas Eckmann schrieb:
> Am Controller fehlt ein 100nF Stützkondensator.
Sehe ich auch so. Mit kurzen Leitungen, möglichst direkt von Pin 8 nach 
Pin 4. Und da kein BOD aktiviert ist, gleich noch einen Widerstand (15 k 
oder so) von Pin 8 nach RESET.

von A. F. (elagil)


Lesenswert?

> Hiermit gehts dann. Scheint was wegoptimiert zu werden?

Tatsächlich! :D

Im makefile steht: "optimization level s"

von A. F. (elagil)


Lesenswert?

ich habe einen hinzugefügt, keine änderung. noch ein bild:

50mV/cm Gleichspannungskompensiert (Amplitude ca. 150mV), Timebase 0,1us 
bei 5-Fach streckung! Das sind dann ca. 17Mhz... ?! Ich weiß ja nicht, 
was das sein soll, ich tippe auf eine wertlose Messung ;)

http://www.abload.de/img/dsc06350v9xoz.jpg

aber es geht mit dem "nop"... seltsam, dass er das für timer0 dann 
drinlässt

von Jörg E. (jackfritt)


Lesenswert?

Man kann mal die Profi´s fragen ob das ein Feature oder Bug is.
Hier liest bestimmt keiner mehr von denen mit :)

Sollte sich niemand melden einfach ein neues Thema aufmachen mit
aussagekräftiger Überschrift.

von A. F. (elagil)


Lesenswert?

mach ich mal ;) danke für die hilfe :)

von Fred S. (kogitsune)


Lesenswert?

Jörg Esser schrieb:
> Hiermit gehts dann. Scheint was wegoptimiert zu werden?
Wie bist Du darauf gekommen, Jörg?

von Walter S. (avatar)


Lesenswert?

Adrian Figueroa schrieb:
> if(TCNT1 > 200)

lass das doch mal weg um zu sehen ob der Ausgang richtig toggelt oder ob 
die Abfrage nie erfüllt ist

von A. F. (elagil)


Lesenswert?

das läuft einwandfrei
1
#include <avr/io.h>
2
3
int main(void)
4
{
5
6
  DDRB |= (1 << PB0);
7
8
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
9
10
  while(1)
11
  {
12
    if(1)
13
    {
14
      PORTB ^= (1 << PB0);
15
      TCNT1=0;
16
    }
17
  }
18
}

von Thomas E. (thomase)


Lesenswert?

Jörg Esser schrieb:
> Hiermit gehts dann. Scheint was wegoptimiert zu werden?
Unsinn.

Ich weiss ja nicht, was der WAI da veranstaltet. Aber ein 
funktionierendes Programm habe ich ihm schon gestern abend geschickt:

Thomas Eckmann schrieb:
> Das läuft auf meinem Attiny 25 so, wie du es dir vorstellst:

Wenn er das nimmt, für den Attiny45 kompiliert, mit Optimierung -0s, 
dann läuft das auch. So ein Popelkram ist absolut Pillepalle. Dafür 
braucht man 5 Minuten, wenn überhaupt. Und nicht 2 Tage, die das jetzt 
schon dauert.
Da wird nichts wegoptimiert und da wurde jetzt auch kein Compilerbug 
entdeckt.
Es bringt überhaupt nichts an irgendwelchen Einstellungen, sei es an den 
CS-Bits noch an der Optimierung rumzuspielen. Der Fehler liegt irgendwo 
anders. Mit hoher Wahrscheinlichkeit sitzt er vor dem PC.
Weil die Watchdog-Fuse gesetzt ist, das falsche Hexfile geflasht wird, 
irgendein vermurxtes Makefile benutzt wird, an statt sich das erzeugen 
zu lassen oder was auch immer. Nein. Und der Controller ist auch nicht 
kaputt.

mfg.

von A. F. (elagil)


Angehängte Dateien:

Lesenswert?

Was soll ich sagen? Es läuft eben nicht, auch wenn der Code korrekt ist.
Ich habe ein neues makefile gemacht und die fuses neu geflasht...

hier mal das makefile, ist das vielleicht kaputt?

von Thomas E. (thomase)


Lesenswert?

Adrian Figueroa schrieb:
> Was soll ich sagen? Es läuft eben nicht, auch wenn der Code korrekt ist.
> Ich habe ein neues makefile gemacht und die fuses neu geflasht...
> hier mal das makefile, ist das vielleicht kaputt?
Warum wurschtelst du dir damit überhaut einen ab? Lass dir das 
automatisch erzeugen.
Womit programmierst du überhaupt? Oder habe ich das irgendwo überlesen?

mfg.

von A. F. (elagil)


Lesenswert?

> Warum wurschtelst du dir damit überhaut einen ab? Lass dir das
> automatisch erzeugen.

dafür nehme ich mfile aus dem winavr paket. mit winavr und programmers 
notepad schreibe ich auch.

von Thomas E. (thomase)


Lesenswert?

Adrian Figueroa schrieb:
> dafür nehme ich mfile aus dem winavr paket. mit winavr und programmers
> notepad schreibe ich auch.
Installier dir AVR-Studio und du hast diese ganzen Probleme nicht.

mfg.

von Jörg E. (jackfritt)


Lesenswert?

Also ich kann das hier nachvollziehen mit Winavr unter eclipse. Basta!
Keine Ahnung was avrstudio macht.
Um das ganz genau zu sehen muss man sich halt mal den ganzen Compile 
Prozess
und Assembler Code anschauen. Einmal mit NOP und einmal ohne.Fertig.

Sorry aufm iPad geschrieben.

von Thomas E. (thomase)


Lesenswert?

Jörg Esser schrieb:
> rozess
> und Assembler Code anschauen. Einmal mit NOP und einmal ohne.Fertig.
Wenn der einzige Unterschied dabei, nicht das eingefügte NOP ist, ist 
das Ganze absoluter Müll.

mfg.

von A. F. (elagil)


Lesenswert?

ich habe atmel studio ausprobiert. natürlich ist mein usbasp dazu nicht 
kompatibel, deswegen benutze ich avrdude zum flashen der .hex, die der 
debugger erzeugt: kommt das gleiche raus.

ich benutze die vorlage für den attiny45, also kann mein makefile nicht 
falsch sein!

Timer0 geht, Timer1 nicht.

von Walter S. (avatar)


Lesenswert?

wenn es mit nop geht dann bitte die beiden assembler listing posten bzw. 
anschauen,
da müsste dann ja ein Unterschied zu sehen sein

von Fred S. (kogitsune)


Lesenswert?

Und wo ist das NOP?

von A. F. (elagil)


Lesenswert?

ich habe das falsche hochgeladen, darum gelöscht ;)

http://www.diffnow.com/?report=8293e

von Fred S. (kogitsune)


Lesenswert?

Und auf den gelöschten Beitrag bezog sich mein Kommentar...!

von A. F. (elagil)


Lesenswert?

eben, das mit dem nop habe ich gar nicht hochgeladen!

von F. F. (foldi)


Lesenswert?

Jörg Esser schrieb:
> Sorry aufm iPad geschrieben.

:-) Das ist der beste Satz seit langem und nicht nur in diesem Thread.

von F. F. (foldi)


Lesenswert?

Bin noch ziemlich neu in C und mit Timer hab ich auch nichts gemacht 
(kommt bald), aber da ich mit dem Tiny 13 was machen will mit C und 
schon gemacht habe, hab ich natürlich auch schon die Auswirkungen des 
fehlenden 100nF gespürt. Da kommt es zu so manchem komischen Verhalten.
Unter Timer 1 stand, dass er eine Pause von 100 µs braucht um sich zu 
stabilisieren. Kann das auch damit zu tun haben? Oder ist die Frage 
völlig bescheuert?

von A. F. (elagil)


Lesenswert?

> Kann das auch damit zu tun haben?

aber dann sollte er doch nach 100us laufen? :)

von F. F. (foldi)


Lesenswert?

Adrian Figueroa schrieb:
>> Kann das auch damit zu tun haben?
>
> aber dann sollte er doch nach 100us laufen? :)

Das ist eben die Frage, die ich mir stellte. Kommt er so überhaupt in 
den richtigen Takt?
Auch die 100nF sind so ein Ding. Hatte schon ganz viel mit nem ATmega 
328 gemacht und da gab es nie Probleme auf dem Steckbrett, auch ohne 
einen Kondensator und erst nachdem ich mir nicht erklären konnte, wieso 
der Tiny so ein merkwürdiges Verhalten an den Tag legte, machte ich mal 
die 100nF dazu und siehe da, alles lief wie es erwartet wurde.

Ohne, dass ich jetzt hier zur Schlacht um die Entwicklungsumgebung 
aufrufen will, aber ich schließe mich einem Vorredner an und finde es 
auch richtig das Atmel Studio zu nehmen.
Es ist ein Monster und auf meinem Netbook braucht es etwas, bis alles da 
ist, aber da das nun mal die neuste Software und das Zugpferd von AVM 
ist, finde ich sollte man das nehmen. Zumindest für Testzwecke, wenn es 
auf anderen Umgebungen Fehler gibt.

von A. F. (elagil)


Lesenswert?

> finde es auch richtig das Atmel Studio zu nehmen.

ja, das überleg ich mir, nur wird mein programmer sowieso nicht direkt 
unterstützt (auch wenn das nicht unbedingt tragisch ist)

von F. F. (foldi)


Lesenswert?

Adrian Figueroa schrieb:
>> finde es auch richtig das Atmel Studio zu nehmen.
>
> ja, das überleg ich mir, nur wird mein programmer sowieso nicht direkt
> unterstützt (auch wenn das nicht unbedingt tragisch ist)


So ein "Dragon" ist eine feine Sache und kostet nicht viel. Damit ist 
dann auch debuggen ne feine Sache.

Da ich selbst noch ein blutiger Anfänger bin, hat es was gebraucht bis 
ich beim Drachen war. Ist jetzt mein "Lieblingsspielzeug".

von Markus M. (adrock)


Lesenswert?

Der Drachen ist das Schweizer Taschenmesser überhaupt... hatte mit dem 
STK-500 angefangen und mir dann bald den Dragon wg. USB geholt...

Programmieren (SPI, HV, JTAG, [PDI]), Onboard-Debuggen (JTAG, DebugWire) 
und das für fast alle AVRs von Tiny über Mega bis XMega. Was will man 
mehr?

Grüße
Markus

von holger (Gast)


Lesenswert?

Echt Geisterstunde hier;)

C Code sieht gut aus, Assembler Listing sieht gut aus.
ATTin45 hat da sicher keinen Bug, das hätte man schon früher gemerkt.

Das einzige was scheisse aussieht ist der kleine einsame Käfer
auf dem Steckbrett. Man muss kein Hellseher sein um da
schlimmes zu denken.

Vieleicht hat er ja Timer1 per Fuse auf ATTiny15 kompatibel
gefused? Aber das würde es auch nicht erklären.

Ich bin mal gespannt ob hier noch irgendeine sinnvolle
Erklärung zu dem Phänomen rauskommt.

von Fred S. (kogitsune)


Angehängte Dateien:

Lesenswert?

Thomas Eckmann schrieb:
> Wenn er das nimmt, für den Attiny45 kompiliert, mit Optimierung -0s,
> dann läuft das auch. .....
Du lässt Dich hier ja ganz schön überheblich über den TE aus.
Ich hatte auch massive Zweifel, konnte die Ergebnisse des TEs aber mit 
einem Attiny45-20PU mit den o.g. Fuses (siehe 
Beitrag "Re: Attiny45, timer tut nichts?" ) 100% verifizieren.
Einen Attiny25 habe ich nicht da, kann also Dein Ergebnis hinsichtlich 
des Attiny25 nicht testen. Mit dem Attiny85 erhalte ich identische 
Ergebnisse wie unten beschrieben.
Kompiliert mit -Os (-O1 ändert nichts), Atmel Studio 6.0.1882, d.h. 
AVR_8_bit_GNU_Toolchain_3.4.0_663.
Hardware: Mit 5V betriebener Attiny45-20PU (Date code (?) 1108, auf der 
Unterseite steht noch "L8  TAIWAN 16") auf einem STK500.

Wie schon der TE fand, geht dies:
1
  while(1) {
2
    asm volatile("NOP");    
3
  6a:  00 00         nop
4
    if(TCNT1 > 200) {
5
  6c:  8f b5         in  r24, 0x2f  ; 47
6
  6e:  89 3c         cpi  r24, 0xC9  ; 201
7
  70:  e0 f3         brcs  .-8        ; 0x6a <main+0x14>
8
      PORTB ^= (1 << PB0);
9
  72:  88 b3         in  r24, 0x18  ; 24
10
  74:  89 27         eor  r24, r25
11
  76:  88 bb         out  0x18, r24  ; 24
12
      TCNT1 = 0;
13
  78:  1f bc         out  0x2f, r1  ; 47
14
  7a:  f7 cf         rjmp  .-18       ; 0x6a <main+0x14>
Das aber nicht:
1
  while(1) {
2
    //asm volatile("NOP");    
3
    if(TCNT1 > 200) {
4
  6a:  8f b5         in  r24, 0x2f  ; 47
5
  6c:  89 3c         cpi  r24, 0xC9  ; 201
6
  6e:  e8 f3         brcs  .-6        ; 0x6a <main+0x14>
7
      PORTB ^= (1 << PB0);
8
  70:  88 b3         in  r24, 0x18  ; 24
9
  72:  89 27         eor  r24, r25
10
  74:  88 bb         out  0x18, r24  ; 24
11
      TCNT1 = 0;
12
  76:  1f bc         out  0x2f, r1  ; 47
13
  78:  f8 cf         rjmp  .-16       ; 0x6a <main+0x14>


Bei identischer Initialisierung funktioniert (d.h. 20Hz Rechteck an PB0) 
auch Folgendes:
1
  while(1) {    
2
    if (TCNT1 > 200) {
3
      PORTB^=(1<<PB0);
4
  68:  91 e0         ldi  r25, 0x01  ; 1
5
{
6
  DDRB |= (1 << PB0) | (1 << PB1);
7
  PORTB |= (1 << PB0)| (1 << PB1);
8
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
9
  while(1) {    
10
    if (TCNT1 > 200) {
11
  6a:  8f b5         in  r24, 0x2f  ; 47
12
  6c:  89 3c         cpi  r24, 0xC9  ; 201
13
  6e:  e8 f3         brcs  .-6        ; 0x6a <main+0x14>
14
      PORTB^=(1<<PB0);
15
  70:  88 b3         in  r24, 0x18  ; 24
16
  72:  89 27         eor  r24, r25
17
  74:  88 bb         out  0x18, r24  ; 24
18
      TCNT1=0;
19
  76:  1f bc         out  0x2f, r1  ; 47
20
      asm volatile("NOP");
21
  78:  00 00         nop
22
  7a:  f7 cf         rjmp  .-18       ; 0x6a <main+0x14>
Relevant scheint das Nullen des TCNT1 zu sein, denn mit
1
  while(1) {    
2
    if (TCNT1 > 200) {
3
  6a:  8f b5         in  r24, 0x2f  ; 47
4
  6c:  89 3c         cpi  r24, 0xC9  ; 201
5
  6e:  e8 f3         brcs  .-6        ; 0x6a <main+0x14>
6
      PORTB^=(1<<PB0);
7
  70:  88 b3         in  r24, 0x18  ; 24
8
  72:  89 27         eor  r24, r25
9
  74:  88 bb         out  0x18, r24  ; 24
10
  76:  f9 cf         rjmp  .-14       ; 0x6a <main+0x14>
bekomme ich das erwartete Signal (schnelles Umschalten an PB0 bei jedem 
Durchgang wenn TCNT1>200) -- siehe Bild.
Dies wird auch bestätigt durch korrektes Funktionieren (Rechteck an PB0 
und Rechteck der halben Frequenz an PB1) hiervon:
1
  while(1) {    
2
    PORTB=TCNT1;  
3
  68:  8f b5         in  r24, 0x2f  ; 47
4
  6a:  88 bb         out  0x18, r24  ; 24
5
  6c:  fd cf         rjmp  .-6        ; 0x68 <main+0x12>
Die Ergebnisse bleiben entsprechend, wenn man für das Toggle des PB0
1
      PINB|=(1<<PB0);  
2
  6e:  b0 9a         sbi  0x16, 0  ; 22
schreibt, so dass nicht 3 Maschinenbefehle nötig sind.

Ich kann mich nicht erinnern, in den letzten Jahren je die Notwendigkeit 
gesehen zu haben, einen TC manuell auf Null zu setzen, wo es doch den 
CTC-Modus gibt! Das wird der größten Mehrheit der Entwickler so gegangen 
sein...
Ein Prozessor-Bug ist durchaus als Ursache denkbar, insbesondere da das 
Zusammenspiel der Verzögerungen beim TimerCounter1 beim Attiny45 im 
Datenblatt doch etwas kryptisch beschrieben ist.
Im Netz fanden sich Hinweise auf ein Problem mit dem TC1 beim Attiny45 
mit BASCOM. Da ich von BASCOM keine Ahnung habe und die entsprechenden 
Themen nicht verfolgt habe, weiß ich nicht, ob das ein reines BASCOM 
Problem ist/war, oder ob die BASCOM Entwickler auf das hier diskutierte 
mögliche Problem mit dem ATtiny45 hereingefallen sind.

von F. F. (foldi)


Lesenswert?

@ Fred S. (kogitsune)
Hab auch noch ein paar von den Tinys. Danke für die deutlichen 
Ausführungen.
Dann weiß ich ja woran ich denken muss,  wenn ich mit den Timern 
Probleme kriege.

von Jörg E. (jackfritt)


Lesenswert?

Ich konnte das bei mir auch mit einem atiny85 nachstellen.Sorry hatte 
ich vergessen zu erwähnen. Sogar auf einem Testboard, also nix mit 100nf 
etc.

von Jörg E. (jackfritt)


Lesenswert?

Thomas schrieb er würde AVR-Studio nehmen. Was passiert dort?

von Markus M. (adrock)


Lesenswert?

Hi,

Im Datenblatt steht beim TCNT1 Register...

"Timer/Counter1 is realized as an up counter with read and write access. 
Due to synchronization of the CPU, Timer/Counter1 data written into 
Timer/Counter1 is delayed by one and half CPU clock cycles in 
synchronous mode and at most one CPU clock cycles for asynchronous mode"

Das hört sich zumindest schonmal ein bisschen "verdächtig" an.

Evtl. läuft da wirklich etwas schief, wenn in sehr kurzen Abständen 
hintereinander auf das TCNT1 lesend/schreibend zugegriffen wird.

Normalerweise würde ich es auch immer vermeiden, schreibend auf den 
Counter zuzugreifen während er läuft.

Im Errata steht nix, aber das hat ja nichts zu sagen...

Grüße
Markus

von Adrian (Gast)


Lesenswert?

> Normalerweise würde ich es auch immer vermeiden, schreibend auf den
> Counter zuzugreifen während er läuft.

Im Grunde macht der CTC Mode ja nichts anderes?

Beim Timer0 ist es zwar auch nicht weiter problematisch, das Nop bringt 
aber immerhin einen ganzen Takt mehr, das ist vielleicht genug.

von Fred S. (kogitsune)


Lesenswert?

Noch eine Ergänzung:
Im Attiny15-Kompatibilitätsmodus (low Fuse 0xF3 [SUT1:0=0b11, 
CKSEL=0b0011], high Fuse 0xDF und extended Fuse 0xFF) führt dieser Code 
(Timer- und Port-Initialisierung wie oben, d.h.
1
  DDRB |= (1 << PB0) | (1 << PB1);
2
  PORTB |= (1 << PB0)| (1 << PB1);
3
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
) zu einem Rechtecksignal an PB0:
1
  while(1) {    
2
    if (TCNT1 > 200 ) {
3
  68:  8f b5         in  r24, 0x2f  ; 47
4
  6a:  89 3c         cpi  r24, 0xC9  ; 201
5
  6c:  e8 f3         brcs  .-6        ; 0x68 <main+0x12>
6
      PINB|=(1<<PB0);  
7
  6e:  b0 9a         sbi  0x16, 0  ; 22
8
      TCNT1=0;  
9
  70:  1f bc         out  0x2f, r1  ; 47
10
  72:  fa cf         rjmp  .-12       ; 0x68 <main+0x12>

Ändert man die low Fuse auf 0xE2, ist wieder ein NOP erforderlich, damit 
ein Rechtecksignal (natürlich anderer Frequenz!) entsteht:
1
  while(1) {    
2
    if (TCNT1 > 200 ) {
3
  68:  8f b5         in  r24, 0x2f  ; 47
4
  6a:  89 3c         cpi  r24, 0xC9  ; 201
5
  6c:  e8 f3         brcs  .-6        ; 0x68 <main+0x12>
6
      PINB|=(1<<PB0);  
7
  6e:  b0 9a         sbi  0x16, 0  ; 22
8
      TCNT1=0;  
9
  70:  1f bc         out  0x2f, r1  ; 47
10
      asm volatile("NOP");
11
  72:  00 00         nop
12
  74:  f9 cf         rjmp  .-14       ; 0x68 <main+0x12>

von Fred S. (kogitsune)


Angehängte Dateien:

Lesenswert?

Und noch ein Detail: Im asynchronen Clock-Modus geht's ohne NOP!
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
int main(void)
5
{
6
  // set async mode, wait until locked, make PLL clock for TC1 
7
  PLLCSR=(1<<PLLE);
8
  _delay_us(200); // datasheet: 100us should suffice
9
  while (!(PLLCSR&(1<<PLOCK)));
10
  PLLCSR|=(1<<PCKE);
11
  
12
  DDRB |= (1 << PB0) | (1 << PB1);
13
  PORTB |= (1 << PB0)| (1 << PB1);
14
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
15
  while(1) {    
16
    if (TCNT1 > 200 ) {
17
      PINB|=(1<<PB0);  
18
      TCNT1=0;  
19
      //asm volatile("NOP");
20
    }    
21
  }
22
}
(*.lss siehe Anlage; kompiliert mit F_CPU=8000000UL).
An PB0 steht ein 158 Hz Signal an. Das passt genau zum asynchronen 64 
MHz Takt für den TC1.

von Jörg E. (jackfritt)


Lesenswert?

Um das Thema nochmal aufzuwärmen.
Es handelt sich um einen Bug im alten GCC.
Mit GCC 4.8 funktioniert nun der folgender Code.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
int main(void)
5
{
6
7
  DDRB |= (1 << PB0) | (1 << PB1);
8
  PORTB |= (1 << PB0)| (1 << PB1);
9
10
  TCCR1 |= (1 << CS10) | (1 << CS11) | (1 << CS13);
11
  TCCR0B |= (1<<CS02) | (1<<CS00);
12
13
  while(1)
14
  {
15
    //asm volatile("NOP");
16
    if(TCNT1 > 200)
17
    {
18
      PORTB ^= (1 << PB0);
19
    TCNT1=0;
20
    }
21
  }
22
}

Wer sein WINAVR updaten möchte, für den gibts hier ne Anleitung
Beitrag "Update von Winavr2010 auf gcc 4.8 Howto"

von Fred S. (kogitsune)


Angehängte Dateien:

Lesenswert?

Hallo Jörg,

zeigst Du bitte auch die zugehörige *.lss? Das ursprüngliche Beispiel in 
c hatte ich mit Atmel Studio 6 (GCC 4.6.1) kompiliert.

Allerdings lässt sich das Problem auch mit Assembler nachweisen:
1
  .org 0        ; interrupt vectors not required, program starts right here 
2
            ; stack initialization not required
3
  eor r1,r1      ; clear reg
4
  sbi DDRB, 0
5
  sbi PORTB, 0
6
  ldi r16, (1 << CS10)|(1<<CS12) ; timer at F_CPU/16 = 500 kHz
7
  out TCCR1, r16
8
  
9
testcnt:
10
  in r16, TCNT1
11
  cpi r16, 201
12
  brcs testcnt
13
  sbi PINB, 0
14
  out TCNT1, r1    ; zero counter value
15
  //nop          ; 1 cycle
16
  rjmp testcnt    ; 2 cycles for jump
Mit auskommentiertem "nop" (wie im Listing oben) erhalte ich an PB0 das 
Signal "2 cycles", füge ich das "nop" ein, erscheint das Signal "3 
cycles" an PB0.

Gruß

Fred

von Fred S. (kogitsune)


Lesenswert?

Vergessen zu erwähnen: Attiny im Beispiel läuft mit 8 MHz.

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.