ATTiny13 dreht völlig durch!

OP Persönliche Seite #1497617
Lesenswert?

Hallo,
ich habe einen einfachen Timer geschrieben und ihn als mein zweites
Projekt (das erste war PORT-Abschalten) nicht in Sisy-Avr sondern in
AVR-Studio mit C-Unterstützung compiliert.
Jetzt will der Controller nicht mehr!
Wenn ich ihn anschließe (JA, RESET auf Plus und Spannung stabilisiert!)
und an PORTB0 und PORTB1 Leds mit 1kOhm Vorwiederstand hänge, dann gehen 
die
Leds mal einzaln, mal zusammen an.
Habt ihr eine Ahnung?
Hier der Code:
1
#include <avr\io.h>
2
#include <avr\interrupt.h>
3

4
int set;
5
int bla;
6

7
ISR(TIM0_OVF_vect){
8
if(set==0) {
9
PORTB = 0b00000110;set = 1;}
10
else{
11
PORTB = 0b00000000;set = 0;}
12
}
13

14
void init(){
15
  TCCR0B = 0b00000100;   // Teiler 1/256
16
  TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
17
  DDRB = 0b00000111;
18
  set = 0;
19
  sei();      
20
}
21

22
int main(void){
23
init();
24
while(1){
25
PORTB = 0b00000001;
26
bla = 0;
27
}
28
return 0;
29
}

mit freundlichen Grüßen,
Valentin
Gast #1497626
Lesenswert?

Ähm... wie bitte willst du sehen ob die LEDs ein paar Mikrosekunden an 
sind ?
Du schaltest zwei davon in der main() immer aus.. selbst wenn sie im 
Intrrupt angemacht werden, danach werden sie in main sofort wieder 
ausgeschaltet :-)

Ausserdem sollte "set" volatile sein.
Gast #1497645
Lesenswert?

>Achso, hätte ich fast vergessen,
>die Fuses sind auf 128khz Oszi-Frequenz eingestellt!

Das ändert nix.
Ich habe Deine Frage beantwortet und dir den Grund, warum das Programm 
nicht das macht du willst, genannt.
#1497669
Lesenswert?

1
#include <avr\io.h>
2
#include <avr\interrupt.h>
3

4
int set;     /* volatile unsigned char set */ 
5
int bla;     /* entfernen, wird nur initialisiert */
6

7
ISR(TIM0_OVF_vect){
8
if(set==0) {PORTB = 0b00000110;set = 1;} /* 1 und 2 an */
9
else{PORTB = 0b00000000;set = 0;}  /* alles aus */
10
           /* an B0 und B1 hängt jeweils eine LED, wozu schaltest du B2? */
11
           /* besser mit ! oder ~ arbeiten. -->   Musterinvertierung */
12
}
13

14
void init(){
15
  TCCR0B = 0b00000100;   // Teiler 1/256
16
  TIMSK0 |= _BV(0);      // Interrupt bei Überlauf also alle 500 ms
17
  DDRB = 0b00000111;     /* zwei LEDs an, drei geschaltet  */
18
  set = 0;
19
  sei();      
20
}
21

22
int main(void){
23
init();
24
while(1){
25
PORTB = 0b00000001;  /*eine an */
26
bla = 0;  /* gefasel. weglassen.  */
27
}
28
return 0;
29
}
OP Persönliche Seite #1497690
Lesenswert?

Vielen Dank für die Antworten!
Also jetzt sieht mein Code so aus:
1
#include <avr\io.h>
2
#include <avr\interrupt.h>
3

4
volatile unsigned char set;
5

6

7
ISR(TIM0_OVF_vect){
8
if(set==0) {
9
PORTB = 0b00000011;set = 1;}
10
else{
11
PORTB = 0b00000000;set = 0;}
12
}
13

14
void init(){
15
  TCCR0B = 0b00000100;   // Teiler 1/256
16
  TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
17
  DDRB = 0b00000011;
18
  set = 0;
19
  sei();      
20
}
21

22
int main(void){
23
init();
24
while(1){
25
PORTB = 0b00000001;
26
}
27
return 0;
28
}
Allerdings geht die LED an PORTB2 immer noch nicht an.
Und wie geht das mit dem Simulieren?
Valentin
#1497691
Lesenswert?

ich habe nichts repariert, sondern nur kommentiert, was ich ändern 
würde. Insbesonders das volatile. Leider weiss ich nicht, ob der Timer 
sich selbst nach Ablauf startet bzw. durchläuft, oder ob man das zu Fuss 
machen muss, in diesem Falle hat der Programmierer noch was vor sich.

Den Rest bitte den Kommentaren entnehmen.

Robert
Gast #1497698
Lesenswert?

Bohh.. leute..

in main ist ein schleife die portb auf 1 setzt.
immer wieder.

mag zwar sein, daß man bei nur 128 khz ein gaaanz kurzes blitzen der 
anderen led sehen könnte, aber so ist das vermutlich nicht gedacht

