AVR eigene Pins verbinden?

Gast #3455579
Lesenswert?

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.
Moderator Persönliche Seite #3455804
Lesenswert?

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.
Gast #3455814
Lesenswert?

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.
Gast #3455991
Lesenswert?

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?
Gast #3456128
Lesenswert?

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
}
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren