1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 | #define F_CPU 16000000UL // definiere Prozessortakt auf 16MHz
|
4 |
|
5 | #define Baud 9600UL // Baudrate definieren
|
6 | #define R_UBRR ((F_CPU / (16L * Baud))-1) // Baudrate umrechnen für das Baudraten-Register
|
7 |
|
8 | volatile unsigned int ADC0 = 0; // der Variable ADC0 wird der Wert 0 zugeordnet
|
9 |
|
10 | volatile unsigned char ADC0_interrupt = 0; // Variable für den Interrupt reservieren
|
11 |
|
12 |
|
13 | // ### Initialisierung der USART
|
14 |
|
15 | void usart_init(void){
|
16 |
|
17 | UBRRH = R_UBRR >> 8; /* R_UBRR in UBRRH schreiben &
|
18 | um 8 Stellen nach rechts verschieben
|
19 | in UBRRH steht: 0000 0000 */
|
20 | UBRRL = R_UBRR; // R_UBRR in UBRRL schreiben
|
21 |
|
22 | UCSRC |= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); /* Zuweisung an UCSRC richten;
|
23 | Datenformat einstellen: 8 Datenbits, 1 Stopp-Bit */
|
24 | UCSRB |= (1<<TXEN); // Sender aktivieren
|
25 | }
|
26 |
|
27 |
|
28 | /* ### Initialisierung des 16-Bit Timer1
|
29 | - 9-Bit PWM-Mode
|
30 | - Fast-PWM
|
31 | - Vorteiler von 1024 --> 15,625 kHz
|
32 | - schreibe 625 ins Vergleichsregister --> 25 Hz
|
33 | - Zählwerte für OCR1A & OCR1B festlegen
|
34 | - PWM-Art bestimmen
|
35 | - OC1A & OC1B sind Ausgänge
|
36 | */
|
37 |
|
38 | void timer_init (){
|
39 |
|
40 | TCCR1A |= (1<<WGM11)| (0<<WGM10); // 9-Bit PWM-Betriebsart
|
41 | TCCR1B |= (1<<WGM13) | (1<<WGM12); // Fast-PWM
|
42 | ICR1 |= 625; // zähle bis 625 --> 25Hz
|
43 | OCR1A |= 312; // PWM an OC1A mit 50% Duty-Cycle
|
44 | OCR1B |= 312; // PWM an OC1B mit 25% Duty-Cycle
|
45 | TCCR1A |= (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0); // invertierende PWM
|
46 | DDRD = (1<<PD5) | (1<<PD4); // OC1A & OC1B als Ausgänge definieren
|
47 | TCCR1B |= (1<<CS10) | (1<<CS12); // Vorteiler von 1024 --> 15,625kHz / Zählbeginn
|
48 | }
|
49 |
|
50 |
|
51 | // ### Initialisierung des Analog-Digital Wandlers mit Referenzspannung AVCC 5V
|
52 |
|
53 | void adc0_init (){
|
54 |
|
55 | ADMUX |= (1<<REFS0); /* AVCC als Referenzspannung
|
56 | 5V */
|
57 | ADCSRA |= (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2); /* Wandelrate des ADC festlegen,
|
58 | Wandelrate = Takt/128 --> 125kHz */
|
59 | ADCSRA |= (1<<ADEN) | (1<<ADIE); // Enable ADC, Interrupt aktivieren
|
60 | ADCSRA |= (1<<ADATE); // ADC auf Dauerwandlung einstellen, Free-Runnig Mode
|
61 | ADCSRA |= (1<<ADSC); // Starten der AD-Wandlung
|
62 | }
|
63 |
|
64 |
|
65 | // ### Interrupt Service Routine für ADC0
|
66 |
|
67 | ISR (ADC_vect){ // ADC löst Interrupt aus
|
68 |
|
69 | ADC0_interrupt = 1; // Variable 'ADC0_interrupt' auf 1 setzen
|
70 | ADC0 = ADC; // ADC auslesen, Wert des ADC in ADC0 schreiben
|
71 | }
|
72 |
|
73 |
|
74 | // ### Mainloop
|
75 |
|
76 | int main (void) { // Mainloop
|
77 |
|
78 | usart_init (); // USART initialisieren
|
79 | adc0_init (); // ADC0 initialisieren
|
80 | timer_init (); // Initialisierung des Timers
|
81 |
|
82 |
|
83 | sei(); // Interrupts aktivieren
|
84 | while (1){
|
85 |
|
86 | if (ADC0_interrupt == 1) { // wenn Variable in ISR gesetzt wurde
|
87 | ADC0 = ADC;
|
88 |
|
89 | while(!(UCSRA & (1<<UDRE))); // Warten bis Sendepuffer leer / bereit zum Senden?
|
90 | UDR = ADC0 >> 8; /* High-Byte senden, ADC0 um 8 Stellen nach rechts verschieben
|
91 | & in UDR (Sendedatenregister) schreiben */
|
92 | while(!(UCSRA & (1<<UDRE))); // Warten bis Sendepuffer leer / bereit zum Senden?
|
93 | UDR = ADC0 & 0xFF; /* Low-Byte senden, ADC0 mit '0000000011111111' &-verknüpfen
|
94 | & in UDR schreiben */
|
95 | ADC0_interrupt = 0; // Variable 'ADC0_interrupt' zurücksetzen
|
96 | }
|
97 | }
|
98 |
|
99 | return 0;
|
100 | }
|