blind ??
#1497701
Lesenswert?

du musst den timer auch schon neu laden!
sonst bringt das nichts!
lade den timer am besten schon im init um, und besser ist es
wenn du im timer noch nen zähler drin hast,
sprich der timer muss x mal aufgerufen werden,
rechne mal hoch bei wie viel hz du da schaltest!
irgend wann ist der impuls zu kurz und die led bleibt dunkel
aber lade mal den timer vor!

hier von nem 2313er der code:

// achtung etwas viel overhead. is mir uart und co... und tasten von 
meiner schreibtisch lampe abervielleicht findest du ja stücke die du 
gebrauchen kannst,...


#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>

  // Ceramic Resonator
  #ifndef F_CPU
  #define F_CPU 20000000 // 4MHz
  #endif

  // UART
  #define UART_BAUD_RATE 9600
  #define 
UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)((F_CPU)/((UART_BAUD_RATE)*16L)-1)



volatile uint8_t     Run = 0;
volatile uint8_t on_kk1  = 50;
volatile uint8_t on_kk2  = 30;

volatile uint8_t kk1  = 0;
volatile uint8_t kk2  = 0;

volatile uint16_t fadeout  = 2000;


ISR(TIMER0_OVF_vect){
cli();
  if(Run==0){
    kk1 = on_kk1;
    kk2 = on_kk2;
    Run = 50;
    if(kk1 == 0 && kk2 == 0){
      PORTB|=4;
    } else {
      PORTB&=~4;
    }
  } else {

    if(kk1 > 0){
      kk1 --;
      PORTB|=1;
    } else {
      PORTB&=~1;
    }
    if(kk2 > 0){
      kk2 --;
      PORTB|=2;
    } else {
      PORTB&=~2;
    }
  }
 Run --;


 if(fadeout != 0)fadeout --;

 if(fadeout == 1){
  if(on_kk1 > 0){ on_kk1 --; }
  if(on_kk2 > 0){  on_kk2 --; }
  fadeout = 100;
 }

TCNT0 = 50;
 sei();
}

int main(void)
{



 DDRB=0xFF;
 PORTB=0x00;

 DDRD=0xFF;
 PORTD=0x00;

  // USART
  UBRRH =(uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
  UBRRL =(uint8_t) UART_BAUD_CALC(UART_BAUD_RATE,F_CPU);

  UCSRB = (1<<RXEN) | (1<<TXEN);  // enable receiver and transmitter
  UCSRC = (3<<UCSZ0);        // 8 bit (default: asynchronous, no 
parity,1stop-bit)

  // Set values for Timer 0: No Prescaler, Timer start, Preload
  TCCR0B |= (1 << CS01); // TINY
  TIMSK  |= (1 << TOIE0);

DDRD  &= ~(1<<DDD3);  /* Pin PC7 als Eingang */
DDRD  &= ~(1<<DDD5);  /* Pin PC7 als Eingang */
DDRD  &= ~(1<<DDD4);  /* Pin PC7 als Eingang */
DDRD  &= ~(1<<DDD3);  /* Pin PC7 als Eingang */
DDRD  &= ~(1<<DDD6);  /* Pin PC7 als Eingang */
DDRD  &= ~(1<<DDD2);  /* Pin PC7 als Eingang */
//PORTB |= (1<<PB5);

  // VARIABLES
  uint8_t get;


  // PROGRAM

  // wait for empty transmit buffer
  while (!(UCSRA & (1<<UDRE)));
  /* put data into buffer, sends the data*/
  UDR = 'x';

 TCNT0 = 80;
 sei();

  while(1) // forever
  {
  if ( PIND & (1<<PIND4) ) {  // Knopf 1
    fadeout =0;
    on_kk1 = 55;
    on_kk2 = 55;

  }
  if ( PIND & (1<<PIND5) ) {  // Knopf 2
    fadeout = 5;
  }
  }

}
OP Persönliche Seite #1497704
Lesenswert?

Hier nochmal der Code:
1
#include <avr\io.h>
2
#include <avr\interrupt.h>
3

4
volatile unsigned char set;
5

6

7
ISR(TIM0_OVF_vect){
8
if(set==0) {
9
PORTB = 0b00000011;set = 1;}
10
else{
11
PORTB = 0b00000000;set = 0;}
12
}
13

14
void init(){
15
  TCCR0B = 0b00000100;   // Teiler 1/256
16
  TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
17
  DDRB = 0b00000011;
18
  set = 0;
19
  sei();      
20
}
21

22
int main(void){
23
init();
24
while(1){
25
PORTB = PORTB | 0b00000001;
26
}
27
return 0;
28
}

Kann man das Set auch vielleicht mit einem bool machen?
Valentin
OP Persönliche Seite #1497714
Lesenswert?

Ohhh, also per NOT oder XOR! Das heißt in GCC also "!"!
Danke
Kann ich die Schleife einfach leer lassen? Oder kürzt der die dann weg?
Und wie geht das mit dem Simulator?
Valentin

