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
}
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.
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.
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.
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.
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.
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)
Andy schrieb:> Also der Compiler bringt keine Fehlermeldung.
Nicht?
ALso das hier
1
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)
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?)
> 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
1
voidtimer0Init()
2
{
3
timer_value=0xFF;
4
5
TIMSK0=(1<<TOIE0);
6
TCCR0A=0;
7
TCCR0B=(1<<CS02)|(1<<CS00);// Prescaler 1024
8
}
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:
1
ISR(TIM0_OVF_vect)
2
{
3
staticuint8_tsw_prescaler=10;
4
5
if(--sw_prescaler==0)
6
{
7
sw_prescaler=10
8
PORTB=PORTB^(1<<LED_PIN);
9
TCNT0=timer_value;
10
}
11
}
um die Taktrate des Attiny13 zusätzlich um 10 zu teilen.
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)
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.
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.
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.
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.