Attiny85 Pin als Eingang

Gast #5695832
Lesenswert?

Ich will den PinB3 auf input schalten, und abfragen wenn er auf high ist 
soll PortB4 toggeln und ansonsten ausgehen. Aber die LED(PB4) ist immer 
an, was haeb ich falsch gemacht?
1
int main(void)
2
{
3
  DDRB  |=  ((1<<DDB4) | (0 << DDB3)); // B4: output; B3: Input
4
  PORTB  |=  ((1<<PB4) | (1<<PB3)); 
5
  
6
    while (1) 
7
    {
8
   if (PINB3==1)
9
   {
10
    // PORTB |= (1<<PB4);
11
   PORTB ^= ( 1 << PB4 );
12
   }
13
   else
14
   {
15
     PORTB &= ~(1<<PB4);
16
   }
Moderator (Firma: Titel) Persönliche Seite #5695879
Lesenswert?

tinyy schrieb:
> wieso kann ich dann nicht "if (PINB & 1)".
Damit würdest du Pin B0 abfragen.

> Wieso muss ich erst die 1 an
> diese Stelle verschieben und dann vergleichen?
Musst du nicht. Du kannst für die Abfrage des Pin B3 auch so schreiben:
1
   if (PINB & 8)
2
   ...
Oder so:
1
   if (PINB & 0x08)
2
   ...
Oder sogar so:
1
   if (PINB & 010)
2
   ...
Dann musst du eben gut Kopfrechen können, um aus den beliebigen 
Zahlensystem den PB3 herauszuknobeln...
Gast #5695903
Lesenswert?

tinyy schrieb:
> was haeb ich falsch gemacht?

Einiges!

Du meinst vermutlich sowas:
1
int main(void)
2
{
3
  DDRB  |=  (1 << DDB4);  // B4: output;
4
  DDRB  &= ~(0 << DDB3);  // B3: Input
5
  
6
  PORTB  |=  (1 << PB4);  // PB4 High
7
  PORTB  |=  (1 << PB3);  // PB3 Pullup on
8
  
9
  while (1) 
10
  {
11
    if (PINB & (1<<PB3))
12
    {
13
      PINB =  ( 1 << PB4 ); // Toggle Pin
14
    }
15
    else
16
    {
17
      PORTB &= ~(1 << PB4); // set low
18
    }
19
  }  
20
  return 0;
21
}

tinyy schrieb:
> wieso kann ich dann nicht "if (PINB & 1)". Wieso muss ich erst die 1 an
> diese Stelle verschieben und dann vergleichen?

> if (PINB & 1)
entspricht
> if (PINB & 0b000001)
Du willst aber
> if (PINB & (1<<PB3))
Welches zu diesem wird
> if (PINB &  0b001000)

Du siehst den Unterschied?
Moderator (Firma: Titel) Persönliche Seite #5696009
Lesenswert?

tinyy schrieb:
> Warum jetzt mit PB3 statt PINB3 vergleichen?
Du könntest auch PD3 oder PINC3 nehmen.
Es ist egal. Alle haben den numerischen Wert 3.

Im "Sinne des Erfinders" ist es allerdings, wenn du PINB3 zur Maskierung 
auf einem Pins verwendest. Und wenn du einen Code zu lesen bekommst, wo 
nicht geplante Definitionen miteinander verwendet werden, dann sollte 
die gelbe Warnlampe angehen und du das Schlimmste vermuten: nämlich, 
dass nicht PD3 in dieser gemischten Abfrage falsch ist, sondern PINB:
if (PINB & (1<<PD3))...
Gast #5696790
Lesenswert?

Lothar M. schrieb:
> Du könntest auch PD3 oder PINC3 nehmen.
> Es ist egal. Alle haben den numerischen Wert 3.

Ist das zu 100% sicher? Bei den Ports vielleicht ...
Ich würde mich nicht darauf verlassen und bei dem Tiny85, der keinen 
Port C oder D besitzt, wird der Compiler beide in der io.h eh nicht 
finden. Außerdem: was soll ich denken, wenn ich ein für den Tiny85 
geschriebenes Programm sehe und dort von PORTC, PINC und DDRC die Rede 
ist?

Außerdem, ähnliche Definitionen und Vorgehensweisen nutzt man ja auch 
bei den  Registern und da passt es häufiger mal nicht.
Es empfiehlt sich, die Schreibweise
1
  PORTB  |=  (1 << PB4);  // Ausgang B4 auf HIGH setzten
2
  PORTB  &= ~(1 << PB3);  // Ausgang B3 auf LOW setzen
anzugewöhnen und mal durchzudenken.

@Arduino Funboy
Das hier ist es nicht ganz - stell dir vor, B3 war vorher Ausgang :-):
  DDRB  &= ~(0 << DDB3);  // B3: Input
            ^^^
Gast #5696802
Lesenswert?

Arduino Fanboy D. schrieb:
> DDRB  &= ~(0 << DDB3);  // B3: Input
Hasste recht!

Besser:
 DDRB  &= ~(1 << DDB3);  // B3: Input

Macht zum Glück nichts aus, da INPUT der  default nach dem Reset.

Sind übrigens noch mehr Unsauberkeiten drin!
> PORTB  |=  (1 << PB4);
Obwohl ich es hier mit PB4 tute, ist es dennoch nicht ganz korrekt.
Besser:
 PORTB  |=  (1 << PORTB4);

Meine übliche Schreibweise wäre eher:
 PORTB  |=  _BV(PB4);
Oder:
 led.setHigh();


Das korrigierte Gesamtprogramm sieht dann so aus:
1
int main(void)
2
{
3
  DDRB  |=  (1 << DDB4);  // B4: output;
4
  DDRB  &= ~(1 << DDB3);  // B3: Input
5
  
6
  PORTB  |=  (1 << PORTB4);  // PB4 High
7
  PORTB  |=  (1 << PORTB3);  // PB3 Pullup on.. 
8
  
9
  while (1) 
10
  {
11
    if (PINB & (1<<PINB3))
12
    {
13
      PINB = ( 1 << PINB4 ); // Toggle Pin
14
    }
15
    else
16
    {
17
      PORTB &= ~(1 << PORTB4); // set low
18
    }
19
  }  
20
  return 0;
21
}




HildeK schrieb:
> Ist das zu 100% sicher? Bei den Ports vielleicht ...

Ich bin mir sicher, dass das bei allen AVRs der Fall ist, welche mir 
bisher unter die Finger gekommen sind.
Und von irgend einer Ausnahme habe ich noch nicht gehört.
PORTB4 und DDB4 kommen in meinen Programmen nicht vor.
Wenn, dann PB4.
Gast #5696832
Lesenswert?

Es ist ein semantischer Unterschied.
Der Wert ist identisch. Das weißt du doch auch, oder?

Merke, es ist der Wunsch des TE es so zu machen!
Nicht meiner.

tinyy schrieb:
> Warum jetzt mit PB3 statt PINB3 vergleichen? Ich komme ziemlich
> Durcheinander Mit registernamen und Pinnamen usw.
Gast #5696856
Lesenswert?

HildeK schrieb:
> Arduino Fanboy D. schrieb:
>> Macht zum Glück nichts aus, da INPUT der  default nach dem Reset.
>
> Deshalb mein Hinweis:
>
> HildeK schrieb:
>> stell dir vor, B3 war vorher Ausgang :-)
Wo du Wahr hast, da hast du Wahr.

