www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Code von Atmel Mega8 auf ATtiny13


Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo wollte mal fragen wie ich den Code umschreiben muss dass er auf 
einem ATtiny 13 läuft hab jetzt viel rumprobiert und wäre für eine 
Lösung sehr dankbar. Funktion: Eine Led blinkt und wird über einen Poti 
geregelt.

#define F_CPU 3686400
#include <avr\io.h>
#include <inttypes.h>
#include <avr\interrupt.h>
//---------------------------------------------------------------------- 
----
unsigned char timer_value;
ISR (TIMER0_OVF_vect)
{
  PORTB = ~ PORTB;    // Flankenwechsel für Tonfrequenz
  TCNT0 = timer_value;
}

ISR(ADC_vect)
{
  int adc_value;
  adc_value=ADC;
  timer_value=char(adc_value/5);
  sbi  (ADCSRA,6);      // restart ADC
}

void adcInit()
{
  ADMUX=0;
  ADCSRA=0xDD;      //0b11011101, ADC-Clock, ADC ON, INT ON
}

void timer0Init()
{
  timer_value=0xFF;
  TCCR0=0x05;
  TIMSK=0x01;
}

void portsInit()
{
  sbi(DDRB,0);      //OUT Summer
  sbi(DDRB,1);      //OUT LED
}

main()
{
  //Initialisierung
    portsInit();      // PortB als Ausgang initialisieren
    timer0Init();      // Timer Interrupt initialisieren
    adcInit();
    sei();                  // enable interrupts
  do { } while(true);    // mainloop
}

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

Bewertung
0 lesenswert
nicht lesenswert
Die Lösung besteht darin, dass du dir
* das Datenblatt zum Mega8
* das Datenblatt zum Tiny13
besorgst und das Programm zunächst analysierst. Du nimmst das Datenblatt 
zum Mega8 und gehst das Programm durch, bis du verstanden hast, was da 
alles genau abgeht. Die Details, was die ganzen Registerzuweigungen 
machen, holst du dir aus dem Datenblatt zum Mega8

Nachdem der Istzustand damit erhoben ist, werden die Datenblätter 
verglichen, ob alles was auf dem Mega8 benutzt wurde, auch in dieser 
Form auf dem Tiny13 verfügbar ist.

Das meiste davon wird identisch sein, aber kleinere Abweichungen wird es 
geben.

Und dann wird das Programm vom Mega auf den Tiny übertragen, wobei die 
Erkentnisse aus dem Datenblattvergleich einfliessen.


Auch auf die Pinbelegung nicht vergessen.
Während der Mega8 3 Ports hat, hat der Tiny nur einen: Alles, auch der 
ADC, ist am PortB.
In der ISR wird daher das hier
  PORTB = ~ PORTB;    // Flankenwechsel für Tonfrequenz
nicht so schlau sein.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja
hab soweit alles verglichen. Die LED brennt zwar aber der Timer scheint 
nicht zu funktionieren. Wie wird das  PORTB = ~ PORTB;  gelöst 
vielleicht liegt es auch daran dass es nicht geht.

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

Bewertung
0 lesenswert
nicht lesenswert
Sorry.
Aber ich geh jetzt nicht her und drösle das hier

  ADCSRA=0xDD;      //0b11011101, ADC-Clock, ADC ON, INT ON

  TCCR0=0x05;
  TIMSK=0x01;

dahingehend auf, welche Bits da wirklich gesetzt sind.

> Wie wird das  PORTB = ~ PORTB;

Indem man nur die Bits toggelt, die auch tatsächlich benutzt werden?
An denen also Summer und LED hängen.

Durch diesen Rundumschlag schaltest du auf dem ADC Pin ständig den 
Pullup Widerstand ein/aus. Der ADC wird so alles mögliche messen, nur 
nicht das, was du willst.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andy schrieb:

> Ja
> hab soweit alles verglichen. Die LED brennt zwar aber der Timer scheint
> nicht zu funktionieren.

Hast du auch daran gedacht, die Taktraten zu vergleichen?

Wenn der Atmega8 langsamer taktet als der Attiny13 kann es passieren, 
dass das Blinken zu schnell für deine Augen wird und du nur noch 
Dauerleuchten siehst.

