/* >> 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 #include #include // 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 // - - - - - - - - - - - - - - - - { /* ATtiny45 PDIP/SOIC/TSSOP (PCINT5/RESET(i)/ADC0/dW) PB5 [1] [8] VCC (PCINT3/XTAL1/CLKI/OC1B(i)/ADC3) PB3 [2] [7] PB2 (SCK/USCK/SCL/ADC1/T0/INT0/PCINT2) (PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4 [3] [6] PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1) GND [4] [5] PB0 (MOSI/DI/SDA/AIN0/OC0A/OC1A(i)/AREF/PCINT0) */ #include #include #include #define F_CPU 1000000 // 1 MHz #define KEY_PIN PINB #define KEY_PORT PORTB #define KEY0 2 #define LED_DDR DDRB #define LED_PORT PORTB #define LED0 0 //#define LED1 1 //#define LED2 4 //#define LED3 3 #define REPEAT_MASK (1<1: key press detect key_release |= ~key_state & i; // 1->0: key release detect if( (key_state & REPEAT_MASK) == 0 ) // check repeat function rpt = REPEAT_START; // start delay if( --rpt == 0 ){ rpt = REPEAT_NEXT; // repeat delay key_rpt |= key_state & REPEAT_MASK; } } uint8_t get_key_press( uint8_t key_mask ) { ATOMIC_BLOCK(ATOMIC_FORCEON){ key_mask &= key_press; // read key(s) key_press ^= key_mask; // clear key(s) } return key_mask; } uint8_t get_key_rpt( uint8_t key_mask ) { ATOMIC_BLOCK(ATOMIC_FORCEON){ key_mask &= key_rpt; // read key(s) key_rpt ^= key_mask; // clear key(s) } return key_mask; } uint8_t get_key_short( uint8_t key_mask ) { uint8_t i; ATOMIC_BLOCK(ATOMIC_FORCEON) i = get_key_press( ~key_state & key_mask ); return i; } uint8_t get_key_long( uint8_t key_mask ) { return get_key_press( get_key_rpt( key_mask )); } uint8_t get_key_long_r( uint8_t key_mask ) // if repeat function needed { return get_key_press( get_key_rpt( key_press & key_mask )); } uint8_t get_key_rpt_l( uint8_t key_mask ) // if long function needed { return get_key_rpt( ~key_press & key_mask ); } int main( void ) { /* Taster Entprellen über Timer nach Peter Danegger */ TCCR1 = 1< 0) pwm = 0; else pwm = 255; if( get_key_long_r( 1< 0 ) --pwm; } } else if( pressed ) { pressed = 0; direction = 1 - direction; } OCR0A = pwm; //_delay_ms(10); } return 0; } // TCCR0A |= (1< Clock = CPUclk/8 74 OCR0A = 239; // Preset 239 für 200µs bei 9,6 Mhz // 200 µs <=> 2,5 kHz TIMSK0 |= (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 // ============================================================================= = // ============================================================================= =