Mehr, als dir zustimmen, kann ich nicht!
Hmmm... doch...
Danke, dass du mich auf den Lapsus aufmerksam gemacht hast.
Gast #5696859
Lesenswert?

Rufus Τ. F. schrieb:
> Und für welche Verwendung sind Deiner Ansicht nach die Symbole PB0 bis
> PB7 gedacht?
Wofür sind deiner Ansicht nach die Symbole PORTB4, PINB4 und DDB4 
gedacht?

Tipp:
Ich heiße nicht Atmel.
Also ist es doch recht unwahrscheinlich, das ich weiß, wie Atmel denkt, 
gedacht hat.
Gast #5696876
Lesenswert?

Rufus Τ. F. schrieb:
> Arduino Fanboy D. schrieb:
>> Wofür sind deiner Ansicht nach die Symbole PORTB4, PINB4 und DDB4
>> gedacht?
>
> Magst Du bitte meine Frage beantworten?

Ich kann meine Antwort gerne nochmal in anderen Worten wiederholen.
Ich weiß nicht GENAU, was Atmel sich dabei gedacht hat!
Denn ich bin nicht Atmel

Wenn du mit der Antwort nicht zufrieden bist, dann ist und bleibt das 
dein Problem.
Gast #5696885
Lesenswert?

