Forum: Mikrocontroller und Digitale Elektronik I/O Pins Abfragen und Vergleichen


von Michael H. (h_m)


Lesenswert?

Guten Tag,

vielleicht kann mir jemand weiterhelfen. Ich möchte über einen interrupt 
int0 einen Rotary-Encoder Abfragen und eine Variable hoch oder runter 
zählen lassen.

Dazu möchte ich den Status von PD2 und PD3 Vergleichen. Das heisst ich 
möchte wissen ob der jeweilige Pin High oder Low ist.

ich möchte das so realisieren, wenn der Interrupt an int0 ausgelöst hat. 
Soll in der ISR dann PD2 mit PD3 verglichen werden. Und wenn PD2 Nicht 
Gleich PD3 ist soll der zaehler um 1 hochgezählt werden. Alle anderen 
Fälle um 1 nach unten.

es funktioniert auch soweit alles nur weiß ich nicht wie ich das mit dem 
Vergleichen in der if abfrage richtig schreiben soll. denn so wie ich es 
jetzt mache zählt mir der Zähler egal in welche richtung ich drehe nur 
nach oben.

hier meine if abfrage zum Vergleich
1
if(A != B)
2
  {
3
    zaehler++;
4
  }
5
  else
6
  {
7
    zaehler--;
8
  }
hier der ganze Code
1
/*
2
 * Encoder_Rotary_Externer_Ueber_Interrupt.c
3
 *
4
 * Created: 01.09.2021 11:20:18
5
 * Author : USER
6
 *
7
 * Atmega8
8
 */ 
9
10
#define F_CPU 8000000
11
12
#include <stdlib.h>
13
#include <avr/io.h>
14
#include <avr/interrupt.h>
15
#include <util/delay.h>
16
#include "serial.h"
17
18
volatile uint8_t zaehler = 0;
19
char buffer[7];
20
21
#define A (1<<PD2)
22
#define B (1<<PD3)
23
24
int main(void)
25
{
26
  setup_uart();
27
  
28
  DDRD &= ~(1<<PD2); // Eingang PD2 Int0
29
  DDRD &= ~(1<<PD3); // Eingang PD3 
30
  DDRB |= (1<<PB5);  // Ausgang PB5 LED
31
  
32
  MCUCR |= (1<<ISC00) ;                 // Int0 jede Flanke löst ein interrupt aus 
33
  //MCUCR |= (1<<ISC01) ;                 // Int0 fallende Flanke löst ein interrupt aus 
34
  //MCUCR |= (1<<ISC01) | (1<<ISC00) ;  // Int0 steigende Flanke löst ein interrupt aus 
35
  GICR |= (1<<INT0);
36
  sei();                        // alle Interrupts aktivieren
37
  
38
    while (1) 
39
    {
40
    itoa( zaehler, buffer, 10);   // convert interger into string (decimal format)
41
    uart_write(buffer);
42
    uart_write(" Volt");
43
    uart_write("\r\n\r\n");       // hier wird zweimal eine neue Zeile begonnen
44
    //_delay_ms(100);
45
    }
46
}
47
48
ISR (INT0_vect)
49
{
50
  PORTB ^= (1<<PB5); // Toggle LED PB5
51
  
52
  if(A != B)
53
  {
54
    zaehler++;
55
  }
56
  else
57
  {
58
    zaehler--;
59
  }
60
  
61
}

von Martin (Gast)


Lesenswert?

Google mal nach Funktionsweise Rotary Encoder
Google mal nach source code Rotary Encoder

Du solltest in den ersten 3 Ergebnissen etwas finden.

von noiasca (Gast)


Lesenswert?

du brauchst nichts neues erfinden:

https://www.mikrocontroller.net/articles/Drehgeber

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Porbiers mal mit "if(B)" statt "if(A != B)"...

: Bearbeitet durch Moderator
von Michael H. (h_m)


Lesenswert?

noiasca schrieb:
> du brauchst nichts neues erfinden:
>
> https://www.mikrocontroller.net/articles/Drehgeber

Das habe ich schon das funktioniert einwandfrei. da steht auch drin 
warum sparvarianten nicht gut sind, aber troztdem will ich es machen.

von A. S. (Gast)


Lesenswert?

Michael H. schrieb:
> #define A (1<<PD2)
> #define B (1<<PD3)

Michael H. schrieb:
> if(A != B)

Ist die Definition für A/B vielleicht falsch? Was soll das darstellen?

von huberdetektor (Gast)


Lesenswert?

A. S. schrieb:
> Ist die Definition für A/B vielleicht falsch?

Falsch ist sie nicht, aber ungeeignet für den Vergleich,
da keine Port-Information gelesen wird.

von huberdetektor (Gast)


Lesenswert?

Michael H. schrieb:
> aber troztdem will ich es machen

Dann werde glücklich mit den prellenden Kontakten.

Jeder ist seines eigenen Glückes Schmied.

Kinder müssen auch erst auf die heisse Herdplatte greifen
bevor sie wissen dass das nicht gut ist.

von A. S. (Gast)


Lesenswert?

huberdetektor schrieb:
> A. S. schrieb:
>> Ist die Definition für A/B vielleicht falsch?
>
> Falsch ist sie nicht, aber ungeeignet für den Vergleich,
> da keine Port-Information gelesen wird.

Naja, deshalb habe ich die if-Abfrage mit gepostet. Keine Ahnung, was 
der TO hinter PD2 und PD3 konkret versteckt. Wenn es 2 bzw. 3 ist, dann 
ist das natürlich falsch.

von huberdetektor (Gast)


Lesenswert?

A. S. schrieb:
> was der TO hinter PD2 und PD3 konkret versteckt.

Der TO versteckt da konkret gar nichts, das ist eine Portbit-
Definition aus den Header-Dateien von Atmel.

Wenn du keine Ahnung hast, einfach mal die ....... halten.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael H. schrieb:
> da steht auch drin warum sparvarianten nicht gut sind,
> aber troztdem will ICH es machen.
Ähem, und warum tust DU es nicht?
Hört sich flapsig an, ist aber so: wenn du es nicht selber machst und 
kapierst, dann lernst du nur, dass du immer Andere fragen musst.

von Michael H. (h_m)


Lesenswert?

ich dachte mir es muss irgendwie einfacher als nachfolgend. So habe ich 
es jetzt gelöst. Aber das gefällt mir nicht.
1
  #define Spur_A !(PIND &(1<<PD2))
2
#define Spur_B !(PIND &(1<<PD3))
3
4
uint8_t A_LOW = 0;
5
uint8_t B_LOW = 0;

1
 f if(Spur_A)
2
  {
3
    A_LOW = 0;
4
  }
5
  else
6
  {
7
    A_LOW = 1;
8
  }
9
  if (Spur_B)
10
  {
11
    B_LOW = 0;
12
  }
13
  else
14
  {
15
    B_LOW = 1;
16
  }
17
  
18
  
19
  
20
  if(A_LOW != B_LOW)
21
  {
22
    zaehler++;
23
  }
24
  else
25
  {
26
    zaehler--;
27
  }
1
/*
2
 * Encoder_Rotary_Externer_Ueber_Interrupt.c
3
 *
4
 * Created: 01.09.2021 11:20:18
5
 * Author : USER
6
 *
7
 * Atmega8
8
 */ 
9
10
#define F_CPU 8000000
11
12
#include <stdlib.h>
13
#include <avr/io.h>
14
#include <avr/interrupt.h>
15
#include <util/delay.h>
16
#include "serial.h"
17
18
volatile uint8_t zaehler = 0;
19
char buffer[7];
20
21
#define A (1<<PD2)
22
#define B (1<<PD3)
23
24
#define Spur_A !(PIND &(1<<PD2))
25
#define Spur_B !(PIND &(1<<PD3))
26
27
uint8_t A_LOW = 0;
28
uint8_t B_LOW = 0;
29
30
31
int main(void)
32
{
33
  setup_uart();
34
  
35
  DDRD &= ~(1<<PD2); // Eingang PD2 Int0
36
  DDRD &= ~(1<<PD3); // Eingang PD3 
37
  DDRB |= (1<<PB5);  // Ausgang PB5 LED
38
  
39
  MCUCR |= (1<<ISC00) ;                 // Int0 jede Flanke löst ein interrupt aus 
40
  //MCUCR |= (1<<ISC01) ;                 // Int0 fallende Flanke löst ein interrupt aus 
41
  //MCUCR |= (1<<ISC01) | (1<<ISC00) ;  // Int0 steigende Flanke löst ein interrupt aus 
42
  GICR |= (1<<INT0);
43
  sei();                        // alle Interrupts aktivieren
44
  
45
    while (1) 
46
    {
47
    itoa( zaehler, buffer, 10);   // convert interger into string (decimal format)
48
    uart_write(buffer);
49
    uart_write(" Volt");
50
    uart_write("\r\n\r\n");       // hier wird zweimal eine neue Zeile begonnen
51
    //_delay_ms(100);
52
    
53
    }
54
}
55
56
ISR (INT0_vect)
57
{
58
  PORTB ^= (1<<PB5); // Toggle LED PB5
59
  
60
  if (Spur_A)
61
  {
62
    A_LOW = 0;
63
  }
64
  else
65
  {
66
    A_LOW = 1;
67
  }
68
  if (Spur_B)
69
  {
70
    B_LOW = 0;
71
  }
72
  else
73
  {
74
    B_LOW = 1;
75
  }
76
  
77
  
78
  
79
  if(A_LOW != B_LOW)
80
  {
81
    zaehler++;
82
  }
83
  else
84
  {
85
    zaehler--;
86
  }
87
  
88
}