Wenn das zutrifft, gibt es mehrere Wege, dem abzuhelfen. Ein Weg wäre, 
den Hardware PRESCALER des Timers zu erhöhen. Das wäre eine Änderung in 
der kryptischen Zeile TCCR0=0x05;

Ich würde mich auch im ersten Schritt nur auf den Timer und die LED 
konzentrieren und erst wenn das steht, den ADC verwenden. Für den ersten 
Schritt würde ich die Zeile

  timer_value=char(adc_value/5);

mal durch

  timer_value=char(/*adc_value*/ 511/5);

ersetzen. Die 511 sind willkürlich gewählt (Mittelwert des 10-Bit 
ADC-Bereichs 0..1023).

Es muss auch heissen (s. Tutorial):
volatile unsigned char timer_value;
Das ist schon ein Bug im Atmega8 Programm.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab jetzt alles mögliche ausprobiert bekomme es aber nicht zum laufen, 
die Led leuchtet nur. Ich weiß nicht mehr weiter.

#define F_CPU 3686400
#include <avr\io.h>
#include <inttypes.h>
#include <avr\interrupt.h>
//---------------------------------------------------------------------- 
----
volatile unsigned char timer_value;
ISR (TIM0_OVF_vect)
{    // Flankenwechsel für Tonfrequenz
  PORTB = ~ 0b000010;
  TCCR0A= timer_value;
}

ISR(ADC_vect)
{
  int adc_value;
  adc_value=ADC;
  timer_value=char(/*adc_value*/511/5);
  sbi  (ADCSRA,6);      // restart ADC
}

void adcInit()
{

  ADMUX=0x42;   // Port, Referenzspannung und Auflösung
     ADCSRA=0xE5;   // Modus, Interrupt und Start
}

void timer0Init()
{
  timer_value=0xFF;
  TIMSK0=0x01;
  TCCR0A=0x15;


}

void portsInit()
{
  sbi(DDRB,1);      //OUT LED
}

main()
{
  //Initialisierung
    portsInit();      // PortB als Ausgang initialisieren
    timer0Init();      // Timer Interrupt initialisieren
    adcInit();
    sei();                  // enable interrupts
  do { } while(true);    // mainloop
}

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

Bewertung
0 lesenswert
nicht lesenswert
Was soll den das hier sein
  PORTB = ~ 0b000010;

http://www.mikrocontroller.net/articles/Bitmanipulation
PORTB = PORTB ^ ( 0b00000010 );

Es wäre gut, wenn du dir für die LED ein #define machst, damit du den 
Mischmasch aus direkter Bitmanipulation und cbi/sbi bereinigen kannst. 
Einige deiner Problem sind durch die ungeschickte Schreibweise 
hausgemacht.
#define F_CPU 3686400
#include <avr\io.h>
#include <inttypes.h>
#include <avr\interrupt.h>
//--------------------------------------------------------------------------
volatile unsigned char timer_value;

#define LED_PIN  PB1

ISR (TIM0_OVF_vect)
{
  PORTB = PORTB ^ ( 1<<LED_PIN );
  TCCR0A = timer_value;
}

ISR(ADC_vect)
{
  int adc_value;

  adc_value = ADC;
  timer_value = char(/*adc_value*/511/5);
  ADCSRA |= (1<<ADSC);      // restart ADC
}

void adcInit()
{
  ADMUX  = 0x42;   // Port, Referenzspannung und Auflösung
  ADCSRA = 0xE5;   // Modus, Interrupt und Start
}

void timer0Init()
{
  timer_value = 0xFF;
  TIMSK0 = 0x01;
  TCCR0A = 0x15;
}

void portsInit()
{
  DDRB |= (1<<LED_PIN);
}

main()
{
  //Initialisierung
  portsInit();      // PortB als Ausgang initialisieren
  timer0Init();      // Timer Interrupt initialisieren
  adcInit();
  sei();                  // enable interrupts

  do { } while(true);    // mainloop
}

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal danke für die Tipps und hilfe.
Aber der Effekt ist immernoch der gleiche. Die Led blinkt einfach nicht.

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