Arduino Fanboy D. schrieb:
> Wofür sind deiner Ansicht nach die Symbole PORTB4, PINB4 und DDB4
> gedacht?

Ist PORTBx überhaupt definiert?
In der iotnx5.h sehe ich nur PINBx, DDRBx, PBx. Zumindest in meiner 
WINAVR-20100110.
1
#define PINB    _SFR_IO8(0x16)
2
#define PINB5   5
3
#define PINB4   4
4
.
5
.
6
#define DDRB    _SFR_IO8(0x17)
7
#define DDB5    5
8
.
9
.
10
#define PORTB   _SFR_IO8(0x18)
11
#define PB5     5
12
.
13
.
Ich wüsste auch nicht, was man außer den drei Definitionen unterscheiden 
müsste.
Gast #5696901
Lesenswert?

HildeK schrieb:
> Ist PORTBx überhaupt definiert?

Ja!

HildeK schrieb:
> Zumindest in meiner
> WINAVR-20100110.
Ich nutze die mit Arduino gelieferte ToolChain.
Sollte also aktueller sein.

Dort findet sich in io.h ein #include <avr/portpins.h>

Und wenn du in diese Datei schaust, findest du auch die Definition von 
PORTBx

@Rufus
Warum das so organisiert ist?
KA, ich bin nicht Atmel!
(vermutlich hätte ich das anders gebaut)
Persönliche Seite #5696947
Lesenswert?

Arduino Fanboy D. schrieb:
> Dort findet sich in io.h ein #include <avr/portpins.h>

Ist die relevant? Ist nicht (für den Tiny85) die iotnx5.h relevant?

In der ist klar eine Zuordnung zu erkennen:
1
#define PINB    _SFR_IO8(0x16)
2
#define PINB5   5
3
#define PINB4   4
4
#define PINB3   3
5
#define PINB2   2
6
#define PINB1   1
7
#define PINB0   0
8

9
#define DDRB    _SFR_IO8(0x17)
10
#define DDB5    5
11
#define DDB4    4
12
#define DDB3    3
13
#define DDB2    2
14
#define DDB1    1
15
#define DDB0    0
16

17
#define PORTB   _SFR_IO8(0x18)
18
#define PB5     5
19
#define PB4     4
20
#define PB3     3
21
#define PB2     2
22
#define PB1     1
23
#define PB0     0

avr/io.h bindet in Abhängigkeit des Controllertyps als erstes 
avr/iotn85.h
ein, das wiederum bindet avr/iotnx5.h ein.

Und damit sind obige Definitionen schon mal vorhanden.

portpins.h bildet Alternativen nur für die Bitnummern der PORT-Register, 
nicht aber für die PIN- oder die DDR-Register.

Du meinst, daraus ableiten zu können, daß das die Definitionen sind, die 
man verwenden soll, wenn man auf Bits in PORT-Registern zugreift?

Ich hab' den Eindruck, daß das sehr, sehr viele AVR-Anwender anders 
sehen.

Die nutzen die Definitionen aus der zum Controller gehörenden 
io.h-Variante, d.h. Bitnamen, die zum jeweiligen Register passen.

Da es keine nochmals abgeleiteten Varianten aus PINB0, DDB0 etc. gibt, 
ist also "portpins.h" eine nicht orthogonale Sonderlocke, die ich 
deswegen schon getrost ignorieren würde.
Gast #5696978
Lesenswert?

Rufus Τ. F. schrieb:
> die ich

Projiziere deine Vorstellung von der Welt, auf die Welt!
Und du wirst deine Vorstellungen bestätigt sehen.

Dann sind sie auch richtig, denn bestätigt.
Oder?

