Hallo, Prozessor: Atmega8 Ich möchte testweise um zu lernen folgendes tun: Einen Pin mit einer bestimmten Frequenz toggeln und diesen mit PB0 (Input Capture) verbinden. Dann möchte ich einen Code schreiben und die erfasste Zeit bzw. Frequenz am ICP (zwischen zwei gleichen Ereignissen) auf einem LCD ausgeben. Funktioniert das? Kann ich einen eigenen Pin, welcher getoggelt wird am gleichen Prozessor am ICP einlesen? Danke. Daniel.
Daniel schrieb: > Kann ich einen eigenen Pin, welcher getoggelt wird am gleichen Prozessor > am ICP einlesen? Du musst nur an eins denken: die Erfassung der Flanke am Eingang erfolgt beim AVR vor dem Umschalten des Ausgangs. Folgendes funktioniert daher nicht:
1 | PORTB |= (1 << 3); // aktivieren Sensor an PB3 |
2 | bool sensorData = (PINB & (1 << 2)) != 0; // Einlesen an PB2 |
Dazwischen muss mindestens ein NOP sein.
Daniel schrieb: > Ich möchte testweise um zu lernen folgendes tun: > Einen Pin mit einer bestimmten Frequenz toggeln und diesen mit PB0 > (Input Capture) verbinden. Baue aber am besten einen Serienwiderstand ein (so 1kOhm), falls im Programm doch mal beide Pins auf Ausgang gestellt werden.
Jörg Wunsch schrieb: > Daniel schrieb: >> Kann ich einen eigenen Pin, welcher getoggelt wird am gleichen Prozessor >> am ICP einlesen? > > Du musst nur an eins denken: die Erfassung der Flanke am Eingang > erfolgt beim AVR vor dem Umschalten des Ausgangs. Folgendes > funktioniert daher nicht: > PORTB |= (1 << 3); // aktivieren Sensor an PB3 > bool sensorData = (PINB & (1 << 2)) != 0; // Einlesen an PB2 > > Dazwischen muss mindestens ein NOP sein. Ok, Serienwiderstand werde ich einfügen. Aber das habe ich noch nicht ganz verstanden. Wäre jemand so nett und würde mir das nochmals erläutern?
@Jörg Aber er will doch den ICP-Eingang benutzen, ich denke mal in Verbindung mit dem Timer. Dann tritt doch dein genanntes Problem nicht auf. Oder hab' ich einen Denkfehler? -Dirk-
Hallo, ich habe nun einen einfachen Schaltungsaufbau: 2 LEDs 1 Pin als Taktgeber Die eine LED (an PB4) leuchtet im Takt des Taktgebers Die andere LED (an PC0) soll leuchten, wenn das ICP aufgerufen wird. Das Ganze funktioniert leider nicht. Das ICP spricht nicht an, d.h. die LED leuchtet nicht. Wenn ich mit einem Draht eine Verbindung von GND zum ICP (PB0) herstelle, leuchtet die LED aber auf. Demnach scheint der Taktgeber den Pin nicht zu triggern. Der Taktgeber Pin "wackelt" aber. Habe testweise dort auch einmal eine LED dran gehängt. Diese blinkt bzw. für unsere Auge leuchtet sie. Messe ich die Spannung am Taktgeber Pin (unverbunden zum ICP) so liegt sie bei 2,40V. Messe ich die Spannung mit Verbindung zum ICP Pin, so liegt diese bei 4,79V. Anbei ein Foto vom Steckbrettaufbau. Und hier der Code:
1 | // ----------------------------------------------------------------------------
|
2 | // INCLUDES
|
3 | // ----------------------------------------------------------------------------
|
4 | |
5 | #include <stdint.h> // Standard Int-Datentypen |
6 | #include <avr/io.h> // avr Header File für IO Ports |
7 | #include <avr/interrupt.h> // Interrupt Vektoren |
8 | #include <inttypes.h> // Makros für int Datentypen |
9 | |
10 | |
11 | // ----------------------------------------------------------------------------
|
12 | // DEFINES
|
13 | // ----------------------------------------------------------------------------
|
14 | #ifndef F_CPU
|
15 | #define F_CPU 8000000UL // processor clock frequency 8Mhz
|
16 | #endif
|
17 | |
18 | // Pin Defines
|
19 | #define LED1 PB4 // rote LED1
|
20 | #define TAKTGEBER PB7 // Taktgeber
|
21 | |
22 | #define LED2 PC0 // rote LED2
|
23 | |
24 | // Port Defines
|
25 | #define PORTLED1 PORTB
|
26 | #define PORTLED2 PORTC
|
27 | |
28 | // Initialisierungsfunktionen
|
29 | void init_ports(void); |
30 | void init_timer1(void); |
31 | |
32 | |
33 | |
34 | //Timer1 16-bit Input Capture Service Routine
|
35 | ISR (TIMER1_CAPT_vect){ |
36 | if ( !(TCCR1B & (1<<ICES1) )){ // Interrupt bei fallender Flanke |
37 | // LED anschalten
|
38 | PORTLED2 &= ~(1 << LED2); |
39 | }
|
40 | else{ |
41 | // LED ausschalten
|
42 | PORTLED2 |= (1 << LED2); |
43 | }
|
44 | TCCR1B ^= ( 1 << ICES1 ); |
45 | TIFR = ( 1 << ICF1 ); |
46 | }
|
47 | |
48 | |
49 | //Timer1 16-bit Compare Match B Interrupt Service Routine
|
50 | ISR (TIMER1_COMPB_vect){ |
51 | // Aufruf 280x pro Sekunde --> 140Hz
|
52 | PORTB ^= (1 << TAKTGEBER); |
53 | PORTLED1 ^= ( 1 << LED1 ); // Referenz-LED für Taktanzeige |
54 | |
55 | OCR1B = OCR1B+((F_CPU/8000000UL)*28571); |
56 | |
57 | }
|
58 | |
59 | int main(void) |
60 | {
|
61 | |
62 | init_ports(); |
63 | init_timer1(); |
64 | |
65 | |
66 | while (1){ |
67 | |
68 | } // Ende main loop |
69 | } // Ende Hauptprogramm |
70 | |
71 | |
72 | |
73 | void init_ports(void) { |
74 | |
75 | |
76 | DDRB = 0x00; |
77 | DDRB |= (1 << DDB4) | (1 < DDB7) ; // LED und Taktgeber als Ausgänge |
78 | PORTB |= (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3) | (1 << PB4) | (1 << PB6) | (1 << PB7); // Pullup am ICP (PB0 ein) |
79 | |
80 | |
81 | DDRC = 0x00; |
82 | DDRC |= (1 << PC0); // LED2 als Ausgang |
83 | PORTC |= (1 << PC1) | (1 << PC2) | (1 << PC3) | (1 << PC4) | (1 << PC5); |
84 | |
85 | |
86 | DDRD = 0x00; |
87 | PORTD |= (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5) | (1 << PD6) | (1 << PD7) ; |
88 | |
89 | sei(); // setzt globales Interrupt enable |
90 | |
91 | return; |
92 | }
|
93 | |
94 | void init_timer1(void) { |
95 | OCR1B = ((F_CPU/8000000UL)*28571); |
96 | TIMSK |= (1 << TICIE1) | (1 << OCIE1B); // Input Capture Interrupt enable, Compare Match B enable |
97 | TCNT1 = 0; // Timer1 16-bit bei 0 starten |
98 | TCCR1B |= (1 << CS10); // kein Prescaler, Timer1 läuft maximal durch für höchste Auflösung |
99 | return; |
100 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.