Bewertung
0 lesenswert
nicht lesenswert
Und die Fehler und Warnungen, die der Compiler wirft, stören dich nicht 
weiter. Oder wie?

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

Bewertung
0 lesenswert
nicht lesenswert
Ausserdem weist du dem Timer an keiner Stelle einen Vorteiler zu. Der 
Timer läuft ganz einfach nicht!

Drösel endlich diesen Unsinn hier
  TIMSK0 = 0x01;
  TCCR0A = 0x15;
in eine vernünftige Bit-Schreibweise auf!
Dann wirst du sehen, dass kein CS Bit gesetzt wird
(Hauptsächlich deshalb, weil die CS Bits beim Tiny13 im Register TCCR0B 
beheimatet sind)

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also der Compiler bringt keine Fehlermeldung.
Und wie soll ich die Bits setzen dass ich einen Effekt sehe.

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

Bewertung
0 lesenswert
nicht lesenswert
Andy schrieb:
> Also der Compiler bringt keine Fehlermeldung.

Nicht?

ALso das hier
timer_value=char(/*adc_value*/511/5);
ist kein gültiges C. Es wäre allerdings gültiges C++.
Genauso wie es in C (wohl aber in C++) kein 'true' gibt.

> Und wie soll ich die Bits setzen dass ich einen Effekt sehe.
Schau endlich ins verd... Datenblatt, lies den Abschnitt über Timer und 
such dir raus, welche Bits in welchen Registern
* es gibt
* zu setzen sind, damit der Timer einen Vorteiler bekommt.

Sorry.
Aber du wirst nicht drumherum kommen, die Beschreibung zu studieren 
anstatt blindlings einfach nur draufloszuprogrammierern und mit der 
Stange im Nebel zu stochern. Jetzt hab ich dir ohnehin schon den Weg bis 
zum zuständigen Register gezeigt. Durch die letzte Tür musst du schon 
alleine gehen.

(Und Hinweis: Im Simulator vom AVR-Studio kann man sein Programm 
wunderbar simulieren. Wenn man das tut, dann erkennt man das der Timer 
gar nicht tickt, weil er keinen Vorteiler hat)

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich würde statt

> TIMSK0 = 0x01;

das so schreiben TIMSK = (1<<TOIE0); (damit du siehst, welche Bits du 
genau setzst)

außerdem der Register TIMSK0 heißt bei ATmega8 TIMSK (oder sehe ich da 
was falsch?)

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TCCR0B = 0x05;
ist das nicht der Vorteiler?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>   TCCR0A = timer_value;

Ich denke, du willst NICHT das Konfigurationsregister des Timers mit 
dem ADC Wert füllen. Ich könnte mir vorstellen, dass du den Timerzähler 
TCNT0 manipulieren willst.

>   TCCR0A = 0x15;

Datenblatt:
11.9.1 TCCR0A – Timer/Counter Control Register A

             Bit 7       6      5      4 3 2     1     0
             COM0A1 COM0A0 COM0B1 COM0B0 – – WGM01 WGM00
Deine
Einstellung  0      0      0      1      0 1     0     1

Da stimmt was nicht; Bit 2 ist undefiniert. Ich würde einfach den Normal 
Modus (Tabelle 11-8) benutzen ohne Hardwareausgabe.

TCCR0A = 0;

Der Prescaler wird mit TCCR0B gesetzt. Das fehlt in void timer0Init() 
völlig. Da läuft nix, da No clock source (Timer/Counter stopped).

11.9.2 TCCR0B – Timer/Counter Control Register B

         Bit 7     6 5 4     3    2    1    0
         FOC0A FOC0B – – WGM02 CS02 CS01 CS00

Table 11-9. Clock Select Bit Description
CS02 CS01 CS00 Description
   0    0    0 No clock source (Timer/Counter stopped)
   0    0    1 clkI/O/(No prescaling)
   0    1    0 clkI/O/8 (From prescaler)
   0    1    1 clkI/O/64 (From prescaler)
   1    0    0 clkI/O/256 (From prescaler)
   1    0    1 clkI/O/1024 (From prescaler)
   1    1    0 External clock source on T0 pin. Clock on falling edge.
   1    1    1 External clock source on T0 pin. Clock on rising edge.