----

Interessante Sache!
Du fragst mich , was die Atmels sich dabei gedacht haben...
Kommst dann mit so einem Wackelpudding an Erklärungen, wie du die Welt 
siehst.

Rufus Τ. F. schrieb:
> ich
> deswegen schon getrost ignorieren würde.
Die Datei wird eingebunden, egal ob du sie ignorieren möchtest oder 
nicht!

Die Welt wird einfacher, leichter zu bewerten, zu beurteilen, wenn 
anfängt Dinge auszublenden, zu ignorieren.
Nur leider werden die logischen Schlüsse, welche man aus diesen 
Vereinfachungen ableitet, mit zunehmender Vereinfachung, immer 
irrationaler.

Von dir hätte ich eine so reduzierte Weltsicht nicht erwartet.
Aber offensichtlich scheinst du dazu zu neigen.
Gast #5697029
Lesenswert?

Hi

Das ist eigentlich ganz einfach: In der Anfangszeit hat Atmel die 
Bezeichnung, z.B. Port B (PB7..PB0)(beim AT90S4414) benutzt. Später 
wurde die Bezeichnung PORT3 eingeführt. Und aus Kompatibilitätsgründen 
werden damit beide Bezeichnungen gültig.

MfG Spess
Gast #5697030
Lesenswert?

Rufus Τ. F. schrieb:
> Du bist jetzt sehr gründlich nicht auf meine Argumentation eingegangen.

Rufus Τ. F. schrieb:
> Du meinst, daraus ableiten zu können,
Darauf bin ich eingegangen!
OK, vielleicht hast du die Antwort nicht verstanden, kann ja sein ...

Dann noch mal klarer:
Ich werde mich nicht deiner Projektion anpassen.


Übrigens:
Bisher hast du mich noch nicht nach "meiner" Meinung gefragt!
Nur, was sich die Atmel Leute dabei gedacht haben mögen.

Ich glaube übrigens nicht, dass sie die Datei portpins.h 
ausliefern/einbinden, damit man sie ignoriert.
Das kann man natürlich tun, ist aber sicherlich nicht der Zweck.

Rufus Τ. F. schrieb:
> Ist eine Diskussion mit Dir tatsächlich komplett sinnlos?
Wenn dir diese Projektion zusagt, und du sie anwendest, dich dem 
entsprechend verhältst, dann wird das wohl so sein!
Deine Entscheidung.
Gast #5697083
Lesenswert?

Rufus Τ. F. schrieb:
> Und warum gibt es dann keine korrespondierende Datei für DDRx und PINx?

Deine provokanten und inhaltsleeren Fragen erinnern mich (verzeihe mir 
bitte den Vergleich) ganz stark an des Kurt Bindl seine Fragen.

Ich ziehe mal ein paar Zeilen aus dem obigen Programm raus:
1
DDRB  &= ~(1 << DDB3);
2
PORTB &= ~(1 << PORTB4);
3
PINB = ( 1 << PINB4 );
Syntax, ist ok
Semantik ist ok
Programm ist damit korrekt lauffähig.

Bei mir würde das eher so aussehen
(wobei es eigentlich nicht wichtig ist, wie ICH das tue, sondern eher 
warum)
1
DDRB  &= ~(1 << PB3);
2
PORTB &= ~(1 << PB4);
3
PINB = ( 1 << PB4);
Syntax, ist ok
Semantik ist brauchbar, da man erkennen kann, was gemeint ist.
Programm ist damit korrekt lauffähig.



Dann setze ich mal 2 Zeilen gegeneinander:
1
PORTB &= ~(1 << PORTB4);
2
PORTB &= ~(1 << PB4);
Dort ist die Semantik in der ersten Zeile eine Nuance klarer.
Etwas konsequenter umgesetzt.
Ein mehr an Klarheit ist doch immer besser, oder?
Gast #5697559
Lesenswert?

Arduino Fanboy D. schrieb:
> Ich nutze die mit Arduino gelieferte ToolChain.
> Sollte also aktueller sein.
>
> Dort findet sich in io.h ein #include <avr/portpins.h>
>
> Und wenn du in diese Datei schaust, findest du auch die Definition von
> PORTBx