PS: Hier der Code:
1
#include <avr\io.h>
2
#include <avr\interrupt.h>
3

4
volatile unsigned char set;
5

6

7
ISR(TIM0_OVF_vect){
8
PORTB = PORTB ^ 0b00000011;set = 1;}
9
}
10

11
void init(){
12
  TCCR0B = 0b00000100;   // Teiler 1/256
13
  TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
14
  DDRB = 0b00000011;
15
  set = 0;
16
  sei();      
17
}
18

19
int main(void){
20
init();
21
while(1){}
22
return 0;
23
}
#1498889
Lesenswert?

Dein Programm ist mitlerweile ein heftiges Sammelsurium an 
Sschreibweisen. Nur die eine, die du eigentlich benutzen solltest, die 
ist nicht dabei :-)

Das ändert aber immer noch nichts daran, dass dein Timer zu schnell 
läuft. So kannst du die Overflows noch weiter runterteilen.
1
#include <avr\io.h>
2
#include <avr\interrupt.h>
3

4
unsigned char counter;
5

6
ISR(TIM0_OVF_vect)
7
{
8
  counter++;
9

10
  if( counter == 7 )    // ergbit bei 1Mhz ca. 0.5 Sekunden bei Presc. 256
11
  {
12
     PORTB = PORTB ^ ( (1<<PB0) | (1<<PB1) );
13
     counter = 0;
14
  }
15
}
16

17
void init()
18
{
19
  TCCR0B = ( 1 << CS02 );    // Teiler 1/256
20
  TIMSK0 = ( 1 << TOIE0 );   // Interrupt bei Überlauf
21

22
  DDRB = (1<<PB0) | (1<<PB1);
23

24
  sei();      
25
}
26

27
int main(void)
28
{
29
  init();
30

31
  while(1)
32
  {
33
  }
34

35
  return 0;
36
}
#1498920
Lesenswert?

Mal abgesehen von all dem Gesagten: das ist sehr schlechter Stil:
1
>   TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
und überdies falsch.  Bit 0 in TIMSK0 gips beim Tiny13 nicht.  Das wäre 
nicht passiert, wenn Du gleich
1
TIMSK0 |= (1<<TOIE0);
geschrieben hättest, wie es sauberer Programmierstil erfordert hätte. 
Der ist nämlich nicht dazu da, fremde Schönheitsideale zu befriedigen, 
sondern sehr nützlich, um sich selbst vor diesem und vielen anderen 
solchen Fehlern zu bewahren.

Aus langer Erfahrung:  So wie ein Programm aussieht, ist es meistens 
auch.  In Deinem Fall sieht schon der kurze Schnipsel so aus, als wäre 
es nicht der Tiny13, der am völligen Durchdrehen ist.
OP Persönliche Seite #1499125
Lesenswert?

So, ich habe eure Tipps mal umgesetzt. Ich benutze aber den internen 
Takt auf 128Khz mit Vorteiler 256 und dann wird das Ganze noch durch 255 
geteilt, bis es zum Overflow kommt. Das gibt meiner Rechnung nach gerade 
mal 1,9 Hz.
Deshalb habe ich den Teiler weggelassen. Hier mein endgültiges Programm:
1
#include <avr\io.h>
2
#include <avr\interrupt.h>
3

4
ISR(TIM0_OVF_vect)
5
{
6
     PORTB = PORTB ^ ( (1<<PB0) | (1<<PB1) );
7
}
8

9
void init()
10
{
11
  TCCR0B = ( 1 << CS02 );    // Teiler 1/256
12
  TIMSK0 = ( 1 << TOIE0 );   // Interrupt bei Überlauf
13
  DDRB = (1<<PB0) | (1<<PB1);
14
  sei();      
15
}
16

17
int main(void)
18
{
19
  init();
20

21
  while(1)
22
  {
23
  }
24

25
  return 0;
26
}
Vielen Dank an alle!!!
Valentin
OP Persönliche Seite #1500231
Lesenswert?

Jetzt wollte ich mein Programm mal auf einen ATMEGA32 transferieren, und 
dabei nur bis 250 zählen. Ich verwende aber wieder Timer0.
Allerdings meint AVR Studio nun, dass TCCR0 kein COM0-Bit hat.
Hier der Code:
1
...
2
ISR (TIMER0_COMPA_vect){
3
PORTB = PORTB ^ ( (1<<PB0) | (1<<PB1) );
4
}
5
...
6
TCCR0 =  (1<<CS02)|(1<<COM0);// Teiler 1/256, Modus: Zählen bis //Vergleichswert
7
   OCR0 = 250;   // Vergleichswert speichern
8
  TIMSK = (1<<TOIE0);//interrupt einschalten
9
  TIFR = (1<<OCF0); //Interrupt bei CompareMatch
10
  sei();//Interrupts einschalten
11
...
Danke für die Antworten,
Valentin

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