Forum: Mikrocontroller und Digitale Elektronik Taster Entprellung am Attiny 841 und Auswertung


von Paul (Gast)


Lesenswert?

Hallo
ich möchte an einem Attiny verschiedene Tasten entprellen und auswerten. 
Dazu möchte ich die Entprellung von Peter verwenden. Dabei scheint es 
ein paar Probleme zu geben. Das fängt an mit der Belegung der Tasten. 
Diese sind beim Ati 841 auf 2 Ports verteilt. Habe dazu es mal 
angepasst.

Belegung der Hardware:

// PA0 --> T1
// PB0 --> T2
// PA7 --> T3
// PA5 --> T4
// PB1 --> T5
1
volatile uint8_t key_state;
2
volatile uint8_t key_press;
3
volatile uint8_t key_rpt;
4
5
#define KEY_DDR    DDRA            // Datenrichtung A
6
#define KEY_PORT   PORTA           // Angabe Port A
7
#define KEY_PIN    PINA            // Angabe PIN A
8
#define KEY_1       0              // PA 0 - Taster 1
9
#define KEY_3       7              // PA 3 - Taster 3
10
#define KEY_4       5              // PA 5 - Taster 4
11
12
#define KEY_DDR    DDRB             // Datenrichtung B
13
#define KEY_PORT   PORTB            // Angabe Port B
14
#define KEY_PIN    PINB             // Angabe PIN B
15
#define KEY_2       0               // PB 0 - Taster 2
16
#define KEY_5       1               // PB 1 - Taster 5
17
               
18
#define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
19
20
PUEA=0b10100001;          // R auf Taster PORT A
21
PUEB=0b00000011;          // R auf Taster PORT B
22
23
#define REPEAT_MASK (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
24
#define REPEAT_START 50        // after 500ms
25
#define REPEAT_NEXT 20              // every 200ms
Ist das so möglich?
LG Paul

von Anton (Gast)


Lesenswert?

Hallo Paul

Paul schrieb:
> Dabei scheint es
> ein paar Probleme zu geben.

wäre sehr hilfreich, wenn Du angeben würdest, WELCHE Probleme es gibt...

Glaskugelgucken alleine hilft da nicht...


mfg

Anton

von Anton (Gast)


Lesenswert?

Hallo Paul

Paul schrieb:
> Dazu möchte ich die Entprellung von Peter verwenden

wäre schön, wenn Du den GANZEN Namen (nicht nur "Peter") und den link 
für die SW von "Peter" posten würdest...

mfg

Anton

von Veit D. (devil-elec)


Lesenswert?

Hallo,

wenn du schon define verwendest, dann solltest du das konsequent 
durchziehen und die Pullup-Register demzufolge auch mittels der Namen 
konfigurieren.  :-)
Deine KEY_DDR, KEY_PORT und KEY_PIN solltest du nochmal überdenken.
Dein ALL-KEYS und MASK wirst du wohl so niemals verwenden können, weil 
die Taster auf verschiedenen Ports liegen.

von Paul (Gast)


Lesenswert?

Einen Fehler habe ich schon gefunden:
1
volatile uint8_t key_state;
2
volatile uint8_t key_press;
3
volatile uint8_t key_rpt;
4
5
#define KEY_DDRA    DDRA            // Datenrichtung A
6
#define KEY_PORTA   PORTA           // Angabe Port A
7
#define KEY_PINA    PINA            // Angabe PIN A
8
#define KEY_1       0              // PA 0 - Taster 1
9
#define KEY_3       7              // PA 3 - Taster 3
10
#define KEY_4       5              // PA 5 - Taster 4
11
12
#define KEY_DDRB    DDRB             // Datenrichtung B
13
#define KEY_PORTB   PORTB            // Angabe Port B
14
#define KEY_PINB    PINB             // Angabe PIN B
15
#define KEY_2       0               // PB 0 - Taster 2
16
#define KEY_5       1               // PB 1 - Taster 5
17
               
18
#define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
19
20
PUEA=0b10100001;          // R auf Taster PORT A
21
PUEB=0b00000011;          // R auf Taster PORT B
22
23
#define REPEAT_MASK (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
24
#define REPEAT_START 50        // after 500ms
25
#define REPEAT_NEXT 20              // every 200ms
Nehme den Code erst langsam in Betrieb.
Es geht dabei um die Frage, ob ich mit dem Code von Peter Danner. die 
Eingänge auf 2 Ports verteilen kann?

von Paul (Gast)


Lesenswert?

Das ist schon mal ein sehr guter Hinweis. Danke

von Paul (Gast)


Lesenswert?

Meinst du diese Stelle:
1
KEY_DDRA&=~ALL_KEYS;
2
KEY_PORTA|=ALL_KEYS;
3
KEY_DDRB&=~ALL_KEYS;
4
KEY_PORTB|=ALL_KEYS;

von Paul (Gast)


Lesenswert?

Nächstes Problem mit dem Timer:
1
ISR (TIMER0_OVF_vect)        // Timer
2
  {
3
  static uint8_t ct0,ct1,rpt;
4
  uint8_t i;
5
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
6
  i=key_state ^~KEY_PINA;        // PINA oder PINB
7
  ct0=~(ct0&i);
8
  ct1=ct0^(ct1&i);
9
  i&=ct0&ct1;
10
  key_state^=i;
11
  key_press|=key_state&i;
12
  if((key_state & REPEAT_MASK)==0)
13
  rpt=REPEAT_START;
14
  if(--rpt==0)
15
    {
16
    rpt=REPEAT_NEXT;
17
    key_rpt|=key_state & REPEAT_MASK;
18
    }
19
  }
ich meine diese Zeile:
1
i=key_state ^~KEY_PINA;        // PINA oder PINB
Mit original Code steht nur KEY_PIN drin. Da ich jetzt PINA und PINB 
verwende klappt das nicht.

von Peter D. (peda)


Lesenswert?

Paul schrieb:
> Belegung der Hardware:
>
> // PA0 --> T1
> // PB0 --> T2
> // PA7 --> T3
> // PA5 --> T4
> // PB1 --> T5

Das ist jetzt keine Raketenwissenschaft, nur ein Bit überlappt sich.
In der ISR die 5 Bits in ein Byte einsammeln:
1
  uint8_t i = PINA & (1<<PA0 | 1<<PA5 | 1<<PA7);
2
  i |= (PINB & ((1<<PB0 | 1<<PB1)) << 1;
3
// ...

von Paul (Gast)


Lesenswert?

Danke für deine Hilfe.
Es stimmt, es ist keine Raketenwissenschaft. Habe die Erklärung vor mir 
zu liegen und gelesen. Gelesen bedeutet aber nicht es zu verstehen. Ist 
einfach zu kompliziert für mich. Scheint aber auch anderen so zu gehen.
LG Paul

von roehrenvorheizer (Gast)


Lesenswert?

Hallo,

sollten da nicht noch etliche KLammern sein?

#define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)


MfG

von Theor (Gast)


Lesenswert?

roehrenvorheizer schrieb:
> Hallo,
>
> sollten da nicht noch etliche KLammern sein?
>
> #define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
>
>
> MfG

https://de.wikibooks.org/wiki/C-Programmierung:_Liste_der_Operatoren_nach_Priorit%C3%A4t

von Joachim B. (jar)


Lesenswert?

Veit D. schrieb:
> wenn du schon define verwendest, dann solltest du das konsequent
> durchziehen und die Pullup-Register demzufolge auch mittels der Namen
> konfigurieren.  :-)
> Deine KEY_DDR, KEY_PORT und KEY_PIN solltest du nochmal überdenken.
> Dein ALL-KEYS und MASK wirst du wohl so niemals verwenden können, weil
> die Taster auf verschiedenen Ports liegen.

Peter D. schrieb:
> Das ist jetzt keine Raketenwissenschaft, nur ein Bit überlappt sich.
> In der ISR die 5 Bits in ein Byte einsammeln:  uint8_t i = PINA &
> (1<<PA0 | 1<<PA5 | 1<<PA7);
>   i |= (PINB & ((1<<PB0 | 1<<PB1)) << 1;

wollte ich auch gerade vorschlagen, die verschiedenen Port A/B Bits in 
ein neues HilfsByte umzusetzen und dann ganz normal weiterarbeiten

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Sowas ähnliches wäre auch mein Vorschlag. Mach das ganze erstmal auf 
einem Port funktionsfähig und dupliziere dann die Routine für den 
anderen Port.

von Paul (Gast)


Lesenswert?

HJabe den kompletten Code. Er funktioniert ohne Fehlermeldung. Die 
Funktion ist beiden Ports möglich, hat aber ein paar komische Effekte.
1
#define F_CPU 8E6        // Angabe Frequenz
2
#include <avr/io.h>        // Einbindung Datein
3
#include <avr/interrupt.h>
4
#include <stdint.h>
5
6
volatile uint8_t key_state;
7
volatile uint8_t key_press;
8
volatile uint8_t key_rpt;
9
10
#define KEY_DDRA    DDRA           // Datenrichtung A
11
#define KEY_PORTA   PORTA          // Angabe Port A
12
#define KEY_PINA    PINA           // Angabe PIN A
13
#define KEY_1       0              // PA 0 - Taster 1
14
#define KEY_3       7              // PA 7 - Taster 3
15
#define KEY_4       5              // PA 5 - Taster 4
16
17
#define KEY_DDRB    DDRB           // Datenrichtung B
18
#define KEY_PORTB   PORTB          // Angabe Port B
19
#define KEY_PINB    PINB           // Angabe PIN B
20
#define KEY_2       0              // PB 0 - Taster 2
21
#define KEY_5       1              // PB 1 - Taster 5
22
               
23
#define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
24
#define REPEAT_MASK (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
25
#define REPEAT_START 50        // after 500ms
26
#define REPEAT_NEXT 20              // every 200ms
27
28
ISR (TIMER0_OVF_vect)        // Timer
29
  {
30
  static uint8_t ct0,ct1,rpt;
31
  uint8_t i;
32
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
33
  i = PINA & (1<<PINA0 | 1<<PINA5 | 1<<PINA7);
34
  i |= (PINB & ((1<<PINB0 | 1<<PINB1)) << 1);
35
  ct0=~(ct0&i);
36
  ct1=ct0^(ct1&i);
37
  i&=ct0&ct1;
38
  key_state^=i;
39
  key_press|=key_state&i;
40
  if((key_state & REPEAT_MASK)==0)
41
  rpt=REPEAT_START;
42
  if(--rpt==0)
43
    {
44
    rpt=REPEAT_NEXT;
45
    key_rpt|=key_state & REPEAT_MASK;
46
    }
47
  }
48
49
uint8_t get_key_press(uint8_t key_mask)
50
  {
51
  cli();
52
  key_mask &=key_press;
53
  key_press^=key_mask;
54
  sei();
55
  return key_mask;
56
  }
57
58
uint8_t get_key_rpt(uint8_t key_mask)
59
  {
60
  cli();
61
  key_mask &=key_rpt;
62
  key_rpt^=key_mask;
63
  sei();
64
  return key_mask;
65
  }
66
67
uint8_t get_key_short(uint8_t key_mask)
68
  {
69
  cli();
70
  return get_key_press(~key_state & key_mask);
71
  }
72
73
uint8_t get_key_long(uint8_t key_mask)
74
  {
75
  return get_key_press(get_key_rpt(key_mask));
76
  }
77
78
void timer_init()
79
  {            
80
  TCCR0B = (1<<CS02)|(1<<CS00);                // Prescaler 1024
81
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
82
  TIMSK0 |= 1<<TOIE0;                      // Interrupt erlauben
83
  }
84
85
int main(void)              // Programmschleife main
86
  {
87
  timer_init();            // Timer init
88
  
89
  PUEA=0b10100001;          // R auf Taster PORT A
90
  PUEB=0b00000011;          // R auf Taster PORT B
91
  
92
  DDRB=0b00000100;          // Port B auf Ausgang schalten
93
  PORTB = (1<<PINB2);
94
  
95
  KEY_DDRA&=~ALL_KEYS;
96
  KEY_PORTA|=ALL_KEYS;
97
  KEY_DDRB&=~ALL_KEYS;
98
  KEY_PORTB|=ALL_KEYS;
99
  
100
  sei();
101
  while(1)              // Programmschleife while
102
    {
103
    if(get_key_press(1<<KEY_2))    // nur Taste press
104
      {                // LED an
105
      PORTB &= ~(1<<PINB2);    // 3+4,4+5
106
      }
107
    
108
    if(get_key_press(1<<KEY_3))    // nur Taste press
109
      {                // LED aus
110
      PORTB |= (1<<PINB2);
111
      }
112
    }                  // Ende while
113
  }                    // Ende main
Effekte sind
- die LED zur Kontrolle auf L blinkt mit unterschiedlichen Takt
- T1 und T2 reagieren nicht so wie sie sollen

von Theor (Gast)


Lesenswert?

Paul schrieb:
> HJabe den kompletten Code. Er funktioniert ohne Fehlermeldung. Die
> Funktion ist beiden Ports möglich, hat aber ein paar komische Effekte.
1
...
2
> #define KEY_1       0              // PA 0 - Taster 1
3
...
4
> #define KEY_2       0              // PB 0 - Taster 2
5
6
> #define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
7
> #define REPEAT_MASK (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
8
9
>   i = PINA & (1<<PINA0 | 1<<PINA5 | 1<<PINA7);
10
>   i |= (PINB & ((1<<PINB0 | 1<<PINB1)) << 1);
11
...
12
>
> Effekte sind

> - die LED zur Kontrolle auf L blinkt mit unterschiedlichen Takt
Das verstehe ich nicht.

> - T1 und T2 reagieren nicht so wie sie sollen
Und wie reagieren sie? Du solltest Dir analytisches Vorgehen angewöhnen. 
D.h. Verhalten detailliert beschreiben. Daraus ergibt sich meist schon 
ein Hinweis auf die Ursache.

Schau Dir den Code an, den ich aus Deinem extrahiert habe.
KEY_1 und KEY_2 haben die gleiche Bitnummer.
Nach der Verschiebeaktion (der zweite Ausdruck mit i auf der linken 
Seite) haben KEY_2 (und übrigens KEY_5) nicht mehr die Bitnummern wie in 
dem define darüber. Logisch, oder?

Das Verhalten lässt sich vermutlich so beschreiben.
"Fragst Du auf KEY_1 und/oder KEY_2 ab, so bewirken beide Tasten das 
selbe. Es gibt anscheinend, vom Programm aus gesehen, keinen Unterschied 
zwischen den beiden Tasten."

Analoges gilt für die Masken ALL_KEYS und REPEAT_MASK.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

ich halte den Vorschlag mit dem vermischen der Bits beider Ports für 
gefährlich, eben weil sie sich überlappen. Am Ende kommt solcher Mist 
bei raus.
1
#define KEY_1       0              // PA 0 - Taster 1
2
#define KEY_3       7              // PA 7 - Taster 3
3
#define KEY_4       5              // PA 5 - Taster 4
4
5
#define KEY_2       0              // PB 0 - Taster 2
6
#define KEY_5       1              // PB 1 - Taster 5
7
               
8
#define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
9
#define REPEAT_MASK (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)

Setze die einzelnen Bits ein und schaue welcher Unsinn rauskommt.
Wie soll KEY1 und KEY2 unterschieden werden?

Damit das halbwegs vernünftig wird müssten mindestens Offsets rein, 
sodass jedes Tasterbit auf seiner nach außen benannten Tasternummer hin 
entspricht. Dann macht das wieder Sinn, nur dann. Oder jeden Port 
einzeln betrachten.

ALL_KEYS und REPEAT_MASK sind gleich. Muss das so sein?
Auch hier lauert eine Falle bei falscher Verwendung, da sie nicht 
schreibgeschützt sind, also obacht.

In C++ würde ich mir EINE Klasse erstellen und davon soviele Objekte wie 
nötig instanzieren. Das als Randnotiz.

von Paul (Gast)


Lesenswert?

1
#define KEY_DDRA    DDRA           // Datenrichtung A
2
#define KEY_PORTA   PORTA          // Angabe Port A
3
#define KEY_PINA    PINA           // Angabe PIN A
4
#define KEY_1       0              // PA 0 - Taster 1
5
#define KEY_3       7              // PA 7 - Taster 3
6
#define KEY_4       5              // PA 5 - Taster 4
7
8
#define KEY_DDRB    DDRB           // Datenrichtung B
9
#define KEY_PORTB   PORTB          // Angabe Port B
10
#define KEY_PINB    PINB           // Angabe PIN B
11
#define KEY_2       0              // PB 0 - Taster 2
12
#define KEY_5       1              // PB 1 - Taster 5
KEY_1 ist doch PORTA - PA0
KEY_2 ist doch PORTB - PB0
zugeordnet.

Veit D. schrieb:
> ALL_KEYS und REPEAT_MASK sind gleich. Muss das so sein?
> Auch hier lauert eine Falle bei falscher Verwendung, da sie nicht
> schreibgeschützt sind, also obacht.

Im original Code von Peter sind noch andere Verwendungen drin. Diese 
verwende ich (noch) nicht
Es könnte zu einer überlagerung von PA0 und PB0 kommen, könnte auch den 
Effekt mit den Tasten ergeben. Die Tasten 3,4,5 laufen ohne Probleme

von Theor (Gast)


Lesenswert?

Paul schrieb:
> [...]
>
> Im original Code von Peter sind noch andere Verwendungen drin. Diese
> verwende ich (noch) nicht
> Es könnte zu einer überlagerung von PA0 und PB0 kommen, könnte auch den
> Effekt mit den Tasten ergeben. Die Tasten 3,4,5 laufen ohne Probleme

Was heisst "könnte"?
Es wäre m.M.n. zweckmäßig, wenn Du den Code auf dem Papier 
nachvollziehst, die Wirkung der Tatsache, dass KEY_1 und KEY_2 durch den 
gleichen Wert ersetzt werden, beobachtest und dann Änderungen überlegst. 
Diese implementierst Du dann und  testest sie.

von Paul (Gast)


Lesenswert?

Theor schrieb:
> dass KEY_1 und KEY_2 durch den
> gleichen Wert ersetzt werden

Ist das der Hauptgrund? Könnte versuchen die Hardware zu ändern.

von Theor (Gast)


Lesenswert?

Paul schrieb:
> Theor schrieb:
>> dass KEY_1 und KEY_2 durch den
>> gleichen Wert ersetzt werden
>
> Ist das der Hauptgrund? [...]

Das stellst Du fest, wenn Du den Code nachvollziehst.

von Joachim B. (jar)


Lesenswert?

Paul schrieb:
> HJabe den kompletten Code. Er funktioniert ohne Fehlermeldung. Die
> Funktion ist beiden Ports möglich, hat aber ein paar komische Effekte.

du hast das noch nicht zuende gedacht!

Peter D. schrieb:
> uint8_t i = PINA & (1<<PA0 | 1<<PA5 | 1<<PA7);
>   i |= (PINB & ((1<<PB0 | 1<<PB1)) << 1;

was psassiert mit deinen KEYS

Paul schrieb:
> #define KEY_DDR    DDRB             // Datenrichtung B
> #define KEY_PORT   PORTB            // Angabe Port B
> #define KEY_PIN    PINB             // Angabe PIN B
> #define KEY_2       0               // PB 0 - Taster 2
> #define KEY_5       1               // PB 1 - Taster 5

nach schieben
>   i |= (PINB & ((1<<PB0 | 1<<PB1)) << 1;

sie werden Bit 1 und Bit 2 welche in der Variable i ja noch frei waren.

Danach sind deine Keys aber KEY_2 ehemals 0 aber 1 durch schieben und 
KEY5 ehemals 1 aber 2 durch schieben!

Es gibt dann keine dopppelt belegten Bits mehr in Variable i

Veit D. schrieb:
> #define KEY_1       0              // PA 0 - Taster 1
> #define KEY_3       7              // PA 7 - Taster 3
> #define KEY_4       5              // PA 5 - Taster 4

NEU

> #define KEY_2       1              // PB 0 - Taster 2
> #define KEY_5       2              // PB 1 - Taster 5
>
> #define ALL_KEYS (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)
> #define REPEAT_MASK (1<<KEY_1|1<<KEY_2|1<<KEY_3|1<<KEY_4|1<<KEY_5)

von Paul (Gast)


Lesenswert?

Joachim B. schrieb:
> NEU
>
>> #define KEY_2       1              // PB 0 - Taster 2
>> #define KEY_5       2              // PB 1 - Taster 5

Meinst du damit das ich die 0 --> 1 und die 1 --> 2 ändern soll?

von Karl M. (Gast)


Lesenswert?

Paul schrieb:
> Joachim B. schrieb:
>> NEU
>>
>>> #define KEY_2       1              // PB 0 - Taster 2
>>> #define KEY_5       2              // PB 1 - Taster 5
>
> Meinst du damit das ich die 0 --> 1 und die 1 --> 2 ändern soll?

Nicht ganz.

Deine realen PinPort Definitionen werden auf eineindeutige ID gepappt.

Du musst somit die Hardware Definitionen und die notwendige PinPort 
Initialisierung von realen Zugriff über das Mapping auf die nun 
"virtuellen" Tasten, trennen.

Du schreibst, und beachte, dass Defines nicht doppelt belegt werden 
können!
Siehe: KEY_DDR, KEY_PORT und KEY_PIN
1
#define KEY_1       0              // PA 0 - Taster 1
2
#define KEY_3       7              // PA 3 - Taster 3
3
#define KEY_4       5              // PA 5 - Taster 4
4
5
#define KEY_2       0               // PB 0 - Taster 2
6
#define KEY_5       1               // PB 1 - Taster 5

Tastenmapping | realer Taster
0             | KEY_1
7             | KEY_3
5             | KEY_4
// hier bitte den Post von Peter Dannegger beachten!
1             | KEY_2
2             | KEY_5

Wenn Du also die Funktionen der Tastenenprellung nutzen möchtest,
dann sind die Mappping ID zu nutzen, bzw. der Bitmaske.
Hier einige Defines dazu:
1
#define MAP_KEY_1 0
2
#define MAP_KEY_3 7
3
#define MAP_KEY_4 5
4
#define MAP_KEY_2 1
5
#define MAP_KEY_5 2

Und solange Du nicht Funktionen der Tastenenprellung verstehst, wirst Du 
diese Erweiterungen nicht umsetzen können.

von Paul (Gast)


Lesenswert?

Habe nachgelesen was Mapping so macht.
Die Funktion der Tasterentprellung versteh ich nicht. Auch mit einer 
Erklärung ist es zu kompliziert für mich. Wie ich feststellen konnte, 
geht es auch vielen anderen so. Mit der Anwendung klappt es besser. 
Verwende die Entprellung in verschiedenen Projekten. Alles ohne 
Probleme.
Vielleicht könnte mir jemand weiterhelfen oder ist es besser die 
Hardware zu ändern?

von Karl M. (Gast)


Lesenswert?

Paul schrieb:
> Habe nachgelesen was Mapping so macht.
> Die Funktion der Tasterentprellung versteh ich nicht. Auch mit einer
> Erklärung ist es zu kompliziert für mich. Wie ich feststellen konnte,
> geht es auch vielen anderen so. Mit der Anwendung klappt es besser.
> Verwende die Entprellung in verschiedenen Projekten. Alles ohne
> Probleme.
> Vielleicht könnte mir jemand weiterhelfen oder ist es besser die
> Hardware zu ändern?

Dann nimm dir bitte 4 Wochen Zeit zum C lernen und dann Verstehen der 
Codeteile.

Wissen braucht halt Zeit und Übung.
Durch Fehler lernt man am meisten.
Ohne Dir, als evtl. Jugendlicher, näher treten zu wollen, es wird schon.
Bleibe am Ball!

von Joachim B. (jar)


Lesenswert?

Paul schrieb:
> Die Funktion der Tasterentprellung versteh ich nicht

musst du auch nicht vollständig verstehen, was du verstehen solltest

deine Tasten an PB liegen auf 0 & 1

die liest du ein auf ein Hilfsbyte

Peter D. schrieb:
> (PINB & ((1<<PB0 | 1<<PB1)) << 1;

also uint8_t hilfsbyte = (PINB & ((1<<PB0 | 1<<PB1)) << 1;

geschiftet nach links

also liegt dein KEY_2 danach auf Bit 1 und dein KEY_5 auf Bit 2

und passt in deine Lücke

Paul schrieb:
> #define KEY_1       0              // PA 0 - Taster 1
> #define KEY_3       7              // PA 3 - Taster 3
> #define KEY_4       5              // PA 5 - Taster 4

denn du benutztes ja nur 0 5 7 -> 1 2 waren frei, da liegen jetzt deine 
Tasten KEY_2 und KEY_5

musst halt nur
KEY_2 auf 1 abfragen
KEY_5 auf 2 abfragen

per #define

: Bearbeitet durch User
von Karl M. (Gast)


Lesenswert?

Hi Joachim B.,

hatte wir schon versucht zu erläutern, hat er bisher leider nicht 
verstanden.

Evtl. schreibt jemand mal alles Komplett, dann ist es nur Copy & Paste.

von Peter D. (peda)


Lesenswert?

Da der ATtiny ja eh fast nichts zu tun hat, kann man natürlich auch auf 
16 Bit erweitern, vorzugsweise mit einem typedef.
1
typedef uint16_t key_t;
2
volatile key_t key_state;
3
volatile key_t key_press;
4
volatile key_t key_rpt;
5
// ..
6
// ISR:
7
  key_t i = PINA | (PINB<<8);
8
// ..
9
key_t get_key_press(key_t key_mask)
Je nach typedef kann man so bis auf 64 Tasten erweitern.

von Karl M. (Gast)


Lesenswert?

Peter D. schrieb:
> Da der ATtiny ja eh fast nichts zu tun hat, kann man natürlich
> auch auf
> 16 Bit erweitern, vorzugsweise mit einem typedef.typedef uint16_t key_t;
> volatile key_t key_state;
> volatile key_t key_press;
> volatile key_t key_rpt;
> // ..
> // ISR:
>   key_t i = PINA | (PINB<<8);
> // ..
> key_t get_key_press(key_t key_mask)
> Je nach typedef kann man so bis auf 64 Tasten erweitern.

Super Peter,

als Ergänzung:

Die Taster an Port A: 0-7 erreicht man nun über die IDs 0-7 und
Die Taster an Port B: 0-7 erreicht man nun über die IDs 8-15 bei der 
Nutzung der Tastenenprellfunktionen.
Dies bezeichne ich dann auch als Mapping.

Deine Benennung deiner Taster KEY1 auf die realen PortPins ist dann eine 
weiteres Mapping!

Beispiel:
KEY_1 liegt auf Port A Bit 0
KEY_3 liegt auf Port A Bit 7

Um dann KEY_1 abfragen zu können, muss man welches Zuordnung verwenden?

Und etwas schwieriger, was gilt für KEY_3?

von Nico W. (nico_w)


Lesenswert?

Man könnte auch das Einlesen und die Entprellroutine voneinander 
entkoppeln. Kostet ggf. ein paar Takte aber dann kann man Schließer und 
Öffner abbilden.

von Karl M. (Gast)


Lesenswert?

Nico W. schrieb:
> Man könnte auch das Einlesen und die Entprellroutine voneinander
> entkoppeln. Kostet ggf. ein paar Takte aber dann kann man Schließer und
> Öffner abbilden.

Warum? Das sucht der TO gar nicht.

Die Tastenentprell-Routine macht das auch automatisch!

von Paul (Gast)


Lesenswert?

Mit einer Sache hast du Recht, die übung fehlt und das Verständnis für 
grosse oder komplizierte Codes. Da hilft wahrscheinlich keine 4 Wochen 
lernen. Könnte sich wahrscheinlich um Jahre handeln, falls überhaupt.
Allein der Code von Peter ist sehr komplex. Da hilft auch ein C Buch 
nicht allzu weit. Egal, mache weiter und versuche es zu verstehen. Wenn 
das nicht so klappt muss ich halt euch wieder fragen. Es ist 
wahrscheinlich nicht verkehrt wenn ihr auch etwas mehr Hilfe kommt. Ist 
sehr hilfreich wenn man einen Code hat der läuft und diesen dann 
auseinander nehmen kann um die Funktion zu begreifen und weiter 
zuentwickeln.
Egal, mache weiter und hoffe das auch mal bei mir funktioniert.
LG Paul

von Paul (Gast)


Lesenswert?

Joachim B. schrieb:
> denn du benutztes ja nur 0 5 7 -> 1 2 waren frei, da liegen jetzt deine
> Tasten KEY_2 und KEY_5
>
> musst halt nur
> KEY_2 auf 1 abfragen
> KEY_5 auf 2 abfragen
>
> per #define

das mit geschiftet habe ich verstanden

Joachim B. schrieb:
> also uint8_t hilfsbyte = (PINB & ((1<<PB0 | 1<<PB1)) << 1;
>
> geschiftet nach links
>
> also liegt dein KEY_2 danach auf Bit 1 und dein KEY_5 auf Bit 2

meine Tasten liegen dann auf 7 5 2 1 0
Habe im Netz nach mapping gesucht. Es gibt die verschiedensten Begriffe 
und Anwendungen dazu. Leider führt keine Quelle zum Ziel.
Sorry, komme nicht weiter. Die gezeigten Beispiel bringen etwas Licht 
ins Dunkel, leider fehlt noch viel.

von Peter D. (peda)


Lesenswert?

Paul schrieb:
> Allein der Code von Peter ist sehr komplex. Da hilft auch ein C Buch
> nicht allzu weit.

Vor allem sollte man sich mal mit den Zahlensystemen und den logischen 
Operatoren beschäftigen.
Die CPU rechnet intern ausschließlich binär und ein Byte besteht aus 8 
Bit.
Logische Operatoren (AND, OR, XOR, Schieben) arbeiten immer auf 
Bitebene.
Zum besseren Verständnis kann man mit dem Windows-Taschenrechner üben.
Allerdings nicht mit der kastrierten Version von W10, sondern mit dem 
Microsoft Rechner-Plus.
Das Schieben von Konstanten erfolgt schon zur Compilezeit, kostet also 
keinen Code. Wenn dadurch ein Ausdruck besser verstehbar wird, sollte 
man es gegenüber magischen Zahlen immer vorziehen.
Auch sollte man Bitwerte nie dezimal hinschreiben. Entweder in hex oder 
binär. Oktal würde ich nicht mehr verwenden.

von Theor (Gast)


Lesenswert?

Paul schrieb:
> Joachim B. schrieb:
>> [...]
>> also liegt dein KEY_2 danach auf Bit 1 und dein KEY_5 auf Bit 2
>
> meine Tasten liegen dann auf 7 5 2 1 0

Wenn Du Joachims Satz nochmal betrachten willst, könnte man den Satz so 
formulieren.
"Deine Tasten liegen auf den Bits mit den Nummern 7, 5, 2, 1 und 0."

> Habe im Netz nach mapping gesucht. Es gibt die verschiedensten Begriffe
> und Anwendungen dazu. Leider führt keine Quelle zum Ziel.
> Sorry, komme nicht weiter. Die gezeigten Beispiel bringen etwas Licht
> ins Dunkel, leider fehlt noch viel.

Es geht um Zuordnungen. "Mapping" heisst in diesem Zusammenhang 
"Zuordnung".
Eine sehr häufig vorkommende Tätigkeit beim Programm- und 
Schaltungsentwurf und auch Operation in Programmen.

Zugeordnet werden einander immer mindestens zwei Elemente.
In Deinem Fall z.B. die Tasten einer Bitnummer im Port.
Aber auch Deine Tasten einer Bitnummer in der Variablen i (in dem obigen 
Code).
Wichtig ist in diesem Zusammenhang der Vergleich dieser beiden 
Zuordnungen.  (Erstmal für Dich zum (Teil-) Verständnis der Funktion).

In der Mathematik heisst eine Zuordnung "Abbildung" - eine andere 
Übersetzung von "Mapping". Kennst Du vielleicht.

von Paul (Gast)


Lesenswert?

Versuche es zu verstehen.
Zuordnung bedeutet also in seiner Grundform, das ich durch ein Programm 
eine taste an einen bestimmten PIN/PORT anschliesse und damit einem 
bestimmten Bit in einem Byte zuordne.
Beispiel:
1
PUEA=0b10100001;
in diesem Fall ordne ich dem Register PUE A, vertreten durch das Byte, 
dem Bit 0,5,7 eine 1 zu. Dadurch schalte ich mit dem Register 
entsprechende Widerstände von Vcc ein. Dadurch wird der Wert des PINS 
auf Vcc gelegt und durch den Taster nach GND gezogen und eine eindeutige 
zuordnung vorgenommen.

Theor schrieb:
> Aber auch Deine Tasten einer Bitnummer in der Variablen i (in dem obigen
> Code).
Da ich verschiedene PIN/Porteingänge nutze (für die einzelnen Taster) 
ergibt sich das Bitmuster

Theor schrieb:
> "Deine Tasten liegen auf den Bits mit den Nummern 7, 5, 2, 1 und 0."


Theor schrieb:
> Aber auch Deine Tasten einer Bitnummer in der Variablen i (in dem obigen
> Code).

In der Variablen i sind als erstes die Bits 7 5 2 belegt.
Wenn ich eine Taste betätige auf 1 und sonst 0?
Danach wird nach links geschiftet. Bedeutet das ich die Werte von PB? um 
eine Stelle nach links schiebe. Wenn das so ist und alle Tasten gedrückt 
werden ergibt sich für die Variable i (8 Bit) der Wert 0b10100111.

Sorry, das ist für mich lautgedacht und folge den Ausführungen an 
Beispielen. Falls Fehler drin sind bitte sofort mit Kritik kommen.

von Theor (Gast)


Lesenswert?

Paul schrieb:
> Versuche es zu verstehen.
> Zuordnung bedeutet also in seiner Grundform, das ich durch ein Programm
> eine taste an einen bestimmten PIN/PORT anschliesse und damit einem
> bestimmten Bit in einem Byte zuordne.

Nein. Oder allenfalls "jein" mit viel Kopfwackeln.
Zuordnung bedeutet ganz allgemein, eine Beziehung zwischen zwei Dingen.

Ich halte es nicht für nützlich an dieser Stelle allzu tief in 
philologische Überlegungen zu gehen.

Eine Zuordnung ist im wesentlichen etwas, was in Deinem Kopf oder auf 
dem Papier stattfindet. Ein abstrakter Vorgang, nichts Reales. Das diese 
Zuordnung oft auch eine physische, reale Entsprechung hat ist nicht 
notwendig, damit es sich um eine Zuordnung handelt.
Man unterscheidet mehr oder weniger streng zwischen der Zuordnung und 
der Handlung oder dem realen Objekt, dass diese Zuordnung repräsentiert.

Siehe auch: https://de.wikipedia.org/wiki/Zuordnung . Dort ist das 
lediglich sozusagen eine Idee, eine gedankliche Konstruktion. Klar?

> Beispiel:
>
1
> PUEA=0b10100001;
2
>
> in diesem Fall ordne ich dem Register PUE A, vertreten durch das Byte,
> dem Bit 0,5,7 eine 1 zu.

Nein. Das ist eine Zuweisung in einem Programm.

Die Zuordnung entsteht entweder im Vorhinein, wenn Du einen Prozessor 
entwirfst, oder im Nachhinein, wenn Du die Wirkung dieser Anweisung 
beobachtest.

> Dadurch schalte ich mit dem Register
> entsprechende Widerstände von Vcc ein. Dadurch wird der Wert des PINS
> auf Vcc gelegt und durch den Taster nach GND gezogen und eine eindeutige
> zuordnung vorgenommen.

Nein. Siehe oben.

> Theor schrieb:
>> Aber auch Deine Tasten einer Bitnummer in der Variablen i (in dem obigen
>> Code).
> Da ich verschiedene PIN/Porteingänge nutze (für die einzelnen Taster)
> ergibt sich das Bitmuster

Ja.

> Theor schrieb:
>> "Deine Tasten liegen auf den Bits mit den Nummern 7, 5, 2, 1 und 0."
>
>
> Theor schrieb:
>> Aber auch Deine Tasten einer Bitnummer in der Variablen i (in dem obigen
>> Code).
>
> In der Variablen i sind als erstes die Bits 7 5 2 belegt.
Was meinst Du mit "belegt"?
Was ich meinte, war die Zuordnung von Tasten zu Bitnummern. Nicht 
weniger, aber auch nicht mehr. :-)

> [...]

Der Punkt ist, dass Du aus den Operationen die Zuordnungen von den 
realen Tasten zu den Bitnummern erkennen kannst. Und umgekehrt, aus der 
Zuordnung der realen Tasten zu den gewollten Bitnummern die dazu nötigen 
Operationen. Das ist alles.

von Theorie (Gast)


Lesenswert?

Hallo

Das ist zwar eine sehr schöne theoretische Abhandlung, bring the aber 
den TO keinen Schritt der Lösung näher.

von Veit D. (devil-elec)


Lesenswert?

Paul schrieb:
>
1
> #define KEY_1       0              // PA 0 - Taster 1
2
> #define KEY_2       0              // PB 0 - Taster 2
3
>
> KEY_1 ist doch PORTA - PA0
> KEY_2 ist doch PORTB - PB0
> zugeordnet.


Das Problem besteht gedanklich. Das KEY_1 an Port A hängt und KEY_2 an 
Port B weißt nur du. Das Programm weiß das nicht. Für das Programm ist 
KEY_1 ein Wert 0 und KEY_2 ein Wert 0. Du verwendest beide beim Bit 
schieben als Wertigkeit. Damit landen beide Bits auf dem gleichen Bit, 
nämlich Bit 0. Dadurch kannst du sie nicht unterscheiden.

Du kannst das mittels Offset wie ich sagte und Peter schon zeigte 
korrigieren. Nur mir persönlich gefällt der gesamte define und 
Korrekturwahnsinn überhaupt nicht. Das ist viel zu Fehleranfällig. 
Merkste ja selbst.

Deswegen ein Vorschlag der wenig Spielraum für Fehler hat. Ungetestet, 
kompiliert jedoch mit C Compiler. Wenn Grundprinzip verstanden wurde ist 
es ausbaufähig. Warum C keine Konstante für die Indexgröße mag weiß ich 
nicht. Vielleicht kann das jemand erklären?
1
#include <avr/io.h>
2
3
//const uint8_t ANZAHLTASTER = 5;  // funktioniert leider nicht "variably modified 'tasterStatus' at file scope"
4
#define ANZAHLTASTER 5
5
// Indexreihenfolge wie KEY Nummerrierung
6
const uint8_t tasterPortBit [ANZAHLTASTER] = {0, 0, 7, 5, 1};
7
volatile uint8_t const *tasterRegPIN  [ANZAHLTASTER] = {&PINA, &PINB, &PINA, &PINA, &PINB};
8
9
uint8_t tasterStatus [ANZAHLTASTER] = {0};
10
11
12
void updateTaster();
13
14
15
int main(void)
16
{
17
    // mit Pullups einmalig einlesen zur "Initialisierung"
18
19
    while (1) 
20
    {
21
        // zyklisch aufrufen
22
        updateTaster();
23
    }
24
}
25
26
27
void updateTaster()
28
{
29
    for (uint8_t i=0; i<ANZAHLTASTER; i++)
30
    {
31
        tasterStatus[i] = *tasterRegPIN[i] >> tasterPortBit[i] & 1;
32
    }
33
}

von neuer PIC Freund (Gast)


Lesenswert?

> Allein der Code von Peter ist sehr komplex.

Vielleicht etwas abseits zur Fragestellung, aber zur Anschauung recht 
gut:
1
                              KEY_PIN     i           ct0         ct1         key_state   key_press
2
initial values                            00000000    00000000    00000000    00000000    00000000 
3
i = key_state ^ ~KEY_PIN      11111111    00000000    00000000    00000000    00000000    00000000 
4
ct0 = ~(ct0 & i)              11111111    00000000    11111111    00000000    00000000    00000000 
5
ct1 = ct0 ^ (ct1 & i)         11111111    00000000    11111111    11111111    00000000    00000000 
6
i &= ct0 & ct1                11111111    00000000    11111111    11111111    00000000    00000000 
7
key_state ^= i                11111111    00000000    11111111    11111111    00000000    00000000 
8
key_press |= key_state & i    11111111    00000000    11111111    11111111    00000000    00000000 
9
---intcall end -----------------
10
i = key_state ^ ~KEY_PIN      11111111    00000000    11111111    11111111    00000000    00000000 
11
ct0 = ~(ct0 & i)              11111111    00000000    11111111    11111111    00000000    00000000 
12
ct1 = ct0 ^ (ct1 & i)         11111111    00000000    11111111    11111111    00000000    00000000 
13
i &= ct0 & ct1                11111111    00000000    11111111    11111111    00000000    00000000 
14
key_state ^= i                11111111    00000000    11111111    11111111    00000000    00000000 
15
key_press |= key_state & i    11111111    00000000    11111111    11111111    00000000    00000000 
16
---intcall end -----------------
17
i = key_state ^ ~KEY_PIN      11111111    00000000    11111111    11111111    00000000    00000000 
18
ct0 = ~(ct0 & i)              11111111    00000000    11111111    11111111    00000000    00000000 
19
ct1 = ct0 ^ (ct1 & i)         11111111    00000000    11111111    11111111    00000000    00000000 
20
i &= ct0 & ct1                11111111    00000000    11111111    11111111    00000000    00000000 
21
key_state ^= i                11111111    00000000    11111111    11111111    00000000    00000000 
22
key_press |= key_state & i    11111111    00000000    11111111    11111111    00000000    00000000 
23
---intcall end -----------------
24
i = key_state ^ ~KEY_PIN      11111110    00000001    11111111    11111111    00000000    00000000 
25
ct0 = ~(ct0 & i)              11111110    00000001    11111110    11111111    00000000    00000000 
26
ct1 = ct0 ^ (ct1 & i)         11111110    00000001    11111110    11111111    00000000    00000000 
27
i &= ct0 & ct1                11111110    00000000    11111110    11111111    00000000    00000000 
28
key_state ^= i                11111110    00000000    11111110    11111111    00000000    00000000 
29
key_press |= key_state & i    11111110    00000000    11111110    11111111    00000000    00000000 
30
---intcall end -----------------
31
i = key_state ^ ~KEY_PIN      11111110    00000001    11111110    11111111    00000000    00000000 
32
ct0 = ~(ct0 & i)              11111110    00000001    11111111    11111111    00000000    00000000 
33
ct1 = ct0 ^ (ct1 & i)         11111110    00000001    11111111    11111110    00000000    00000000 
34
i &= ct0 & ct1                11111110    00000000    11111111    11111110    00000000    00000000 
35
key_state ^= i                11111110    00000000    11111111    11111110    00000000    00000000 
36
key_press |= key_state & i    11111110    00000000    11111111    11111110    00000000    00000000 
37
---intcall end -----------------
38
i = key_state ^ ~KEY_PIN      11111110    00000001    11111111    11111110    00000000    00000000 
39
ct0 = ~(ct0 & i)              11111110    00000001    11111110    11111110    00000000    00000000 
40
ct1 = ct0 ^ (ct1 & i)         11111110    00000001    11111110    11111110    00000000    00000000 
41
i &= ct0 & ct1                11111110    00000000    11111110    11111110    00000000    00000000 
42
key_state ^= i                11111110    00000000    11111110    11111110    00000000    00000000 
43
key_press |= key_state & i    11111110    00000000    11111110    11111110    00000000    00000000 
44
---intcall end -----------------
45
i = key_state ^ ~KEY_PIN      11111110    00000001    11111110    11111110    00000000    00000000 
46
ct0 = ~(ct0 & i)              11111110    00000001    11111111    11111110    00000000    00000000 
47
ct1 = ct0 ^ (ct1 & i)         11111110    00000001    11111111    11111111    00000000    00000000 
48
i &= ct0 & ct1                11111110    00000001    11111111    11111111    00000000    00000000 
49
key_state ^= i                11111110    00000001    11111111    11111111    00000001    00000000 
50
key_press |= key_state & i    11111110    00000001    11111111    11111111    00000001    00000001 
51
---intcall end -----------------
52
i = key_state ^ ~KEY_PIN      11111110    00000000    11111111    11111111    00000001    00000001 
53
ct0 = ~(ct0 & i)              11111110    00000000    11111111    11111111    00000001    00000001 
54
ct1 = ct0 ^ (ct1 & i)         11111110    00000000    11111111    11111111    00000001    00000001 
55
i &= ct0 & ct1                11111110    00000000    11111111    11111111    00000001    00000001 
56
key_state ^= i                11111110    00000000    11111111    11111111    00000001    00000001 
57
key_press |= key_state & i    11111110    00000000    11111111    11111111    00000001    00000001 
58
---intcall end -----------------
59
i = key_state ^ ~KEY_PIN      11111110    00000000    11111111    11111111    00000001    00000001 
60
ct0 = ~(ct0 & i)              11111110    00000000    11111111    11111111    00000001    00000001 
61
ct1 = ct0 ^ (ct1 & i)         11111110    00000000    11111111    11111111    00000001    00000001 
62
i &= ct0 & ct1                11111110    00000000    11111111    11111111    00000001    00000001 
63
key_state ^= i                11111110    00000000    11111111    11111111    00000001    00000001 
64
key_press |= key_state & i    11111110    00000000    11111111    11111111    00000001    00000001 
65
---intcall end -----------------
66
i = key_state ^ ~KEY_PIN      11111110    00000000    11111111    11111111    00000001    00000001 
67
ct0 = ~(ct0 & i)              11111110    00000000    11111111    11111111    00000001    00000001 
68
ct1 = ct0 ^ (ct1 & i)         11111110    00000000    11111111    11111111    00000001    00000001 
69
i &= ct0 & ct1                11111110    00000000    11111111    11111111    00000001    00000001 
70
key_state ^= i                11111110    00000000    11111111    11111111    00000001    00000001 
71
key_press |= key_state & i    11111110    00000000    11111111    11111111    00000001    00000001 
72
---intcall end -----------------
73
i = key_state ^ ~KEY_PIN      11111110    00000000    11111111    11111111    00000001    00000001 
74
ct0 = ~(ct0 & i)              11111110    00000000    11111111    11111111    00000001    00000001 
75
ct1 = ct0 ^ (ct1 & i)         11111110    00000000    11111111    11111111    00000001    00000001 
76
i &= ct0 & ct1                11111110    00000000    11111111    11111111    00000001    00000001 
77
key_state ^= i                11111110    00000000    11111111    11111111    00000001    00000001 
78
key_press |= key_state & i    11111110    00000000    11111111    11111111    00000001    00000001 
79
---intcall end -----------------
80
i = key_state ^ ~KEY_PIN      11111111    00000001    11111111    11111111    00000001    00000001 
81
ct0 = ~(ct0 & i)              11111111    00000001    11111110    11111111    00000001    00000001 
82
ct1 = ct0 ^ (ct1 & i)         11111111    00000001    11111110    11111111    00000001    00000001 
83
i &= ct0 & ct1                11111111    00000000    11111110    11111111    00000001    00000001 
84
key_state ^= i                11111111    00000000    11111110    11111111    00000001    00000001 
85
key_press |= key_state & i    11111111    00000000    11111110    11111111    00000001    00000001 
86
---intcall end -----------------
87
i = key_state ^ ~KEY_PIN      11111111    00000001    11111110    11111111    00000001    00000001 
88
ct0 = ~(ct0 & i)              11111111    00000001    11111111    11111111    00000001    00000001 
89
ct1 = ct0 ^ (ct1 & i)         11111111    00000001    11111111    11111110    00000001    00000001 
90
i &= ct0 & ct1                11111111    00000000    11111111    11111110    00000001    00000001 
91
key_state ^= i                11111111    00000000    11111111    11111110    00000001    00000001 
92
key_press |= key_state & i    11111111    00000000    11111111    11111110    00000001    00000001 
93
---intcall end -----------------
94
i = key_state ^ ~KEY_PIN      11111111    00000001    11111111    11111110    00000001    00000001 
95
ct0 = ~(ct0 & i)              11111111    00000001    11111110    11111110    00000001    00000001 
96
ct1 = ct0 ^ (ct1 & i)         11111111    00000001    11111110    11111110    00000001    00000001 
97
i &= ct0 & ct1                11111111    00000000    11111110    11111110    00000001    00000001 
98
key_state ^= i                11111111    00000000    11111110    11111110    00000001    00000001 
99
key_press |= key_state & i    11111111    00000000    11111110    11111110    00000001    00000001 
100
---intcall end -----------------
101
i = key_state ^ ~KEY_PIN      11111111    00000001    11111110    11111110    00000001    00000001 
102
ct0 = ~(ct0 & i)              11111111    00000001    11111111    11111110    00000001    00000001 
103
ct1 = ct0 ^ (ct1 & i)         11111111    00000001    11111111    11111111    00000001    00000001 
104
i &= ct0 & ct1                11111111    00000001    11111111    11111111    00000001    00000001 
105
key_state ^= i                11111111    00000001    11111111    11111111    00000000    00000001 
106
key_press |= key_state & i    11111111    00000001    11111111    11111111    00000000    00000001 
107
---intcall end -----------------
108
i = key_state ^ ~KEY_PIN      11111111    00000000    11111111    11111111    00000000    00000001 
109
ct0 = ~(ct0 & i)              11111111    00000000    11111111    11111111    00000000    00000001 
110
ct1 = ct0 ^ (ct1 & i)         11111111    00000000    11111111    11111111    00000000    00000001 
111
i &= ct0 & ct1                11111111    00000000    11111111    11111111    00000000    00000001 
112
key_state ^= i                11111111    00000000    11111111    11111111    00000000    00000001 
113
key_press |= key_state & i    11111111    00000000    11111111    11111111    00000000    00000001 
114
---intcall end -----------------
115
i = key_state ^ ~KEY_PIN      11111111    00000000    11111111    11111111    00000000    00000001 
116
ct0 = ~(ct0 & i)              11111111    00000000    11111111    11111111    00000000    00000001 
117
ct1 = ct0 ^ (ct1 & i)         11111111    00000000    11111111    11111111    00000000    00000001 
118
i &= ct0 & ct1                11111111    00000000    11111111    11111111    00000000    00000001 
119
key_state ^= i                11111111    00000000    11111111    11111111    00000000    00000001 
120
key_press |= key_state & i    11111111    00000000    11111111    11111111    00000000    00000001 
121
---intcall end -----------------
122
i = key_state ^ ~KEY_PIN      11111111    00000000    11111111    11111111    00000000    00000001 
123
ct0 = ~(ct0 & i)              11111111    00000000    11111111    11111111    00000000    00000001 
124
ct1 = ct0 ^ (ct1 & i)         11111111    00000000    11111111    11111111    00000000    00000001 
125
i &= ct0 & ct1                11111111    00000000    11111111    11111111    00000000    00000001 
126
key_state ^= i                11111111    00000000    11111111    11111111    00000000    00000001 
127
key_press |= key_state & i    11111111    00000000    11111111    11111111    00000000    00000001 
128
---intcall end -----------------
129
i = key_state ^ ~KEY_PIN      11111111    00000000    11111111    11111111    00000000    00000001 
130
ct0 = ~(ct0 & i)              11111111    00000000    11111111    11111111    00000000    00000001 
131
ct1 = ct0 ^ (ct1 & i)         11111111    00000000    11111111    11111111    00000000    00000001 
132
i &= ct0 & ct1                11111111    00000000    11111111    11111111    00000000    00000001 
133
key_state ^= i                11111111    00000000    11111111    11111111    00000000    00000001 
134
key_press |= key_state & i    11111111    00000000    11111111    11111111    00000000    00000001 
135
---intcall end -----------------

Setze fast nur noch Peter D. sein Code ein. Läuft. Und mal Danke an der 
Stelle.

von Walter (Gast)


Lesenswert?

Hallo

Könnte man nicht auch:

#define Key_2 0

#define Key2_g (Key_2<<1)
#define Key5_g (Key_5<<1)

Und dann mit den geänderten defines für Key2 und Key5 weiterarbeiten?

von Martin (Gast)


Lesenswert?

Hallo Paul



Paul schrieb:
> uint8_t i;
>   TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
>   i = PINA & (1<<PINA0 | 1<<PINA5 | 1<<PINA7);
>   i |= (PINB & ((1<<PINB0 | 1<<PINB1)) << 1);

da hast Du u.a. einen Fehler - Du musst dieses shiften mit einer anderen 
Hilfsvariablen machen:

uint8_t i;
uint8_t k;
k = PINA & (1<<PINA0 | 1<<PINA5 | 1<<PINA7);
k|= (PINB & ((1<<PINB0 | 1<<PINB1)) << 1);

TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);

i = key_state ^ ~k;   /* Deine neue "Hilfsvariable" */

ALL_KEYS wird eh' nur im main() verwendet - das kann man auf die 
einzelnen Ports aufspalten

von Paul (Gast)


Lesenswert?

Hallo Martin
habe deinen Code eingegeben. Leider wird dabei die Taste 2 (KEY2-PB0) 
vollkommen vergessen. Egal ob ich KEY2 verwende, es funktioniert nur 
Taste 1.
Kann es sein das nur i-->k sonst das selbe ist?

von Paul (Gast)


Lesenswert?

Hallo PIC
da hast du dir ja richtig Arbeit gemacht

neuer PIC Freund schrieb im Beitrag #6033894:
> i = key_state ^ ~KEY_PIN      11111111    00000000    11111111
> 11111111    00000000    00000001

Wenn ich bisher richtig verstanden habe ist i das Abbild der Taster die 
Betätigt werden. Bei KEY_PIN unterscheidest du nur 11111111 oder 
11111110. Benutzt du in diesem Fall nur 1 Taster?
Bisher hat der Code von Peter wunderbar funktioniert, leider bisher ...

von Peter D. (peda)


Lesenswert?

Martin schrieb:
> da hast Du u.a. einen Fehler - Du musst dieses shiften mit einer anderen
> Hilfsvariablen machen:

Warum denn?
k wird nach der Zuweisung zu i nie wieder benötigt, daher kannst Du auch 
gleich i nehmen.
Der Compiler merkt das eh, also wird er exakt den gleichen Code 
erzeugen.

von Paul (Gast)


Lesenswert?

Hallo Peter
komme leider überhaupt nicht weiter. Versuche deinen Code mit Anleitung 
zu verstehen. Ist einfach eine Nummer zu gross für mich. Habe auch 
versucht den ersten Teilen zu folgen. Wird nichts.

Peter D. schrieb:
> Das ist jetzt keine Raketenwissenschaft, nur ein Bit überlappt sich.
> In der ISR die 5 Bits in ein Byte einsammeln:  uint8_t i = PINA &
> (1<<PA0 | 1<<PA5 | 1<<PA7);
>   i |= (PINB & ((1<<PB0 | 1<<PB1)) << 1;

Wie kann es sein, wenn ich in der ISR die 5 Bits in einem Byte einsammle 
ein Taster vollkommen ignoriert wird?

von Martin (Gast)


Lesenswert?

Hallo Peter D.

Es ist richtig, dass die Hilfsvariable k nicht zwingend nötig ist, aber 
so eine " Entzerrung " des Codes ist häufig hilfreich.

Das entscheidende ist aber, dass Paul die Zeile
" i = key_state ^ ~ k"
NICHT in seinem Code hatte - oder ist diese Zeile obsolet??

von Martin (Gast)


Lesenswert?

Hallo Paul

Wenn möglich, lege die 5 Taster auf EINEN Port, dann dürfte es 
wesentlich leichter sein, die SW zum laufen zu bringen

von Joachim B. (jar)


Lesenswert?

Martin schrieb:
> Wenn möglich, lege die 5 Taster auf EINEN Port, dann dürfte es
> wesentlich leichter sein, die SW zum laufen zu bringen

und wenn es nicht möglich die Tasten auf einen Port zu legen so kann man 
alle Port Bits in ein Byte shiften wie gezeigt.

Wer es selber durchdenkt findet die Lösung auch ohne die ganze 
Entprellroutine zu verstehen, wer lernen will macht dort weiter!

Die KEY Abfrage muss ja nicht zwingend die Bits an PA und PB abbilden, 
die Bits an PA und PB werden gelesen in ein Hilfsbyte geschoben und dort 
werden die Key Bits abgefragt, entprellt,

"VÖLLIG LOSGELÖST VON DEN PORTS" .........

: Bearbeitet durch User
von Martin (Gast)


Lesenswert?

Hallo Joachim B.

Alles schön und gut was Du da schreibst, wenn es aber dem TO 
offensichtlich nicht weiter hilft und es eine bessere Lösung durch 
verlegen der Taster auf einen Port gibt - warum nicht diesen Weg gehen 
als an einer nicht funktionierenden SW zu verzweifeln?

Oder kannst Du ihm eine copy&Paste Lösung präsentieren??

von Theor (Gast)


Lesenswert?

Naja.

Das Auffällige ist, dass die Lösung, ausgehend von Peters Vorschlag hier 
Beitrag "Re: Taster Entprellung am Attiny 841 und Auswertung" eigentlich nur noch 
minimale Transferleistung erfordert.
Dazu ist ihm auch noch die Bedeutung einer "Zuordnung" (von Martin als 
"Mapping" in die Diskussion eingeführt, aber auch und sogar als 
Zuordnung paraphrasiert) ziemlich ausführlich und mehrfach erklärt und 
sogar das Ergebnis mitgeteilt worden.

Man kann darüber streiten, was eine "minimale" Transferleistung ist, 
aber wir sind uns vermutlich ziemlich einig, dass es lediglich darum 
geht ein Bit, durch eine Schiebeoperation und eine logische Verknüpfung 
hindurch zu verfolgen und sein resultierende Position auszumauchen.

Auch das ist ihm von Walter (wenn ich nicht irre), nach einigen 
Schleifen, mehr oder weniger auf dem Silbertablett serviert worden.

Wie schon von jemandem erwähnt, ist ein vollständiges Verständnis dieser 
vertikalen Zählergeschichte für die Problemlösung eigentlich nicht 
notwendig. Man muss "lediglich" (auch das ist diskutabel) abgrenzen 
können, wo eigentlich der Test auf eine bestimmte Taste stattfindet, und 
welche Variablen da verglichen werden. Man muss eigentlich nur eine Idee 
von Datenfluss haben und davon ein mentales Bild entwerfen können.

Nicht genug damit, hat sich neuer Pic-Freund die Mühe gemacht, jeden 
einzelnen Schritt tabellarisch auszuführen und hinzuschreiben. (Aus dem 
alten AVR-Freaks-Thread kopiert? Egal.)

Aber trotz dieser mehrfachen Versuche, Paul Denkanstöße zu geben, 
unternimmt er offenbar keine eigenen Versuche, geht nicht das Risiko von 
Fehlern ein, sondern will jeden einzelnen Schritt, ob Veränderung im 
Code oder Schlussfolgerung, von uns bestätigt haben. Es scheint mir, wie 
schon erwähnt, auch so, als wenn er von der Sache insgesamt keine 
umfassendere Vorstellung hat. Es geht immer um triviale Details, in 
denen er sich verliert, weil er nichts hat, in das er sie einordnen 
könnte.

Es wird wohl nichts weiter übrig bleiben als entweder den Code für ihn 
zu schreiben oder, in Anbetracht der Tatsache, dass er ein großes, aus 
mehreren Einzelprojekten bestehendes Vorhaben realisieren will, mit dem 
wir dann die nächsten Monate in ähnlicher Weise beschäftigt werden, (wer 
hier will das?) eine Grenze ziehen und sagen:
OK. Wir helfen Dir hier, Dir selbst zu helfen. Aber wenn Du keine 
Anstrengungen unternimmst, oder einfach nicht fähig bist, solche 
Leistungen zu vollbringen, dann ist hier Schluss.

In gewisser Weise handelt es sich vielleicht darum, dass Paul zuviel auf 
einmal will und gewisse frühere Schritte (Bitmanipulationen etc.) nicht 
oder zuwenig geübt hat. Da er nicht von unten aufbaut, steht er in einem 
Wust von Einzelheiten, die sich nicht zusammenfügen.

Auffällig ist auch, dass er nie irgendeinen Ansatz von Analyse vorträgt. 
Es geht nur immer nicht. Warum, oder was jedenfalls eine Ursache sein 
könnte , davon hat er nicht die geringste Vorstellung - oder er 
äussert sie jedenfalls nicht.

Wie siehst Du das, Paul? Könnte da was dran sein?

Vermutlich hättest Du gerne, dass man Dir den Code fertig hinschreibt. 
Aber hast Du Verständnis dafür, dass man erwartet, dass Du Dir selbst 
hilfst? Bist Du bereit, diese Anstrengung auf Dich zu nehmen? Willst Du 
lernen? Richtig hart lernen und das die ganze Zeit, während Du an Deinem 
Projekt arbeitest?

von Karl M. (Gast)


Lesenswert?

Theor schrieb:
> Naja.
>
> Das Auffällige ist, dass die Lösung, ausgehend von Peters Vorschlag hier
> Beitrag "Re: Taster Entprellung am Attiny 841 und Auswertung" eigentlich
> nur noch  minimale Transferleistung erfordert.

Grosses Lob für die Zusammenfassung. Ja wirklich.
Ich denke alle Anregungen nun auf dem Tisch, jetzt braucht es nur noch 
Zeit, dass Paul sie verarbeitet.

Die sollten wir ihm nun geben und diesen Thread schließen.

von Peter D. (peda)


Lesenswert?

Martin schrieb:
> Das entscheidende ist aber, dass Paul die Zeile
> " i = key_state ^ ~ k"
> NICHT in seinem Code hatte - oder ist diese Zeile obsolet??

Da hast Du natürlich recht, ohne diese Zeile ist der Code Nonsens.
Meine Zeilen sollten nur das Einlesen von KEY_PIN verdeutlichen und 
nicht die weitere Verarbeitung ersetzen.

Ich bin mal gespannt, wie er den weitaus komplizierteren Brocken 
bewältigt, ein zuverlässiges I2C-Protokoll zu entwickeln.

von Paul (Gast)


Lesenswert?

Hallo Peter
das mit dem I2C Protokoll ist bereits gelöst. Habe verschiedene Teile 
mit dem Bus und einem Atmega 128 verbunden. Auch die Verbindung zwischen 
einem Ati841 und dem Atmega128 läuft bereits in beide Richtungen. Auch 
der AC und ADC vom Ati841 laufen sehr gut.
Fehlt einfach nur die Tastenentprellung. Mal heute abend schauen wie ich 
es machen kann.
Paul

von Paul (Gast)


Lesenswert?

Schliesst diesen Thread bitte nicht zu schnell. Gibt sicher noch Problem 
mit diesem Code.

von Martin (Gast)


Lesenswert?

Paul schrieb:
> Hallo Peter
> Habe verschiedene Teile
> mit dem Bus und einem Atmega 128 verbunden. Auch die Verbindung zwischen
> einem Ati841 und dem Atmega128 läuft bereits in beide Richtungen. Auch
> der AC und ADC vom Ati841 laufen sehr gut.
> Paul

Hast Du nicht erst vor kurzem noch mit dem ADC / Comparator gekämpft 
weil Du eine falsche Pin Belegung hattest? Und das funktioniert jetzt??

Und hast Du mal Taster vom Attiny841 eingelesen, per Bus an den Master 
geschickt und dieser ein Signal an den Attiny geschickt, damit dieser 
eine LED ansteuert wenn der Taster betätigt wird?
Dafür (1 Taste einlesen) musste aber das Entprellen ja schon machen 
können

Martib

von Thomas S. (thschl)


Lesenswert?

Hallo Paul,
habe jetzt nicht alles durchgelesen aber wenn du 2 Ports verwendest, 
wäre es für dich sinnvoll alles auch 2fach zu programmieren

also
1
#define KEY_1_A       0              // PA 0 - Taster 1
2
#define KEY_3_A       7              // PA 3 - Taster 3
3
#define KEY_4_A       5              // PA 5 - Taster 4
4
5
#define KEY_2_B       0               // PB 0 - Taster 2
6
#define KEY_5_B       1               // PB 1 - Taster 5
7
8
#define ALL_KEYS_A  -- fuer Port A 
9
#define ALL_KEYS_B  -- fuer Port B
10
11
#define REPEAT_MASK_A  -- fuer Port A 
12
#define REPEAT_MASK_B  -- fuer Port B

dann entsprechend zuweisen, damit weisst du was wo benutzt wird

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

Martin schrieb:
> Oder kannst Du ihm eine copy&Paste Lösung präsentieren??

könnte ich, aber

Theor schrieb:
> ausgehend von Peters Vorschlag hier
> Beitrag "Re: Taster Entprellung am Attiny 841 und Auswertung" eigentlich
> nur noch
> minimale Transferleistung erfordert.

wenn Paul sich einfach mal klarmacht das er Tasten an 2 Ports 
angeschlossen abfragt

#define KEY_portA_1       0    // PA 0 - Taster 1
#define KEY_portA_3       7    // PA 3 - Taster 3
#define KEY_portA_4       5    // PA 5 - Taster 4

#define KEY_portB_2       0    // PB 0 - Taster 2
#define KEY_portB_5       1    // PB 1 - Taster 5

dabei 2 Bits an A und B die selbe Bitnummer haben
#define KEY_1       0          // PA 0 - Taster 1
#define KEY_2       0          // PB 0 - Taster 2

auch sehr unglücklich sind die verschiedensten Nummern BIT und TASTE, 
warum tut man sich das an?

Portabfrage
#define KEY_LINKS_PORTA   0    // PA 0 - Taster links
#define KEY_RECHTS_PORTA  3    // PA 3 - Taster rechts
#define KEY_ENTER_PORTA   5    // PA 5 - Taster enter

#define KEY_DOWN_PORTB    0    // PB 0 - Taster down
#define KEY_UP_PORTB      1    // PB 1 - Taster up

schon sind diese verwirrenden Nummern weg!

er diese einfach in der KEY Abfrage umbenennt

#define KEY_read_links    0  // wie Port Hilfsbyte Bit 0 - Taster links
#define KEY_read_rechts   3  // wie Port Hilfsbyte Bit 3 - Taster rechts
#define KEY_read_rechts   5  // wie Port Hilfsbyte Bit 5 - Taster enter

und in der KEY Abarbeitung eigentlich andere Bits nutzt durch shiften

#define KEY_read_down    1 // nach shiften Hilfsbyte Bit 1-Taster down
#define KEY_read_up      2 // nach shiften Hilfsbyte Bit 2-Taster up

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

Das stimmt, habe bis vor kurzem mit dem ADC und AC gekämpft. Der 
entscheidende Hinweis kam von Peter. Danach lief alles ohne Flackern. 
Die Pin Belegung war soweit korrekt, hatte in einem Register etwas nicht 
eingeschaltet (Sorry, kann gerade nicht in das Programm schauen)mit dem 
negativ einschalten.
Ja, ich habe ein Signal vom Master zum Slave geschickt und eine LED 
angesteuert und einen Taster Zustand ausgelesen. Habe nur die einfache 
Version gewählt und es hat funktioniert.
Die Tasterentprellung von Peter habe ich bereits in anderen Programmen 
verwendet und dabei so ziemlich alle Version gemacht die das Programm so 
macht.
Hatte aber noch nie das die Taster auf 2 Ports verteilt sind und sich 2 
Taster stören.

von Paul (Gast)


Lesenswert?

Habe nichts gegen lernen. Habe mir schon viel erarbeitet und angewendet. 
Dazu zählen auch teilweise recht komplizierte Teile. Manche Sachen habe 
ich allein begriffen, bei manchen Teilen habe ich um Rat gefragt. 
Teilweise sind es einfach Kleinigkeiten, manchmal sind es einfach Sachen 
die ich nicht begriffen habe. Deswegen werde ich auf jeden Fall 
weitermachen. Manche Projekte sind aus mehreren Sachen zusammengebaut 
und funktionieren super. Ist alles vertreten.
LG Paul

von Martin (Gast)


Lesenswert?

Hallo Joachim B.

Großes Lob und "thumbs up" :-)

Du hast recht - mit Deinem letzten Beitrag sollte Paul eigentlich (!!) 
in der Lage sein, dieses Entprellen für 2 Ports hin zu bekommen.

Wenn aber jemand nur die Grundrechnungsarten beherrscht darf er sich 
nicht wundern, wenn er bei höherer Mathematik scheitert - es sei denn, 
er ist Willens, sich weiter zu bilden ;-)

Beitrag #6036014 wurde vom Autor gelöscht.
von Egonwalter M. (heiner1234)


Angehängte Dateien:

Lesenswert?

Hallo Paul

Ich hab' mal versucht, ein (hoffenlich!) funktionsfähiges Programm zu
erstellen aus Deinen und den anderen Beiträgen.

Testen kann ich's nicht da keine HW vorhanden, ich konnte es nicht mal
compilieren, da mein AVRSTudio 418 keinen Attiny841 kennt...

Hilfe zur Selbsthilfe ist gut, aber manchmal hilft es auch ein
bestehendes Programm "auseinanderzunehmen", um es zu verstehen.
Und wenn man sieht, dass jemand wirklich nicht weiterkommt ....

Würde mich freuen, wenn's funktioniert.

von Paul (Gast)


Lesenswert?

Egonwalter M. schrieb:
> Hilfe zur Selbsthilfe ist gut, aber manchmal hilft es auch ein
> bestehendes Programm "auseinanderzunehmen", um es zu verstehen.
> Und wenn man sieht, dass jemand wirklich nicht weiterkommt ....

Vielen Dank an Egonwalter M.
habe dein Programm gerade gesehen. Bin dabei es auf den Attiny zu 
bringen.
Deine Meinung kann ich vollkommen unterstützen. Wenn ein Programm ohne 
Probleme läuft hat man einen Code ohne Fehler. Dann kann man damit 
beginnen ihn auseinder zu nehmen und genau schauen wie andere es machen. 
Im ersten überblick muss ich wirlich sagen das ich staune. Es waren 
bereits Hinweise und gute Ansätze dabei, teilweise fast fertig. Hatte 
auch angefangen etwas damit zu machen. Leider habe ich auch ansatzweise 
nicht soweit gedacht.
Egal ob mich manche Leute blöd finden, bedanke ich mich trotzdem für die 
Hilfe und Geduld.
LG Paul

von Paul (Gast)


Lesenswert?

Habe den Code jetzt auf dem Ati841 drauf. Ein paar kleine Sachen waren 
dran, habe alles gefunden und korregiert
1
while(1) 
2
      {                      // Programmschleife while
3
      //if(get_key_press(1<<KEY_DOWN_PORTB))  // Taster 2
4
       if(get_key_press(1<<KEY_LINKS_PORTA))  // Taster 1
5
       //if(get_key_press(1<<KEY_RECHTS_PORTA))  // Taster 3
6
       //if(get_key_press(1<<KEY_ENTER_PORTA))  // Taster 4
7
       //if(get_key_press(1<<KEY_UP_PORTB))  // Taster 5
8
        
9
        {  // nur Taste press
10
        /*  if(get_key_press(1<<(KEY_read_down >>1))) {   falls obige Zeile nicht fkt!! */    
11
        PORTB &= ~(1<<PINB2);        // 3+4,4+5// LED an
12
        }
13
      
14
      if(get_key_press(1<<KEY_DOWN_PORTB))  // Taster 2
15
      //if(get_key_press(1<<KEY_LINKS_PORTA))  // Taster 1
16
      //if(get_key_press(1<<KEY_RECHTS_PORTA))  // Taster 3
17
      //if(get_key_press(1<<KEY_ENTER_PORTA))  // Taster 4
18
      //if(get_key_press(1<<KEY_UP_PORTB))  // Taster 5
19
    
20
        {                    // nur Taste press  
21
        PORTB |= (1<<PINB2);        // LED aus
22
        }
23
      }                    // Ende while
habe zum testen die verschiedenen Kombinationen eingegeben.
Alles mit Taster 2 und/oder zu tun hat geht nicht. Bei der oberen 
Kombination kann ich mit Taster 1 ein und wieder ausschalten, wobei 
Taster 2 keine Funktion hat.

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

Lass mal die ganze Entprellsache weg und versuche mal das Programm ohne 
zu testen - also:
-  nur mit jeweils einem Taster (Taster 1 bis Taster 5) eine LED an/aus 
zuschalten und check mal, ob da Taster 2 fkt.

Funktioniert Dein Taster 2 überhaupt?

Du kannst ja - ohne Entprellroutine - mal testen: mit Taster1 eine LED 
ein, mit Taster2 diese wieder aus.

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

Habe mir schnell ein kleines Programm geschrieben mit dem ich die 
Ausgänge testen kann. Damit kann ich die Tasten schalte und die LED 
ein/aus. Auch die Taste 2 funktioniert damit ohne Probleme

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

Also - Taste 2 fkt problemlos, wenn die Entprellroutine NICHT 
implementiert ist ....

hm ...

aber Taste 5 fkt wiederum problemlos, wenn die Entprellroutine 
implementiert ist ... beide Tasten liegen ja auf PORTB und beide Tasten 
werden in der Entprellroutine um 1 nach links geschoben und zur 
Variablen k  addiert ...

hm ...

muss mal in mich gehen ...

probier mal mit:
KEY_read_down anstatt KEY_DOWN_PORTB in der main:
...
while(1) {            // Programmschleife while
    if(get_key_press(1<<KEY_read_down)) {

denn in der Entprellroutine verwenden wir ja:
REPEAT_MASK 
(1<<KEY_read_links|1<<KEY_read_rechts|1<<KEY_read_enter|1<<KEY_read_down 
|1<<KEY_read_up)

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

Habe ich geändert. Jetzt reagiert Taste 5 ein/aus

von Egonwalter M. (heiner1234)


Lesenswert?

Taste 5 hat aber doch vorher schon reagiert...

Taste 2 reagiert also immer noch nicht?

Versteh' ich nicht ...

in der Variablen k (TIMER ISR) ist die Info, dass PINB0 und PINB1 um 1 
nach links geschoben sind:
BIT 0 = PA 0 - Taster links     Taster 1
BIT 1 = PB 0 - Taster down    Taster 2
BIT 2 = PB 1 - Taster up    Taster 5
BIT 5 = PA 5 - Taster enter    Taster 4
BIT 7 = PA 7 - Taster rechts    Taster 3

dies findet sich auch in REPEAT_MASK wieder - also "rechnet" die TIMER 
ISR mit den geshifteten Werten ...
d.h  key_state und key_press arbeitet auch mit den geshifteten Werten 
...

die "Auswertefunktionen" wie z.B get_key_press arbeitet auch mit den 
geshifteten Werten ...wenn ich dann bei diesen Funktionen als Parameter 
KEY_read_down angebe, müßte eigentlich Taster 2 derjenige sein, der die 
LED anmacht ....

: Bearbeitet durch User
von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

Paul schrieb:
> Habe den Code jetzt auf dem Ati841 drauf. Ein paar kleine Sachen
> waren dran, habe alles gefunden und korregiert

was hast Du korrigiert?

zur Abfrage in der main():

BIT 0 = PA 0 - Taster links     Taster 1  KEY_LINKS_PORTA
BIT 1 = PB 0 - Taster down      Taster 2  KEY_read_down
BIT 2 = PB 1 - Taster up        Taster 5  KEY_read_up
BIT 5 = PA 5 - Taster enter     Taster 4  KEY_ENTER_PORTA
BIT 7 = PA 7 - Taster rechts    Taster 3  KEY_RECHTS_PORTA

: Bearbeitet durch User
von Heiner1234 (Gast)


Lesenswert?

Hallo Paul

In der Main musst du Taste 2 und Taste 5 wie bei der ISR behandeln

Für Taste 2 gilt dann:
If(get_key_press((1<<PB0)<<1)

PB0 ist ja Taster2, wird eingelesen und dann auch um 1 geschoben
Gilt für PB1 genauso

Müsste gehen!!

von Paul (Gast)


Lesenswert?

Guten Tag,
danke für eure Antworten, komme heute abend erst wieder an meinen 
Rechner. Teste es dann sofort

von Paul (Gast)


Lesenswert?

Das sieht jetzt so aus:
1
while(1) 
2
      {                      // Programmschleife while
3
      //if(get_key_press(1<<KEY_DOWN_PORTB))  // Taster 2
4
      if(get_key_press(1<<KEY_read_down))  // Taster 2
5
      //if(get_key_press(1<<KEY_LINKS_PORTA))  // Taster 1
6
       //if(get_key_press(1<<KEY_RECHTS_PORTA))  // Taster 3
7
       //if(get_key_press(1<<KEY_ENTER_PORTA))  // Taster 4
8
       //if(get_key_press(1<<KEY_UP_PORTB))  // Taster 5
9
        
10
        {  // nur Taste press
11
        /*  if(get_key_press(1<<(KEY_read_down >>1))) {   falls obige Zeile nicht fkt!! */    
12
        PORTB &= ~(1<<PINB2);        // 3+4,4+5// LED an
13
        }
14
      
15
      //if(get_key_press(1<<KEY_DOWN_PORTB))  // Taster 2
16
      if(get_key_press(1<<KEY_read_down))  // Taster 2
17
      //if(get_key_press(1<<KEY_LINKS_PORTA))  // Taster 1
18
      //if(get_key_press(1<<KEY_RECHTS_PORTA))  // Taster 3
19
      //if(get_key_press(1<<KEY_ENTER_PORTA))  // Taster 4
20
      //if(get_key_press(1<<KEY_UP_PORTB))  // Taster 5
21
    
22
        {                    // nur Taste press  
23
        PORTB |= (1<<PINB2);        // LED aus
24
        }
25
      }                    // Ende while
Habe die verschiedenen Kombinationen auskommentiert. Werde das nächste 
eintragen

von Paul (Gast)


Lesenswert?

Habe noch mal alle Tasten ausprobiert und Ergebnisse dahinter.
1
//if(get_key_press(1<<KEY_DOWN_PORTB))    // Taster 2 --> reagiert Taster 1
2
//if(get_key_press((1<<KEY_read_down)<<1))  // keine Funktion
3
//if(get_key_press(1<<(KEY_read_down >>1)))  // Taste 2 --> Taste 1 reagiert
4
//if(get_key_press(1<<KEY_LINKS_PORTA))    // Taster 1 funktioniert
5
//if(get_key_press(1<<KEY_RECHTS_PORTA))  // Taster 3 funktioniert
6
//if(get_key_press(1<<KEY_ENTER_PORTA))    // Taster 4 funktioniert
7
//if(get_key_press(1<<KEY_UP_PORTB))    // Taster 5 funktioniert

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

also - Taste 2 funktioniert NICHT, auch wenn in main() steht

while(1) {            // Programmschleife while
    if(get_key_press(1<<KEY_read_down)) {

Paul schrieb:
> Habe den Code jetzt auf dem Ati841 drauf. Ein paar kleine Sachen waren
> dran, habe alles gefunden und korregiert

Was hast Du geändert?

Eigentlich dürfte das nicht gehen wg dem shiften:
if(get_key_press(1<<KEY_UP_PORTB))    // Taster 5 funktioniert

Hast Du auch mal probiert:
If(get_key_press((1<<PB0))

oder

If(get_key_press((1<<PB0)<<1)

PB0 ist ja Taster 2

NACHTRAG

welchen Taster musst Du betätigen wenn in main steht:
while(1) {            // Programmschleife while
    if(get_key_press(1<<KEY_read_up)) {

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

Es waren nur wenige Fehler zu Anfang drin, vergessenes Semikolon, 
Klammer zu viel oder wenig, halt Kleinigkeiten.
Habe jetzt die beiden eingegeben, geht leider auch nicht.
Erste Version keine Funktion
zweite version - Taste 1 reagiert

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

while(1){

      if(get_key_press(1<<KEY_read_down))PORTB |= (1<<PINB2);   // 
Taster 2

      if(get_key_press(1<<KEY_read_up))PORTB &=~(1<<PINB2);  // Taster 5

      }

funktioniert das?

von Paul (Gast)


Lesenswert?

Mit dem Nachtrag funktioniert keine Taste

von Paul (Gast)


Lesenswert?

LED ist sofort eingeschaltet, keine Taste reagiert

von Egonwalter M. (heiner1234)


Lesenswert?

Dann ist die if-Bedingung
if(get_key_press(1<<KEY_read_down))PORTB |= (1<<PINB2);

immer erfüllt ...

von Paul (Gast)


Lesenswert?

Egonwalter M. schrieb:
> if(get_key_press(1<<KEY_read_down))PORTB |= (1<<PINB2);

Muss dass nicht so aussehen:

if(get_key_press(1<<KEY_read_down))
PORTB |= (1<<PINB2);

von Egonwalter M. (heiner1234)


Lesenswert?

Paul schrieb:
> Egonwalter M. schrieb:
>> if(get_key_press(1<<KEY_read_down))PORTB |= (1<<PINB2);
>
> Muss dass nicht so aussehen:
>
> if(get_key_press(1<<KEY_read_down))
> PORTB |= (1<<PINB2);

das ist beides das selbe

Kannst Du nochmal testen:

while(1){
if(get_key_press(1<<KEY_read_down))PORTB ^= (1<<PINB2); /* toggeln
}

=> nur Taster 2

und wenn's nicht fkt (anzunehmen ist es ja) das gleiche mit
while(1){
if(get_key_press(1<<KEY_read_up))PORTB ^= (1<<PINB2); /* toggeln
}


=> also 2 verschiedene Tests

von Egonwalter M. (heiner1234)


Lesenswert?

If(get_key_press((1<<PINB0)<<1) - hast Du da wirklich Taste 1 betätigt?

Da wird doch 'ne 1 in PB0 geschrieben und dann um 1 nach links geshiftet 
- es müsste entweder Taste2 oder Taste 5 sein.

Taste 1 ist doch auf PORTA PA0 verkabelt - wie kann es da Taste 1 sein 
bei If(get_key_press((1<<PINB0)<<1) ...

: Bearbeitet durch User
von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

Ich bin mir nicht sicher, ob das shiften von PORTB in der ISR korrekt 
ist - teste mal mit

/*  k |= (PINB & ((1<<PINB0 | 1<<PINB1)) << 1);*/
  k |= PINB & ((1<<PINB0 | 1<<PINB1) << 1);

von neuer PIC Freund (Gast)


Lesenswert?

1
unsigned char fkt1(void)
2
{
3
        unsigned char k = 0;
4
        k |= PINB & ((1<<PINB0 | 1<<PINB1) << 1);
5
   0:   83 b1           in      r24, 0x03       ; 3
6
        return k;
7
}
8
   2:   86 70           andi    r24, 0x06       ; 6
9
   4:   08 95           ret

Alternativ einfach mal den compiler explorer nutzen. Dann braucht man 
auch nicht rätseln.

von Peter D. (peda)


Lesenswert?

Paul schrieb:
> Alles mit Taster 2 und/oder zu tun hat geht nicht.

Dieses planlose Rumprobieren bringt doch nichts.

Ich möchte nochmal eindringlich dazu raten, sich erstmal mit den 
Bitoperationen zu beschäftigen.
Beitrag "Re: Taster Entprellung am Attiny 841 und Auswertung"

Wer den Taschenrechner nicht mag, kann das auch im AVR-Simulator 
ausprobieren.
Man kann sich auch über den Debugger oder die UART die Variablen 
ausgeben lassen. Dann sieht man, was beim Drücken geschieht.

Wenn das I2C-Protokoll gut ist, ginge auch Debuggen über I2C.
Ich vermute aber, daß das I2C-Protokoll nur sehr rudimentär ist und 
keine Fehlererkennung, Störungsbehandlung und Retry besitzt. D.h. es wir 
gnadenlos abstürzen, wenn die Verbindung kurz unterbrochen wird oder bei 
Kurzschluß auf den Datenleitungen (Hot-Plugging).

: Bearbeitet durch User
von Egonwalter M. (heiner1234)


Angehängte Dateien:

Lesenswert?

Hallo Paul

zu der Bitschubserei - die habe ich nun in der ISR "aufgedröselt", teste 
damit mal.

@PETER D.

Dein Beitrag

Peter D. schrieb:
> Paul schrieb:
>> Belegung der Hardware:
>>
>> // PA0 --> T1
>> // PB0 --> T2
>> // PA7 --> T3
>> // PA5 --> T4
>> // PB1 --> T5
>
> Das ist jetzt keine Raketenwissenschaft, nur ein Bit überlappt sich.
> In der ISR die 5 Bits in ein Byte einsammeln:  uint8_t i = PINA &
> (1<<PA0 | 1<<PA5 | 1<<PA7);
>   i |= (PINB & ((1<<PB0 | 1<<PB1)) << 1;
> // ...

ist nicht so ganz korrekt - siehe Klammersetzung
Und ob der I2C funktioniert, weißt Du doch auch nicht. Paul hat ja 
geschrieben, dass er schon Daten zwischen Atmega und Attiny ausgetauscht 
hat.
Und als "planloses Rumprobieren" würde ich es nicht bezeichnen.

@ neuer PIC Freund(Gast)
Schöner Beitrag, wenn man sich damit (Register/Assembler) auskennt. Ich 
jedenfalls nicht - somit für mich ... nicht so hilfreich.

Paul - lass Dich nicht unterkriegen. Das kriegen wir schon hin.

Jetzt müßte auch das einlesen von Taster 2 funktionieren mit:
while(1){
if(get_key_press(1<<KEY_read_down)) {

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Egonwalter M. schrieb:
> ist nicht so ganz korrekt - siehe Klammersetzung

Jo mei, ne Klammer zuviel:
1
  uint8_t i = PINA & (1<<PA0 | 1<<PA5 | 1<<PA7);
2
  i |= (PINB & (1<<PB0 | 1<<PB1)) << 1;
3
  i = key_state ^ ~i;
4
  ct0 = ~(ct0 & i);
5
// usw.

Das sollte aber der Compiler angemeckert haben.
Man sieht auch leicht, wo sie zuviel ist. Einen Ausdruck doppelt zu 
klammern hat keinen Effekt.

: Bearbeitet durch User
von Egonwalter M. (heiner1234)


Angehängte Dateien:

Lesenswert?

Hallo Paul

Habe doch wieder (!) einen Fehler in der ISR

falsch:
i = PINB &(1 << PINB0)|(1 << PINB1);      /* einlesen PORTB unveraendert 
*/


korrekt:

i = PINB &(1 << PINB0|1 << PINB1);      /* einlesen PORTB unveraendert 
*/

=> Klammer ZUVIEL!!

Sorry!

von Paul (Gast)


Lesenswert?

Hallo
habe deine letzte ISR eingebaut. Nach den ersten Tset funktioniert es. 
Muss aber noch einige Kombiantinen testen ob alles miteinader 
funktioniert.

von Paul (Gast)


Lesenswert?

Habe wahrscheinlch alle Tasten und Kombinationen getestet. Eine kleine 
Sache war noch drin, ansonsten funktioniert alles super.
Danke für deine Hilfe. Werde den Code aufräumen und kommentieren und 
dann stelle ich alles ins Netz zur Hilfe auch für andere.
Dann werde ich mich dabei machen die Sache mit den Bits zu verstehen.
Nochmal danke für eure Hilfe und Geduld

LG Paul

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

Paul schrieb:
> Habe wahrscheinlch alle Tasten und Kombinationen getestet. Eine kleine
> Sache war noch drin, ansonsten funktioniert alles super.
> Danke für deine Hilfe. Werde den Code aufräumen und kommentieren und
> dann stelle ich alles ins Netz zur Hilfe auch für andere.

Welche kleine Sache war noch drin?
Code aufräumen & kommentieren  - ich hoffe, Du weißt, was Du da machst 
...
Code in's Netz stellen - ich hoffe u.a. hier in diesem Forum unter 
diesem Thread!!!

Und wenn Du den Code in's Netz bzw HIER einstellst - da poste auch 
gleich Deine I2C-Kommunikation hier, bitte!

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

Hallo
Es hatte sich ein < eingeschlichen, warum auch immer. Egal, gefunden und 
korrigiert. Keine Angst, werde nichts verändern was relevant ist. Es 
geht um die Lesbarkeit, um die Zuordnung der Klammern und nicht 
benötigter Coder der Auskommentiert ist. Werde auch die notwendigen 
Kommentare nicht vergessen. Im Moment ist der Code der Taster und vom 
I2C Bus Anbindung noch getrennt. Da ich auch in anderen Projekten beide 
Codes verwende dürfte es kein Problem sein beides zusammen in eine 
Programm zu bringen. Es fehlt dann aber noch die Eingabe der I2C 
Adressen durch die DIP und die Umschaltung dazu.
Selbstverständlich werde ich den Code hier einstellen. Mit der Lösung 
die wir gefunden haben möchte ich anderen weiterhelfen, da der Ati 841 
nicht so verbreitet ist.
LG Paul

von Joachim B. (jar)


Lesenswert?

Egonwalter M. schrieb:

> falsch:
> i = PINB &(1 << PINB0)|(1 << PINB1);      /* einlesen PORTB unveraendert
> */

stimmt

Egonwalter M. schrieb:
> korrekt:
>
> i = PINB &(1 << PINB0|1 << PINB1);      /* einlesen PORTB unveraendert
> */

mag ja korrekt sein, aber schlecht lesbar
> i = PINB &( (1 << PINB0) | (1 << PINB1) );

ich finde das lesbarer trotz 2 Klammern mehr,
Die Bit-Schieberei vor dem Verodern ist besser zu erkennen.

von Egonwalter M. (heiner1234)


Lesenswert?

Joachim B. schrieb:
> Egonwalter M. schrieb:
>> korrekt:
>>
>> i = PINB &(1 << PINB0|1 << PINB1);      /* einlesen PORTB unveraendert
>> */
>
> mag ja korrekt sein, aber schlecht lesbar
>> i = PINB &( (1 << PINB0) | (1 << PINB1) );
>
> ich finde das lesbarer trotz 2 Klammern mehr,
> Die Bit-Schieberei vor dem Verodern ist besser zu erkennen.

Das ist wohl Ansichtssache. Entscheidend ist die Funktion, nichts 
anderes.
Die Bitschieberei ist auch ohne der 2ten Klammer erkennbar.
Und wenn, dann müsste man das durchgängig machen - also auch bei den 
#defines.

von Paul (Gast)


Lesenswert?

Wie versprochen der bereinigte Code der Tasten. s sind auch noch die 
aderen Funktionen des Codes von Peter drin aber nicht verwendet.
1
#define F_CPU 8E6                // Angabe Frequenz
2
  #include <avr/io.h>                // Einbindung Datein
3
  #include <avr/interrupt.h>
4
  #include <stdint.h>
5
6
  volatile uint8_t key_state;
7
  volatile uint8_t key_press;
8
  volatile uint8_t key_rpt;
9
10
  #define KEY_DDRA      DDRA            // Datenrichtung A
11
  #define KEY_PORTA     PORTA            // Angabe Port A
12
  #define KEY_PINA      PINA            // Angabe PIN A
13
14
  #define KEY_LINKS_PORTA     0          // PA 0 - Taster links     Taster 1
15
  #define KEY_RECHTS_PORTA    7          // PA 7 - Taster rechts    Taster 3
16
  #define KEY_ENTER_PORTA     5          // PA 5 - Taster enter    Taster 4
17
18
  #define KEY_DDRB      DDRB            // Datenrichtung B
19
  #define KEY_PORTB     PORTB            // Angabe Port B
20
  #define KEY_PINB      PINB            // Angabe PIN B
21
22
  #define KEY_DOWN_PORTB  0            // PB 0 - Taster down    Taster 2
23
  #define KEY_UP_PORTB    1            // PB 1 - Taster up      Taster 5
24
25
  #define KEY_read_links    0            // wie Port Hilfsbyte Bit 0 - Taster links
26
  #define KEY_read_rechts   7            // wie Port Hilfsbyte Bit 7 - Taster rechts
27
  #define KEY_read_enter    5            // wie Port Hilfsbyte Bit 5 - Taster enter
28
29
  #define KEY_read_down    1            // nach shiften Hilfsbyte Bit 1-Taster down
30
  #define KEY_read_up      2            // nach shiften Hilfsbyte Bit 2-Taster up
31
32
  #define ALL_KEYS_PA (1<<KEY_LINKS_PORTA|1<<KEY_RECHTS_PORTA|1<<KEY_ENTER_PORTA)
33
  #define ALL_KEYS_PB (1<<KEY_DOWN_PORTB|1<<KEY_UP_PORTB)
34
35
  #define REPEAT_MASK (1<<KEY_read_links|1<<KEY_read_rechts|1<<KEY_read_enter|1<<KEY_read_down|1<<KEY_read_up)
36
  #define REPEAT_START 50              // after 500ms
37
  #define REPEAT_NEXT 20              // every 200ms
38
39
  ISR (TIMER0_OVF_vect) 
40
    {                        // Timer
41
    static uint8_t ct0,ct1,rpt;
42
    uint8_t i;
43
    uint8_t k;
44
    TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
45
    k = PINA & (1<<PINA0 | 1<<PINA5 | 1<<PINA7);        // einlesen PORTA unveraendert 
46
    i = PINB &(1 << PINB0|1 << PINB1);            // einlesen PORTB unveraendert 
47
    i = i << 1;                        // schiebe das von PORTB eingelesene um 1 nach 
48
    k = i | k;                        // verodern von i (PORTB geschoben) und PORTA 
49
    i = key_state ^ ~k;
50
    ct0=~(ct0&i);
51
    ct1=ct0^(ct1&i);
52
    i&=ct0&ct1;
53
    key_state^=i;
54
    key_press|=key_state&i;
55
    if((key_state & REPEAT_MASK)==0)
56
    rpt=REPEAT_START;
57
    if(--rpt==0) 
58
      {
59
      rpt=REPEAT_NEXT;
60
      key_rpt|=key_state & REPEAT_MASK;
61
      }
62
    }
63
64
  uint8_t get_key_press(uint8_t key_mask) 
65
  {
66
    cli();
67
    key_mask &=key_press;
68
    key_press^=key_mask;
69
    sei();
70
    return key_mask;
71
  }
72
73
  uint8_t get_key_rpt(uint8_t key_mask) 
74
  {
75
    cli();
76
    key_mask &=key_rpt;
77
    key_rpt^=key_mask;
78
    sei();
79
    return key_mask;
80
  }
81
82
  uint8_t get_key_short(uint8_t key_mask) 
83
  {
84
    cli();
85
    return get_key_press(~key_state & key_mask);
86
  }
87
88
  uint8_t get_key_long(uint8_t key_mask) 
89
  {
90
    return get_key_press(get_key_rpt(key_mask));
91
  }
92
93
  void timer_init() 
94
  {
95
    TCCR0B = (1<<CS02)|(1<<CS00);                // Prescaler 1024
96
    TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms
97
    TIMSK0 |= 1<<TOIE0;                    // Interrupt erlauben
98
  }
99
100
  int main(void) 
101
  {                          // Programmschleife main
102
    timer_init();                    // Timer init
103
    PUEA=0b10100001;                  // R auf Taster PORT A
104
    PUEB=0b00000011;                  // R auf Taster PORT B
105
    DDRB=0b00000100;                  // Port B auf Ausgang schalten
106
    PORTB = (1<<PINB2);
107
    KEY_DDRA&=~ALL_KEYS_PA;
108
    KEY_PORTA|=ALL_KEYS_PA;
109
    KEY_DDRB&=~ALL_KEYS_PB;
110
    KEY_PORTB|=ALL_KEYS_PB;
111
      sei();
112
    while(1) 
113
    {                        // Programmschleife while
114
      if(get_key_press(1<<KEY_LINKS_PORTA))      // Taster 1 
115
      // if(get_key_press(1<<KEY_read_down))    // Taster 2
116
      // if(get_key_press(1<<KEY_RECHTS_PORTA))    // Taster 3 
117
      // if(get_key_press(1<<KEY_ENTER_PORTA))    // Taster 4 
118
      // if(get_key_press(1<<KEY_read_up))      // Taster 5     
119
      {  
120
        PORTB &= ~(1<<PINB2);        
121
      }
122
      // if(get_key_press(1<<KEY_LINKS_PORTA))    // Taster 1
123
      if(get_key_press(1<<KEY_read_down))      // Taster 2
124
      //if(get_key_press(1<<KEY_RECHTS_PORTA))    // Taster 3 
125
      // if(get_key_press(1<<KEY_ENTER_PORTA))    // Taster 4 
126
      // if(get_key_press(1<<KEY_read_up))      // Taster 5
127
        {  
128
        PORTB |= (1<<PINB2);        // LED aus
129
      }
130
    }                    // Ende while
131
  }                      // Ende
132
  
133
    // Funktion der Taster            Anordnung der Taster
134
    
135
    // KEY_LINKS_PORTA      Taster 1        T1    
136
    // KEY_read_down      Taster 2    
137
    // KEY_RECHTS_PORTA      Taster 3    T2    T3    T4
138
    // KEY_ENTER_PORTA      Taster 4 
139
    // KEY_read_up        Taster 5        T5

von Paul (Gast)


Lesenswert?

Weiter geht es mit dem Code zum Attiny 841 mit I2C Bus als Slave. Der 
Code ist noch nicht geputzt und einiges zur Probe drin, aber er 
funktioniert.
Falls ihn jemand verwendet bitte die Erfahrung mitteilen.
1
// Slave mit Attiny 841 zum Master mit ATm 1284p
2
3
#include "main.h"      // CPU 16MHz
4
#include <avr/interrupt.h>  // dient zur Behandlung der Interrupts
5
#include <avr/io.h>         // Integer-Definitionen
6
7
#define I2C_SLAVE_ADDRESS       0x52  // Slave Adresse 0x52
8
#define I2C_DATA_INTERRUPT      0x80  // 0x80
9
#define I2C_BUS_COLLISION       0x08  // 0x08
10
#define I2C_ADDRESS_STOP_MATCH  0x40  // 0x40
11
12
volatile uint8_t command;
13
volatile uint8_t tx_buf[2];  // 4
14
volatile uint8_t tx_buff = 11;  // 4
15
volatile uint8_t tx_buf_index = 0;
16
//volatile uint8_t adc_data;
17
//static volatile unsigned short adc_data;
18
//adc_data = 2;
19
20
// Funktionsprototypen
21
//void ADC_init(void);
22
void I2C_init(void);
23
//void Timer0_init(void);
24
25
void I2C_init(void)
26
  {
27
  TWSA = I2C_SLAVE_ADDRESS;          // TWI Adressregister
28
  TWSD = 0xFF;                // Datenregister
29
  TWSCRA = (1<<TWEN)|(1<<TWSHE)|(1<<TWASIE)|(1<<TWSIE)|(1<<TWDIE);      
30
  // Register A, TWEN-Schnittstelle Aktivieren, TWSHE-Haltezeit aktivieren, TWASIE-Adressenunterbrechung aktivieren, 
31
  // TWSIE-Stop Unterbrechung aktivieren, TWDIE-Datenunterbrechung aktivieren 
32
    TWSCRB = (1<<TWAA)|(1<<TWCMD1)|(0<<TWCMD0);  // Register B, TWI Bestätigungsaktion, TWI Befehl
33
  sei();      // Interrups einschalten
34
  }
35
36
ISR( TWI_SLAVE_vect )
37
  {
38
    uint8_t status = TWSSRA & 0xC0;      // Register A
39
  if (status & I2C_DATA_INTERRUPT)
40
  // Daten wurden vom Master empfangen oder werden angefordert
41
    {
42
      if (TWSSRA & (1 << TWDIR))          // Master fordert Daten vom Slave an
43
      {
44
      //////if(tx_buf_index >= sizeof(tx_buf))
45
      ////  {
46
      /////  tx_buf_index=0;
47
      /////  }
48
      //TWSD = tx_buf[1];
49
      /////TWSD = tx_buf[tx_buf_index];
50
      TWSD = tx_buff;
51
      //tx_buf_index++;
52
      TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
53
      }
54
    else       // Master sendet Daten zum Slave
55
      {
56
      TWSCRB |= (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
57
      command = TWSD;
58
      }
59
    }
60
  else if (status & I2C_ADDRESS_STOP_MATCH)
61
    {
62
    if (TWSSRA & I2C_BUS_COLLISION)
63
      {
64
      TWSCRB = (uint8_t) (1<<TWCMD1);
65
      }
66
    else
67
      {
68
      if (TWSSRA & (1<<TWAS))
69
        {
70
        // ACK
71
        TWSCRB = (uint8_t) ((1<<TWCMD1)|(1<<TWCMD0));
72
        }
73
      else
74
        {
75
        // Stop Condition
76
        TWSCRB = (uint8_t) (1<<TWCMD1);
77
        }
78
      }
79
    }
80
  }
81
82
int main(void)
83
  {  
84
  DDRA=0b00000011;      // Port A auf Ausgang schalten
85
  PORTA=0b00000011;      // Port A auf aus 
86
  DDRB=0b00000011;      // Port A auf Ausgang schalten
87
  PORTB=0b00000011;      // Port A auf aus  
88
    //ADC_init();
89
  I2C_init();
90
  //Timer0_init;
91
  while(1)
92
    {
93
    if (command != 42)           // Taster T2 PD0
94
     {                    // Wenn T1 gedrückt...
95
       PORTA &=~(1<<PINA1);        // LED 2 ein  
96
     }
97
     else
98
    {                    // wenn nicht
99
       PORTA |=(1<<PINA1);          // LED 2 ein ??
100
    }  
101
     if (command != 43)           // Taster T2 PD0
102
    {                    // Wenn T1 gedrückt...
103
      PORTA &=~(1<<PINA0);        // LED 2 aein
104
    }
105
     else
106
    {                    // wenn nicht  
107
      PORTA |=(1<<PINA0);          // LED 2 ein ??
108
    }   
109
    //if(command != 0x00)
110
    {
111
    //switch(command)
112
      {
113
        
114
        
115
    // ========>> TASTENEINGABEN T3
116
    if (!(PINA & (1<<PINA7)) )            // Taster T 3
117
      {                  // Wenn T3 gedrückt...
118
      tx_buff = 5;  // 4
119
      }
120
    
121
    // ========>> TASTENEINGABEN T2
122
    if (!(PINB & (1<<PINB2)) )            // Taster T 3
123
      {                  // Wenn T3 gedrückt...
124
      tx_buff = 3;  // 4
125
      }    
126
        //case 0x01:
127
        // Test Daten
128
        //tx_buf[0] = 0x01;
129
        //tx_buf[1] = 0x02;
130
        //tx_buf[2] = 0x13;
131
        //tx_buf[3] = 0x14;
132
        //tx_buf_index = 0;
133
        //break;
134
      }
135
      //command = 0x00;
136
    }
137
   
138
    }
139
  }
Nicht vergessen, ist alles erst im entstehen und bestimmt noch 
verbessert werden.

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

Wie um alles in der Welt kann/soll jemand Deinen Code testen, wenn Du 
diese "main.h" NICHT(!!!) mit angegeben hast?

Bitte etwas mehr Sorgfalt walten lassen!

Paul schrieb:
> Weiter geht es mit dem Code zum Attiny 841 mit I2C Bus als Slave. Der
> Code ist noch nicht geputzt und einiges zur Probe drin, aber er
> funktioniert.
> Falls ihn jemand verwendet bitte die Erfahrung mitteilen.// Slave mit
> Attiny 841 zum Master mit ATm 1284p
>
> #include "main.h"      // CPU 16MHz
> #include <avr/interrupt.h>  // dient zur Behandlung der Interrupts
> #include <avr/io.h>         // Integer-Definitionen

da bekommt man das Ding nich' mal kompiliert...

auch wenn der Code nicht fertig ist - die Kommentare sollten stimmen

außerdem solltest Du den Code als Datei (!) anhängen und nicht hier im 
Fenster - kann man dann das file besser runterladen

Ist der Code für den Master oder den Attiny841?
Wenn's für den Master ist - was ist mit dem Code für den Attiny und 
wenn's für den Attiny ist - wo ist der Code für den Master?

: Bearbeitet durch User
von Paul (Gast)


Angehängte Dateien:

Lesenswert?

De Code ist nur für den Attiny 841 und die main besteht nur aus dem
1
#define F_CPU 16000000        // CPU clock in Hz
hänge die Datein aber getrennt für master und slave an.
Der Code ist in Arbeit und auf keinen Fall fertig. Dadurch stimmen aber 
auch die Kommentare nicht. Die Auskommentierten Teile einfach löschen.

von Paul (Gast)


Angehängte Dateien:

Lesenswert?

Kommt noch der master. Falls die I2clcd fehlen sollten oder der 
Copmpiler deswegen meckert bitte die Datein auskommentieren

von Paul (Gast)


Lesenswert?

Hatte ja eindeutig geschrieben das es der Code zum Ati 841 ist und der 
ist der Slave

von Paul (Gast)


Lesenswert?

Vergessen dazu zu sagen, der Master ist ein Atmega 1284p

von neuer PIC Freund (Gast)


Lesenswert?

1
// wait until transmission completed
2
  while(!(TWCR & (1<<TWINT)));

Standard Internetzeugs. Ein bisschen legaler Kurzschluss und alles 
steht.

1
lcd_command(LCD_CLEAR);          // Leere Display
2
delay_ms(2);                  // Warte 2ms

Sinnfreie Kommentierung.
1
// ========>> TASTENEINGABEN T3
2
    if (!(PINA & (1<<PINA7)) )            // Taster T 3

Kapitulation?

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo neuer PIC Freund

Klar, dass Du Dich als Gast anmeldest - da kann man so schön ungestört 
ablästern und bleibt anonym. Erbärmlich.

Wie Paul schon etwas weiter oben geschrieben hat, sind die Kommentare 
nicht uptodate - also was sollen Deine Kommentare?

neuer PIC Freund schrieb im Beitrag #6040978:
> Standard Internetzeugs. Ein bisschen legaler Kurzschluss und alles
> steht.

Wilst Du helfen oder nur rumtrollen?

von neuer PIC Freund (Gast)


Lesenswert?

> Wilst Du helfen oder nur rumtrollen?

Denkanregungen geben, im positiven Sinne. Hätte ich vielleicht mit 
Blümchen verzieren sollen, damit es freundlicher rüberkommt.

Z.b. vollredundante Kommentare gar nicht erst schreiben. Kostet den 
Schreiberling Zeit und dem Leser bringt es nichts.

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.