Danke. Ja, ist in dem 'alten' WINAVR auch enthalten, hatte ich bisher 
nur nicht gesehen:
1
#if defined(PB4) && !defined(PORTB4)
2
#  define PORTB4 PB4
3
#elif defined(PORTB4) && !defined(PB4)
4
#  define PB4 PORTB4
5
#endif
Damit akzeptiert deinen Quelltext auch mein Compiler und umgekehrt - die 
Portabilität wäre auch das Wichtigste.

Und dann gibt es auch noch generische Definitionen (gekürzt):
1
/* Define Generic PORTn, DDn, and PINn values. */
2

3
/* Port Data Register (generic) */
4
#define    PORT7        7
5
#define    PORT6        6
6
.
7
.
8

9
/* Port Data Direction Register (generic) */
10
#define    DD7          7
11
#define    DD6          6
12
.
13
.
14

15
/* Port Input Pins (generic) */
16
#define    PIN7         7
17
#define    PIN6         6
18
.
19
.
Demnach deutet alles darauf hin, dass deine Erfahrung
Arduino Fanboy D. schrieb:
> HildeK schrieb:
>> Ist das zu 100% sicher? Bei den Ports vielleicht ...
>
> Ich bin mir sicher, dass das bei allen AVRs der Fall ist, welche mir
> bisher unter die Finger gekommen sind.
sogar Fakt für alle ist, sonst würde der Teil wenig sinnvoll sein.

Demnach geht genauso
1
DDRB  &= ~(1 << DD3);
2
PORTB &= ~(1 << PORT4);   
3
PINB = ( 1 << PIN4 );
Scheint für jeden Gusto was vorhanden zu sein. Ich nehme immer, weil so 
mit dem Thema begonnen (z.B. im Forumstutorial):
1
DDRB  &= ~(1 << DDB3);
2
PORTB &= ~(1 << PB4);   // so ist im DB auch der Pin gekennzeichnet
3
PINB = ( 1 << PINB4 );
Die Semantik ist imho dann am klarsten, wenn man das, was man 
programmiert hat, auch nach einiger Zeit noch versteht :-). Ich 
persönlich bin nicht darauf angewiesen, dass es andere auch genauso gut 
verstehen, weil ich nur eine private Anwendungen habe.
Gast #5697577
Lesenswert?

Nachtrag:
In letzter Zeit bevorzuge ich die über die sbit.h von Peter D. 
vorgestellte Variante.
Ein einfaches Programm sieht dann so aus und ist noch viel 
verständlicher und mir viel sympathischer:
1
#include "sbit.h"  // (c) Peter Dannegger
2

3
#define LED0      PORT_B0
4
#define LED0_oe    DDR_B0
5
#define LED1       PORT_B1
6
#define LED1_oe     DDR_B1
7
#define INPUT     PIN_B2
8
#define INPUT_oe  DDR_B2
9

10
#define EIN  0      // zum LEDs schalten beim STK500
11
#define AUS  1   
12
#define HIGH 1    // für Inputs
13
#define LOW  0
14

15
int main()
16
{
17
  LED0_oe  = 1;    // Auf Output schalten
18
  LED1_oe  = 1;
19
  INPUT_oe = 0;    // auf Input schalten
20
   
21
  LED0 = AUS;      // LED0-Port auf aus
22
  LED1 = EIN;     // LED1-Port auf ein
23
  
24
  if(LED1 == EIN) LED0 = EIN;  // auch Abfragen sind möglich
25
  if(LED0 == EIN) LED1 = AUS;
26
  
27
  LED0  ^= 1;         // Toggle
28
  PORTB ^= (1<<PB0);  // entspricht dieser bekannten Version
29
  PINB   = (1<<PB0);  // oder auch der
30

31
  LED1 ^= 1;  // Toggle
32

33
  if (INPUT == HIGH) LED1 ^= 1;  // Input-Abfrage
34
  if (INPUT == LOW)  LED0 ^= 1;
35

36
  while(1)  asm("NOP");  // nur wegen Simulator
37
}
Hat was für die Lesbarkeit, oder?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren