Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | PWM-Timer jetzt hoffentlich richtig konfiguriert. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
c13a8db10d0f2dd9fdab110760d74bf8 |
User & Date: | tux12345@justmail.de 2016-04-14 10:30:27 |
Context
2016-12-24
| ||
17:54 | Portbelegung für den AVR-Programmer als Bild mit allen Informationen. check-in: 173dad296b user: tux12345@justmail.de tags: trunk | |
2016-04-14
| ||
10:30 | PWM-Timer jetzt hoffentlich richtig konfiguriert. check-in: c13a8db10d user: tux12345@justmail.de tags: trunk | |
10:29 | AVR-CPU-Takt auf 8Mhz erhöht. check-in: c860fa0d40 user: tux12345@justmail.de tags: trunk | |
Changes
Changes to main/main.c.
1 2 3 | #include <stdlib.h> #include<avr/io.h> | | | > | | | | > > > > > > > > > | | | < | | < | | > > | > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #include <stdlib.h> #include<avr/io.h> #include <avr/interrupt.h> #include "timer.h" /* * Konstanten */ // Melodiedefinitionen const char melody1[] = "BY}6YB6%"; const char melody2[] = "Qj}6jQ6%"; /* * Globale Variablen */ extern volatile uint8_t program_status; extern volatile uint8_t timer_status; // Der Tonindex zählt die Anzahl bereits gespielter Töne. Daraus ergibt sich der nächste Ton. uint32_t index = 0; void write_PWM(uint8_t out); uint8_t generator_step(); int32_t generator_tone(int32_t index, int32_t x, int32_t tone_choice, int32_t o); void check_timer_error(); int main() { //Energiesparen: Nicht benötigte Module ausschalten: //AD-Wandler, USART-Interface, SPI und Timer1 abschalten //PRR |= _BV(PRADC) | _BV(PRUSART0) | _BV(PRSPI) | _BV(PRTIM1); //Pin für Fehlerausgabe DDRC |= _BV(PORTC5); PORTC |= _BV(PORTC5); //Pin für PWM-Ausgabe DDRD |= _BV(PORTD6); PORTD &= (unsigned char) ~_BV(PORTD6); setup_Timer(); sei(); while(1) { check_timer_error(); // Läuft, bis der Timer-Interrupt auftritt program_status = PROGRAM_IDLE; while (program_status == PROGRAM_IDLE); // Neue Werte berechnen uint8_t out = generator_step(); // Berechneter Ausgabewert per PWM schreiben write_PWM(out); } } inline void write_PWM(uint8_t out) { // TODO: Funktioniert CTC auch mit 0 oder 0xFF als vergleichswert korrekt? //-> Ist der Port dauerhaft auf LOW, wenn 0 geschrieben wird und dauerhaft auf HIGH, wenn 0xFF geschrieben wird? OCR0A = out; } int32_t generator_tone(int32_t index, int32_t x, int32_t tone_choice, int32_t o) { char tone = (3&index>>16?melody1:melody2)[tone_choice%8]; tone += 51; return((3&x&( index*tone>>o))<<4); } uint8_t generator_step() { int32_t n=index>>14; int32_t s=index>>17; uint8_t ret = 0; ret += generator_tone(index, 1, n, 12); ret += generator_tone(index, s, n^index>>13, 10); ret += generator_tone(index, s/3, n+((index>>11)%3), 10); ret += generator_tone(index, s/5, 8+n-((index>>10)%3), 9); ++index; return ret; } inline void check_timer_error() { if(timer_status == TIMER_STATUS_ERROR) PORTC &= (unsigned char) ~_BV(PORTC5); } |
Changes to main/timer.c.
1 2 3 4 5 | #include "timer.h" #include <avr/io.h> #include <avr/interrupt.h> | | > > | > > > > | | | | | > > | < > > > > > | > | > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #include "timer.h" #include <avr/io.h> #include <avr/interrupt.h> volatile uint8_t program_status = PROGRAM_IDLE; volatile uint8_t timer_status = TIMER_STATUS_OK; uint8_t number_timer_ticks = 0; ISR(TIMER2_OVF_vect) { //TODO: 16-Bit Timer 1 verwenden. Vereinfacht den code… ++number_timer_ticks; if(number_timer_ticks == TIMER_TICKS_PERIOD) { number_timer_ticks = 0; if(program_status == PROGRAM_IDLE){ program_status = PROGRAM_BUSY; PORTC &= (unsigned char) ~_BV(PORTC5); } else timer_status = TIMER_STATUS_ERROR; } else PORTC |= _BV(PORTC5); } void setup_Timer() { //Programmtimer (8kHz), stößt alle 125 Interrupts eine neue Berechnung an // //TCNT2 = 0x00; // Counter auf 0 setzen TIMSK2 |= _BV(TOIE2); // Timer 2 Overflow-interrupt einschalten TCCR2B |= _BV(CS21); // Taktgeber auf Prescaler mit F_CPU/8 setzen. Dadurch ergibt sich 8Mhz/8/125 = 8kHz Abtastrate // PWM-Timer hält die Lautsprechermembran auf einem Level. Wird bei jedem Programmtimerinterrupt neu programmiert. // OCR0A = 0x00; // // Vergleichswert für PWM mit 0 initialisieren. Wird von main berechnet und überschrieben //TCNT0 = 0x00; // Counter auf 0 setzen TCCR0A = _BV(WGM00) | _BV(WGM01) | _BV(COM0A1); // Timer 0 für Fast PWM konfigurieren TCCR0B |=_BV(CS00) | _BV(WGM02); // Taktgeber auf CPU-Takt setzen } |
Changes to main/timer.h.
1 2 3 4 5 6 7 8 9 10 11 12 | #ifndef TIMER_H #define TIMER_H #include <stdint.h> # define PROGRAM_BUSY 1 # define PROGRAM_IDLE 0 # define TIMER_TICKS_PERIOD 125 # define TIMER_STATUS_OK 0 # define TIMER_STATUS_ERROR 1 | | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #ifndef TIMER_H #define TIMER_H #include <stdint.h> # define PROGRAM_BUSY 1 # define PROGRAM_IDLE 0 # define TIMER_TICKS_PERIOD 125 # define TIMER_STATUS_OK 0 # define TIMER_STATUS_ERROR 1 void setup_Timer(); #endif |