... Das Datenblatt ist eig. unbrauchbar ...
Stimmt. Mal was Anderes: ich setze Dich in einen Airliner und geb Dir das Betriebshandbuch. Du wirst es als unbrauchbar wegwerfen - und das Ding nicht in die Luft kriegen. Dagegen ist ein CPL-Pilot meist in der Lage ohne Einweisung mit einem nicht gerade ungebräuchlichen Jet mit Hilfe des Betriebshandbuchs in die Luft zu gehen. Tut er aber nicht - er holt sich ne Einweisung. Die brauchst Du auch: ins Datenblatt, ins Programmierhandwerk etc.
Beispiel: der Code im Datenblatt ist möglicherweise nicht für den Compiler, den Du verwendest. Oder es sind eben nicht alle notwendigen Initialisierungen drin. Das Datenblatt ist sowieso schon sooo lang, oder? UND es wendet sich eigentlich nicht an Anfänger. Sorry, das soll nicht ätzend sein, soll Dich nicht entmutigen, es ist einfach so.
... kann mir jemand schreiben wie der Code aufzubauen ist? ...
Das kann schätzungsweise jeder Zweite hier - denke ich. Und als kleine Hilfe für Dein Problem lege ich einen kompletten, lauffähigen Code für nen tiny13 dazu, bei dem der Timer zum Blinken einer LED eingesetzt wird. IDE dafür ist AVR-Studio4. Erklärungen stehen im Kommentar des Codes. Mehr schreibe ich hier nicht dazu.
Du solltest vermutlich das eine oder andere Tutorial noch durchgehen, dann ein KLEINES Programmschnippsel Dir irgenwo abschreiben, modifizieren, schaun ob was rauskommt ausser Fehlermeldungen etc etc. Die nicht unübliche Vorgehensweise eines Anfängers. Und - Timerprogrammierung ist schon eher fortgeschrittenes Können bei den AVR´s.
Code:
/* >>
Stand ...\...\LED_B3.c x20 21Jan14 2340
x20 21Jan14 2340 Timernutzung für Sound zusätzlich auf PB0 mit PWM
=============================================================================== =
Target MCU : ATTiny 13
Target Hardware : Experimentierplatine tiny13
Target cpu-frequ. : Interner Oszillator (9,6 MHz)
=============================================================================== =
*** Aufgabenstellung : LED auf Port PB3 blinkt z.B. 1 Hz, Sound auf PB4
Taktgeber durch Timer-ISR, Variation der Timerparameter
============================================================================== */
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h> // Für Interruptbehandlung nötig
// CPU Frequenz
#define F_CPU 9600000UL
// Setze Bit
#define SetBit(ADDR,BIT) ((ADDR) |= (1<<(BIT)))
// Lösche Bit
#define ClrBit(ADDR,BIT) ((ADDR) &= ~(1<<(BIT)))
// Toggel Bit
#define ToggleBit(ADDR,BIT) ((ADDR) ^= (1<<(BIT)))
// - - - - - - - - - - - - - - -
// Grüne LED auf Port PB3
#define L1G 3
// Anmerkung: die LED-Schaltung ist GND-Kathode-LED-Anode-Portpin
volatile int16_t Izeit_1; // Wertbereich int16: 32.767. uint16: 65.535
volatile int16_t ZHorznt; // Wertbereich int16: 32.767. uint16: 65.535
volatile int16_t Sekundn; // Zähler für Sekunden
// - - - - - - - - - - - - - - -
// Funktionsprototypen
void wms(uint16_t v) ; // Waitroutine (Controller zählt nur vor sich hin)
void TC0TMR_init(void) ; // Init Tmr/Cntr 0, 8-Bit auf 20 kHz = 50 µs
ISR(TIM0_COMPA_vect) ; // Vektor 7, Prog.Addr. 0x0006
// ============================================================================= =
// ============================================================================= =
// ============================================================================= =
// ===== Subroutinen ========================================================= =
// ============================================================================= =
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// PROCEDURE wms()
// - Warteroutine die NUR Zeit vertrödelt; Controller zählt runter bis Null
// PARAMETER
// - I uint16_t Wartezeit in Millisekunden
// Die geforderte Zeit ist i.A. nur ungefähr!
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void wms(uint16_t ms) // Waitroutine (Controller zählt runter bis Null)
// - - - - - - - - - - - - - - - -
{ //
for(; ms>0; ms--) //
{ //
uint16_t __c = 2395; // Anpassung an 9,6 MHz
__asm__ volatile ( // Beginn Assembler Routine / nicht optimieren
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__c)
: "0" (__c)
);
}
} // Ende void wms(uint16_t ms)
// ============================================================================= =
// ============================================================================= =
// === Initialisierung des Timer0 tiny13 für CTC
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TC0TMR_init(void) // Init Tmr/Cntr 0, 200µs bei 9,6 Mhz = 5kHz
// - - - - - - - - - - - - - - - -
{ //
TCCR0A |= (1<<WGM01); // Timer im CTC-Mode, Top=OCR0A 73
TCCR0B |= (1<<CS01); // Prescaler 8 => Clock = CPUclk/8 74
OCR0A = 239; // Preset 239 für 200µs bei 9,6 Mhz
// 200 µs <=> 2,5 kHz
TIMSK0 |= (1<<OCIE0A); // Tmr/Cntr0 CompareA interrupt enabled
} // Ende void TC0TMR_init(void)
// ============================================================================= =
// ============================================================================= =
// === Nicht unterbrechbare ISR für timer0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ISR(TIM0_COMPA_vect) // Vektor 7, Prog.Addr. 0x0006
// - - - - - - - - - - - - - - - -
{ //
Izeit_1 --; // ###>>> Izeit_1 ist aktuell int16_t ==>>
// bleibt im Wertebereich < 32.767
ToggleBit (PORTB, 4); // .. Audioport toggeln
if ( Izeit_1 ) // Interrupt-Timer = 1 ... 40 000 ... (1 sec blink)
{ } // WENN Izeit_1 =|= Null => wahr => Anweisung ausgeführen
else // Izeit_1 = Null = unwahr, daher "else" ausführen
{ // Eine Sekunde ist voll =>
Izeit_1 = ZHorznt; // .. daher: Rückstellen auf Zeithorizont
ToggleBit (PORTB, L1G ); // .. und LED toggeln
Sekundn ++; // "Sekundencounter" hochzählen
} // Ende if (Izeit_1 )
return;
} // Ende ISR(TIM0_COMPA_vect)
// ============================================================================= =
// ============================================================================= =
// ============================================================================= =
// ===== ENDE Subroutinen ================================================= =
// ============================================================================= =
// ============================================================================= =
// === HAUPTProgramm ========================================================== =
// FUNCTION main()
// - Initialisierungen
// - LED kurzblinken als Signal für Programmstart
// - Pause 100 ms ohne Aktion
// - Hauptschleife
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int main(void) // Hauptprogramm
{ //
// - - - - - - - - - - - - - - -
// Variablendefinition
uint16_t i; // Zählvariable
uint16_t ton; // Zählvariable
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// === Grundlegende Initialisierungen der Hardware, Portdefinition
//PCINT5,/RESET,ADC0,dW PB5 1 8 Vcc
// PCINT3,CLKI,ADC3 PB3 2 7 PB2 SCK,ADC1,T0,PCINT2
// PCINT4, ADC2 PB4 3 6 PB1 MISO,AIN1,OC0B,INT0,PCINT1
// GND 4 5 PB0 MOSI,AIN0,OC0A,PCINT0
// - - - - - - - - - - - - - - -
// Portbelegung und Initialisierung der Anschlüsse :
// /RESET PB5 1 A + 28 Vcc
// L1G PB3 2 A A 27 PB2 nc
// Piezo1 PB4___3 A A 26___PB1 nc
// Piezo GND 4 - A 25 PB0 nc
// - - - - - - - - - - - - - - -
// Portkonfiguration
// Ports+Pins als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktiv.
// A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp
DDRB = 0b11111111; // siehe aktuell oben
PORTB = 0b00000000; // und Port/Pull Ups (1) aktivieren
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TC0TMR_init (); // Initialisierung des Timers
sei(); // Interrupts zulassen
// ============================================================================= =
// Es folgt das eigentliche "Hauptprogramm" mit den Aktionen
// ============================================================================= =
// Einstellen der Werte
ZHorznt = 5000; // Zeithorizont einstellen
Izeit_1 = ZHorznt; // Zeithorizont für Timer übernehmen
Sekundn = 0; // Boardzeit initialisieren
// Eine kurze Zeit Dauerton
while (Sekundn < 5) // Schleife ca. x sec
{ //
} // Ende while ( Sekundn < ...
// - - - - - - - - - - - - - - - -
// Jetzt Ton ab- und anschwellend
cli();
ZHorznt = 5000; // Setze Zeithorizont
Sekundn = 0; // Sekunden zurücksetzen
sei();
i = 0; // Schleifenzähler setzen
ton = OCR0A; //
while ( Sekundn < 10 )
{
for (i = 0; i<50; i++) //
{ //
ton--; // Ton tiefer stellen
OCR0A = ton; //
wms ( 10);
} //
for (i = 0; i<50; i++) //
{ //
ton++; // Ton hochdrehen
OCR0A = ton; //
wms ( 10);
} //
} // Ende while ( Sekundn < 10 )
// - - - - - - - - - - - - - - - -
// Konstanten Ton einschalten
cli();
ZHorznt = 5000; // Setze Zeithorizont
Sekundn = 0; // Sekunden zurücksetzen
sei();
// Eine kurze Zeit Dauerton
while (Sekundn < 5) // Schleife ca. x sec
{ //
} // Ende while ( Sekundn < ...
// - - - - - - - - - - - - - - -
// Zum Abschluss wieder Sirenentöne ab- und anschwellend
i = 0; // Schleifenzähler setzen
//ton = OCR0A; //
ton = 255; //
while ( 1 )
{
for (i = 0; i< 100; i++) //
{ //
ton--; // Ton tieferstellen
OCR0A = ton; //
wms ( 20);
} //
for (i = 0; i< 100; i++) //
{ //
ton++; // Ton hochdrehen
OCR0A = ton; //
wms ( 20);
} //
} // Ende while ( 1 ...
// - - - - - - - - - - - - - - -
return 0; //
} //
// ===== Ende
// ============================================================================= =
// ============================================================================= =
Diesen Code hatte ich extra für ne Anfängerschulung geschrieben. Die Leute hatten davor schon ein paar wenige Stunden Einweisung hinter sich.
Und natürlich wünsche ich Dir viel Erfolg. Und Geduld.
Nachtrag: der tiny84 hat Prescaler. Für den Timer0 beispielsweise siehe Documentation 8006K–AVR–10/10, Seite 84.
Nochn Nachtrag:
... Datenblatt ist eig. unbrauchbar ... Mit dem Datenblatt arbeite ich die ganze Zeit ...
Zitat von
ooweberoo
... #define F_CPU 1000000UL //max. Takt ATtiny84 ...
Auf Seite 1 des Datenblatts steht der maximale Takt des tiny84 mit 20 MHz angegeben . . . Dazu muss natürlich der entsprechende Quarz benutzt werden.
Lesezeichen