>  TIMSK0 = 0x01;

11.9.6 TIMSK0 – Timer/Counter Interrupt Mask Register
Bit 7 6 5 4      3      2     1 0
    – – – – OCIE0B OCIE0A TOIE0 -

Die 0x01 sind also auch falsch. Der Attiny13 kommt nie in die 
ISR(TIM0_OVF_vect), sondern resettet sich beim Auftreten des Interrupts.

Also
void timer0Init()
{
  timer_value = 0xFF;

  TIMSK0 = (1<<TOIE0);
  TCCR0A = 0;
  TCCR0B = (1<<CS02) | (1<<CS00); // Prescaler 1024
}

Der Attiny13 läuft ab Werk mit

Table 6-4. Internal Calibrated RC Oscillator Operating Modes
CKSEL1..0 Nominal Frequency
10(1)     9.6 MHz                 (1) = Werkseinstellung

Beim größten(!) Prescaler 1024 wird die ISR(TIM0_OVF_vect) 
9600000/1024/256 = 36,6 mal pro Sekunde aufgerufen (oder häufiger (!) 
wenn TCNT0 auf timer_value > 0 gesetzt wird). Das Auge löst das nicht 
mehr als Blinken auf, sondern als Dauerleuchten.

Ändere die ISR mal in:
ISR (TIM0_OVF_vect)
{
  static uint8_t sw_prescaler = 10;

  if ( --sw_prescaler == 0 )
  {
    sw_prescaler = 10
    PORTB = PORTB ^ ( 1<<LED_PIN );
    TCNT0 = timer_value;
  }
}

um die Taktrate des Attiny13 zusätzlich um 10 zu teilen.

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jungs,
verstehe ich richtig, du verwendest den Timer/Counter0 von ATmega8? (Im 
Datenblatt sehe ich aber keine >>TCCR0A und >>TCCR0B Register für den 
Timer/Counter0)

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ISR (TIM0_OVF_vect)

muss doch so heißen ISR(TIMER0_OVF_vect)

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
nein das erste Programm war auf einem Mega8 und hat funktioniert. Jetzt 
will ich es auf einem ATtiny13 haben.
Es geht aber immer noch nicht die Led blinkt nicht sondern leuchtet nur 
ich glaub ich gebs jetzt auf.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich schrieb:

>> ISR (TIM0_OVF_vect)
>
> muss doch so heißen ISR(TIMER0_OVF_vect)

Guter Hinweis! Kann sein, aber ich habe das aktuelle Attiny13 
Includefile des WinAVR nicht vor mir um nachzusehen.

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

Bewertung
0 lesenswert
nicht lesenswert
ich schrieb:
>> ISR (TIM0_OVF_vect)
>
> muss doch so heißen ISR(TIMER0_OVF_vect)

Hat mich auch verblüfft.
Aber stimmt schon so. Hab im Include File nachgesehen.

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das erste ist doch richtig, ich dachte es geht um den ATmega8 (und das 
war mein Fehler)

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

Bewertung
0 lesenswert
nicht lesenswert
Andy schrieb:

> ich glaub ich gebs jetzt auf.

Arbeite einfach sorgfältig!

Es ist ein Irrtum zu glauben, man kann ein Programm so mir nichts, dir 
nichts von Prozessor A auf Prozessor B transferieren.

Man muss sich jedes Bit in jedem Konfigurationsregister ansehen, ob es 
auf der Zielarchitektur auch wirklich wieder an derselben Stelle ist.

Benutzt man die Schreibweise ala

    TCCRA0 = 0x15;

dann ist dieser Vorgang doppelt hart und man schaffts sich nur unnötig 
selbst Stress.

Ausserdem: Nicht böse sein.
Aber wenn du das Mega8 Programm ganz einfach mit Datenblatthilfe neu 
geschrieben hättest (*), wärst du schon 3mal fertig.

(*) Also:
Überlegen welchen Timermodus ich haben möchte bzw. brauche. Datenblatt 
nehmen und die entsprechenden Register und Bits raussuchen und in einer 
vernünftigen Form hinschreiben.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok dank dir werd nochmal alles nachschauen und es neu vesuchen.

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.