von huberdetektor (Gast)


Lesenswert?

Lothar M. schrieb:
> dann lernst du nur, dass du immer Andere fragen musst.

Ja, und dieses Fragen statt Lernen macht er hier seit fünf
Jahren. Fragen deswegen weil er seit den ersten Posts hier
scheinbar nichts dazugelernt hat. Nach fünf Jahren!

von Michael H. (h_m)


Lesenswert?

Lothar M. schrieb:
> Michael H. schrieb:
>> da steht auch drin warum sparvarianten nicht gut sind,
>> aber troztdem will ICH es machen.
> Ähem, und warum tust DU es nicht?
> Hört sich flapsig an, ist aber so: wenn du es nicht selber machst und
> kapierst, dann lernst du nur, dass du immer Andere fragen musst.

> Ähem, und warum tust DU es nicht?
weil ich es gerade Versuche.

> Hört sich flapsig an, ist aber so: wenn du es nicht selber machst und
> kapierst, dann lernst du nur, dass du immer Andere fragen musst.

ich versuche es doch gerade selber zu machen. und die Sparvariante mache 
ich damit ich es gemacht habe und nicht nur gelesen habe das es nicht 
gut ist.

von A. S. (Gast)


Lesenswert?

huberdetektor schrieb:
> Wenn du keine Ahnung hast, einfach mal die ....... halten.

Ja, sorry dass Du den Fehler nicht gefunden hast. Ich habe die 3 
falschen Zeilen identifiziert, Dein Beitrag ist auch wichtig.

von A. S. (Gast)


Lesenswert?

Michael H. schrieb:
> ich dachte mir es muss irgendwie einfacher als nachfolgend

Warum nicht direkt, quasi wie im Ausgangspost?
1
  if(SPUR_A == SPUR_B) {zaehler--;}
2
  else                 {zaehler++;}

Du brauchst hier keine Hilfsvariablen A_LOW und B_LOW. Und auch kein A 
und B. Oder musst halt A und B wir SPUR_A/B definieren.

von Stefan F. (Gast)


Lesenswert?

Verpacke die Abfragen der Port Pins am Besten in Funktionen, dann 
bekommst du keinen Knoten im Kopf.

Bei der Gelegenheit geben wir PD2 und PD3 ordentliche Namen. Da mit der 
Zweck unbekannt ist, nenne ich sie mal Adam und Eva.
1
bool adam()
2
{
3
    return (PIND & (1<<PD2)) > 0;
4
}
5
6
bool eva()
7
{
8
  return (PIND & (1<<PD3)) > 0;
9
}
10
11
12
if (adam() != eva())
13
{
14
   tu etwas;
15
}

von A. S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Verpacke die Abfragen der Port Pins am Besten in Funktionen, dann
> bekommst du keinen Knoten im Kopf.

Es gibt ja viele Unterschiede zwischen Makros und Funktionen. Und 
entsprechend viele Argumente pro und contro.

Aber für den Knoten dürften die Makros des TO
Michael H. schrieb:
> #define Spur_A !(PIND &(1<<PD2))
> #define Spur_B !(PIND &(1<<PD3))

nach adam/eva übersetzt, genauso klar sein
1
#define adam  !(PIND &(1<<PD2))
2
#define eva   !(PIND &(1<<PD3))

von Michael H. (h_m)


Lesenswert?

Danke für die hilfreichen Erklärungen. Jetzt kann ich das wesentlich 
übersichtlicher umsetzen.

von Stefan F. (Gast)


Lesenswert?

Die Funktionen sind übrigens in der Regel genau so effizient wie Makros. 
Der Compiler erzeugt für beide Varianten letztendlich den selben Code.

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
Noch kein Account? Hier anmelden.