mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATTiny13 dreht völlig durch!


Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <avr\io.h>
#include <avr\interrupt.h>

int set;
int bla;

ISR(TIM0_OVF_vect){
if(set==0) {
PORTB = 0b00000110;set = 1;}
else{
PORTB = 0b00000000;set = 0;}
}

void init(){
  TCCR0B = 0b00000100;   // Teiler 1/256
  TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
  DDRB = 0b00000111;
  set = 0;
  sei();      
}

int main(void){
init();
while(1){
PORTB = 0b00000001;
bla = 0;
}
return 0;
}

mit freundlichen Grüßen,
Valentin

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, hätte ich fast vergessen,
die Fuses sind auf 128khz Oszi-Frequenz eingestellt!
Was meinst du mit dem volatile?

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Jetzt will der Controller nicht mehr!
So ein kurzes Programm könntest du im AVR-Studio auch einfach mal 
simulieren...

> dann gehen die Leds mal einzaln, mal zusammen an.
Abhängig von was?

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: R. Freitag (rfr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr\io.h>
#include <avr\interrupt.h>

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

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

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

int main(void){
init();
while(1){
PORTB = 0b00000001;  /*eine an */
bla = 0;  /* gefasel. weglassen.  */
}
return 0;
}

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das funktioniert nach wie vor nicht.

Autor: Ben ___ (burning_silicon)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schaltung her!

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Quatsch. Das Programm ist falsch.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stützkondensator vergessen mit häufigem Reset als Folge?

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Antworten!
Also jetzt sieht mein Code so aus:
#include <avr\io.h>
#include <avr\interrupt.h>

volatile unsigned char set;


ISR(TIM0_OVF_vect){
if(set==0) {
PORTB = 0b00000011;set = 1;}
else{
PORTB = 0b00000000;set = 0;}
}

void init(){
  TCCR0B = 0b00000100;   // Teiler 1/256
  TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
  DDRB = 0b00000011;
  set = 0;
  sei();      
}

int main(void){
init();
while(1){
PORTB = 0b00000001;
}
return 0;
}
Allerdings geht die LED an PORTB2 immer noch nicht an.
Und wie geht das mit dem Simulieren?
Valentin

Autor: R. Freitag (rfr)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: R. Freitag (rfr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lass das setzen der LED in main mal weg. Setze dafür die LED in der ISR. 
Verwende dort Toggelbefehle.

Gruss

Robert

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ??

Autor: Möhre X. (keks0r)
Datum:

Bewertung
0 lesenswert
nicht 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;
  }
  }

}

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohhh, das habe ich garnicht gesehen!!!!
Gut.
Also muss ich da den Port mit einer Oder-Verknüpfung beschreiben!
Was für Togglebefehle? Die gibts in Sisy-C nicht!
Und wie geht das Simulieren?
Valentin

PS: Danke für die Antworten!

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier nochmal der Code:
#include <avr\io.h>
#include <avr\interrupt.h>

volatile unsigned char set;


ISR(TIM0_OVF_vect){
if(set==0) {
PORTB = 0b00000011;set = 1;}
else{
PORTB = 0b00000000;set = 0;}
}

void init(){
  TCCR0B = 0b00000100;   // Teiler 1/256
  TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
  DDRB = 0b00000011;
  set = 0;
  sei();      
}

int main(void){
init();
while(1){
PORTB = PORTB | 0b00000001;
}
return 0;
}


Kann man das Set auch vielleicht mit einem bool machen?
Valentin

Autor: R. Freitag (rfr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schag nach in deinem C-handbuch  unter '!' und '~'.

Gruss

Robert

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nicht "!"
sondern ^

besser ist das.

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <avr\io.h>
#include <avr\interrupt.h>

volatile unsigned char set;


ISR(TIM0_OVF_vect){
PORTB = PORTB ^ 0b00000011;set = 1;}
}

void init(){
  TCCR0B = 0b00000100;   // Teiler 1/256
  TIMSK0 |= _BV(0);   // Interrupt bei Überlauf
  DDRB = 0b00000011;
  set = 0;
  sei();      
}

int main(void){
init();
while(1){}
return 0;
}

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
huch, vergiss meinen letzten beitrag, lol.
&

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DA war noch eine } zuviel. Hab ich inzwischen weggemacht!
Valentin

PS: Soll ich jetzt doch mit NOT arbeiten? x xor x = 0 , oder?

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Allerdings geht die LED an PORTB2 immer noch nicht an.
warum sollte sie auch wenn PORTB2 ein Eingang ist ...

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie "ein Eingang"?
Ich habe ihn doch auf Ausgang geschaltet!
Valentin

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
#include <avr\io.h>
#include <avr\interrupt.h>

unsigned char counter;

ISR(TIM0_OVF_vect)
{
  counter++;

  if( counter == 7 )    // ergbit bei 1Mhz ca. 0.5 Sekunden bei Presc. 256
  {
     PORTB = PORTB ^ ( (1<<PB0) | (1<<PB1) );
     counter = 0;
  }
}

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

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

  sei();      
}

int main(void)
{
  init();

  while(1)
  {
  }

  return 0;
}

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal abgesehen von all dem Gesagten: das ist sehr schlechter Stil:
>   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
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.

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <avr\io.h>
#include <avr\interrupt.h>

ISR(TIM0_OVF_vect)
{
     PORTB = PORTB ^ ( (1<<PB0) | (1<<PB1) );
}

void init()
{
  TCCR0B = ( 1 << CS02 );    // Teiler 1/256
  TIMSK0 = ( 1 << TOIE0 );   // Interrupt bei Überlauf
  DDRB = (1<<PB0) | (1<<PB1);
  sei();      
}

int main(void)
{
  init();

  while(1)
  {
  }

  return 0;
}
Vielen Dank an alle!!!
Valentin

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein schneller Lerneffekt.  Glückwunsch zum nun laufenden Programm!

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
...
ISR (TIMER0_COMPA_vect){
PORTB = PORTB ^ ( (1<<PB0) | (1<<PB1) );
}
...
TCCR0 =  (1<<CS02)|(1<<COM0);// Teiler 1/256, Modus: Zählen bis //Vergleichswert
   OCR0 = 250;   // Vergleichswert speichern
  TIMSK = (1<<TOIE0);//interrupt einschalten
  TIFR = (1<<OCF0); //Interrupt bei CompareMatch
  sei();//Interrupts einschalten
...
Danke für die Antworten,
Valentin

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dafür gibts Datenblätter.
REINGUCKEN :-)

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da steht GAR-NIX von einem Compare Register. Vergleicht der das dauernd?
Valentin

Autor: Michael Potthoff (mipo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
tja, dann musst Du wohl in Datenblatt schauen...

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Valentin Buck schrieb:
> Da steht GAR-NIX von einem Compare Register.

doch

Autor: Valentin Buck (nitnelav) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"The double buffered Output Compare Register (OCR0) is compared with the
Timer/Counter value at all times."
OK, der vergleicht es also dauernd.
Valentin

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.