Forum: Mikrocontroller und Digitale Elektronik Attiny 2313 einzelne Bits ansprechen


von Andreas M. (andreas2461988)


Lesenswert?

Hallo,

ich bin gerade dabei meine erste Versuche mit einem Attiny 2313 zu 
machen. Die Ports komplett anzusprechen funktioniert super, allerdings 
schaff ich nicht ein einzelnes bit anzusprechen. Für dies kenn ich 
normalerweiße den Befehl sbit in C, aber mit diesem bekomm ich einen 
Fehler beim kompilieren. Das ganze Register will ich nicht ansprechen, 
da ich nur einen Ausgang auslesen will und die anderen dazu nicht 
relevant sind.

Gruß Andreas

Das Programm ist nur zum testen und soll ein Lauflicht laufen lassen 
solange der entsprechende Taster gedrückt ist:


int main (void)
{
DDRB = 0xFF;    //Port D als Ausgang definieren
DDRA = 0X00;    //Port A als Eingan definieren

for (;;) {    // Schleife

if ( PINA == 0x02)

        {

        PORTB = 0x80;
        _delay_ms(250);


          PORTB = 0x40;
        _delay_ms(250);


          PORTB = 0x20;
        _delay_ms(250);


          PORTB = 0x10;
        _delay_ms(250);


          PORTB = 0x08;
        _delay_ms(250);

       }
          }
}

von Michael H. (michael_h45)


Lesenswert?

Bitmanipulation
Die Vorgehensweise ist: wort-weises Lesen und Ausmaskieren der 
irrelevanten Bits.

von Klaus W. (mfgkw)


Lesenswert?

Die Vorgehensweise ist: erstmal das Tutorial lesen.
Da steht das alles drin :-)

von Uwe (de0508)


Lesenswert?

Hallo Andreas,

nicht ärgern, manchmal muss man sich die Macros selbst definieren:
1
#include <avr/io.h>
2
3
#define sbit(_port, _bit)  _port |= _BV(_bit)
4
#define cbit(_port, _bit)  _port &= ~_BV(_bit)
5
#define tbit(_port, _bit)  _port ^= ~_BV(_bit)

Ich verwende nun aber nur noch dieses Macro, das ist viel 
leistungsfähiger:
1
// PeDa
2
struct bits {
3
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
4
} __attribute__((__packed__));
5
6
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
7
#define  SBIT(x,y)  SBIT_(x,y)

Man muss nicht sofort versehen, was da genau passiert, außer wie man es 
anwendet.

Hier sind einige Beispiele:
1
#define LED_DDR SBIT(DDRB,PB1)
2
#define LED     SBIT(PORTB,PB1)
3
4
// Pin auf Ausgabe
5
LED_DDR = 1;
6
7
// Pin auf High setzen
8
LED = 1;
9
10
// Pin auf Low setzen
11
LED = 0;
12
13
// Toggle Pin
14
if (LED) { LED = 0; } else { LED = 1; }
15
16
#define SWITCH_DDR SBIT(DDRB,PB2)
17
#define SWITCH_PORT SBIT(PORT,PB2)
18
#define SWITCH     SBIT(PIN,PB2)
19
20
// Pin auf Eingang
21
SWITCH_DDR = 0;
22
23
// Pullup ON
24
SWITCH_PORT = 1;
25
26
if (SWITCH == 0) // ist der Eingang aktiv ? (==0)
27
{ 
28
// do some thing
29
}

von Michael H. (michael_h45)


Lesenswert?

Uwe S. schrieb:
> Man muss nicht sofort versehen, was da genau passiert, außer wie man es
> anwendet.

genau das ist größtmöglicher stumpfsinn!

von Andreas M. (andreas2461988)


Lesenswert?

Hallo,

ihr seid super, danke für eure schnellen Antworten!!

Leider kommt es jetzt noch zu einem Fehler und zwar wenn ich die 
definierte Variable verwende, dann bringt mit der compiler:

 ../Blink.c:34: error: lvalue required as left operand of assignment

Gruß Andi

von Uwe (de0508)


Lesenswert?

Andi,

bitte stelle auch immer den kompletten Code ein, nur so sehen wir was 
Du gerade machst.

_

von Andreas M. (andreas2461988)


Lesenswert?

Hier der code
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
7
8
9
int main (void)
10
{
11
       
12
    
13
    
14
15
16
            
17
    DDRB = 0xFF;    //Port D als Ausgang definieren
18
    #define LED1     SBIT(PORTB,PB7)
19
    #define LED2     SBIT(PORTB,PB6)
20
    #define LED3     SBIT(PORTB,PB5)    
21
    #define LED4     SBIT(PORTB,PB4)
22
    #define LED5     SBIT(PORTB,PB3)
23
    #define S1DDR   SBIT(DDRA,PA0)
24
    #define S1PORT   SBIT(PORTA, PA0)
25
    #define S1        SBIT(PIN,PA0)
26
27
  
28
29
    S1DDR = 0;
30
    S1PORT = 1;
31
    
32
33
    
34
        for (;;) {    // Schleife
35
                
36
37
38
    
39
        
40
        if ( S1 == 0)
41
              
42
        {
43
44
        PORTB = 0x80;
45
        _delay_ms(250);
46
47
        
48
          PORTB = 0x40;
49
        _delay_ms(250);
50
51
52
          PORTB = 0x20;
53
        _delay_ms(250);
54
55
56
          PORTB = 0x10;
57
        _delay_ms(250);
58
59
60
          PORTB = 0x08;
61
        _delay_ms(250);
62
    
63
       }
64
    
65
    else
66
    {PORTB = 0x80;}        
67
        
68
      
69
        
70
  
71
        }
72
}

von dummschwaetzer (Gast)


Lesenswert?

dann zeig mal Zeile 34 in blink.c und die Deklarationen von den Sachen, 
die in Zeile 34 verwendet werden.

von Peter D. (peda)


Lesenswert?


von Michael H. (michael_h45)


Lesenswert?

Michael H. schrieb:
> Uwe S. schrieb:
>> Man muss nicht sofort versehen, was da genau passiert, außer wie man es
>> anwendet.
>
> genau das ist größtmöglicher stumpfsinn!

und die bestätigung dafür folgt natürlich auf dem fuße!

Andreas M. schrieb:
>  ../Blink.c:34: error: lvalue required as left operand of assignment


besten dank!

von Hilfreicher Helfer (Gast)


Lesenswert?

200 g   Radieschen
200 g   Frühlingszwiebel(n)
400 g   Mozzarella

von Andreas M. (andreas2461988)


Lesenswert?

Hallo,

schön zu sehen das die Benutzer eines Forums immer gleich sind egal um 
welches Thema es geht!

Danke Uwe, genau das mit dem Sbit habe ich gesucht!


@Michael, das Leistungsfähige Macro habe ich gar nicht benutzt, also 
keine Grund zur aufregung.

@ alle die Ihre Einkaufslisten hier einbringen, die helfen mir nicht 
wieder!

Gruß Andreas, dessen erste Begeisterung langsam nachlässt von diesem 
Forum.

von Jakov K. (jackenkoffer)


Lesenswert?

Das
1
    #define LED1     SBIT(PORTB,PB7)
2
    #define LED2     SBIT(PORTB,PB6)
3
    #define LED3     SBIT(PORTB,PB5)    
4
    #define LED4     SBIT(PORTB,PB4)
5
    #define LED5     SBIT(PORTB,PB3)
6
    #define S1DDR   SBIT(DDRA,PA0)
7
    #define S1PORT   SBIT(PORTA, PA0)
8
    #define S1        SBIT(PIN,PA0)

sollte man außerhalb der ganzen main() funktionen machen.
es steht direkt nach den anderen makros( in deinem fall muss es nach dem
1
 #include <util/delay>
 stehen )

außerdem hast du die funktion "strukt bits" vergessen.

der Quellcode(anfang) müsste so aussehen :
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
struct bits {
7
  unsigned b0:1;
8
  unsigned b1:1;
9
  unsigned b2:1;
10
  unsigned b3:1;
11
  unsigned b4:1;
12
  unsigned b5:1;
13
  unsigned b6:1;
14
  unsigned b7:1;
15
} __attribute__((__packed__));
16
17
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
18
19
#define LED1     SBIT(PORTB,PB7)
20
#define LED2     SBIT(PORTB,PB6)
21
#define LED3     SBIT(PORTB,PB5)    
22
#define LED4     SBIT(PORTB,PB4)
23
#define LED5     SBIT(PORTB,PB3)
24
#define S1DDR   SBIT(DDRA,PA0)
25
#define S1PORT   SBIT(PORTA, PA0)
26
#define S1        SBIT(PIN,PA0)
27
28
int main (void)
29
{
30
   DDRB = 0xff;
31
   ...(usw)

und: wenn du Hilfe in diesem Forum suchst, findest du sie ;)

Gruß, Jakov

von Andreas M. (andreas2461988)


Lesenswert?

Hallo Jakov,

danke für deine Hilfe. Ich hatte den struct bit vergessen, da ich dachte 
es handelt sich um eine andere Methode die Pins zu definieren. Weißt du 
wo man nachlesen kann was der struct bit teil genau macht?

Nun habe ich leider noch das Problem wenn ich die Variable zum ersten 
mal verwende sagt der compiler:

../Blink.c:51: error: 'volatile struct bits' has no member named 'bDDA1'

Gruß Andreas

von Peter D. (peda)


Lesenswert?

Andreas M. schrieb:
> ../Blink.c:51: error: 'volatile struct bits' has no member named 'bDDA1'

Psst, ich verrate Dir mal ein Geheimnis:
Die 51 hinter dem Filenamen ist die Zeilennummer, wo der Fehler wirkt.
Diese Zeile must Du angucken oder uns zeigen.

Und die Meldung besagt, daß er den Text "DDA1" gefunden hat, Du aber 
nirgendwo etwas sinnvolles dafür definiert hast.


Du kannst aber auch einfach meine oben verlinkte sbit.h includieren, das 
vermeidet solche Fehler.


Peter

von Andreas M. (andreas2461988)


Lesenswert?

Hallo Peter,

danke für den Tipp, das wusst ich zwar schon, hat mich in dem Fall 
leider nicht weiter gebracht, da in den Zeilen nicht viel steht, ich 
glaube der Fehler liegt immer noch irgendwo an der Dekleration!

Deine Methode funktioniert um den Eingang und den Pullup zu Schalten 
ohne das der Compiler meckert, aber sobald ich dies in der IF Schleife 
verwende will es nicht funktionieren if(PIN_D0 ==1).

Die Methode mit define gefällt mir, da ich hiermit meine Namen frei 
vergeben kann, deswegn hoff ich das ich es auf diese weise zum laufen 
bekomme!

Ich hoffe doch, das auch ich es irgendwann schaffe den Eingang zu 
lesen...
1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
#include <sbit.h> 
6
7
struct bits {
8
  unsigned b0:1;
9
  unsigned b1:1;
10
  unsigned b2:1;
11
  unsigned b3:1;
12
  unsigned b4:1;
13
  unsigned b5:1;
14
  unsigned b6:1;
15
  unsigned b7:1;
16
 } __attribute__((__packed__));
17
18
#define sbit(_port, _bit)  _port |= _BV(_bit)
19
#define cbit(_port, _bit)  _port &= ~_BV(_bit)
20
#define tbit(_port, _bit)  _port ^= ~_BV(_bit)
21
22
23
24
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin)
25
26
  
27
    #define LED1     SBIT(PORTB,PB7)
28
    #define LED2     SBIT(PORTB,PB6)
29
    #define LED3     SBIT(PORTB,PB5)    
30
    #define LED4     SBIT(PORTB,PB4)
31
    #define LED5     SBIT(PORTB,PB3)
32
    #define S1_DDR   SBIT(DDRD,PD0)
33
    #define S1PORT   SBIT(PORTD, PD0)
34
    #define S1        SBIT(PIND,PD0)
35
36
37
38
39
40
int main (void)
41
{
42
43
  DDRB = 0xFF;    //Port D als Ausgang definieren
44
    S1_DDR = 0;      //../Blink.c:53: error: 'volatile struct bits' has no member named 'bPB1'
45
  S1PORT = 1;      //../Blink.c:54: error: 'volatile struct bits' has no member named 'bPB1'
46
47
//  DDRA = 0x00;
48
//  PORTA = 0XFF;
49
    
50
51
    
52
        for (;;) {    // Schleife
53
                
54
  
55
56
57
    
58
        
59
        if ( S1 == 0) //../Blink.c:65: error: 'volatile struct bits' has no member named 'bPD0'
60
61
              
62
        {

von Ingo (Gast)


Lesenswert?

Ich finde solche Makros nicht hilfreich, weil oft vergessen wird was 
eigentlich passiert...


Ingo

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Ingo schrieb:
> Ich finde solche Makros nicht hilfreich, weil oft vergessen wird was
> eigentlich passiert...

Sag das nicht so leichfertig - das demonstriert doch Herrschaftswissen 
...
(und wenn der Makro noch so blöd ist)

von Peter D. (peda)


Lesenswert?

Andreas M. schrieb:
> if ( S1 == 0) //../Blink.c:65: error: 'volatile struct bits' has no member named 
'bPD0'

Du mußt das Macro SBIT aus meiner sbit.h schon vollständig kopieren!

Es besteht nämlich aus 2 Defines.
Das 2. sieht nur so aus, als wäre es überflüssig, ist es aber nicht.
Es macht im ersten Paß die Auflösung des "PD0" zu "0".
Erst dann kann der 2. Durchlauf es verwenden und "b0" draus bauen.


Peter

von Andreas M. (andreas2461988)


Lesenswert?

Es funktioniert, ich danke dir!!!!

Zuvor wollte ich es noch mit der Methode von Uwe zum laufen bringen, die 
mir eigentlich sehr gut gefällt. Ich hoffe ich finde noch heraus warum 
diese nicht geht, solange werde ich nun mit deinem Header arbeiten! 
Dieser funktioniert zwar noch nicht zum einbinden, aber ich habe jetzt 
zum testen den kompletten Code kopiert!

Danke!

Gruß Andi

von Uwe (de0508)


Lesenswert?

Hallo Andreas,

nun das war und ist nicht meine Methode, sondern die von Peter (PeDa),
so hatte ich es auch im Codeschnipsel angegeben:
1
// PeDa
2
struct bits {
3
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
4
} __attribute__((__packed__));
5
6
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
7
#define  SBIT(x,y)  SBIT_(x,y)

Und dies wäre auch so komplett in den deinen Code zu übertragen.

Peter hat dann seine Idee auch in seine |sbit.h| eingearbeitet.

Wie immer ist sein Code oder seine Ideen sehr ausgeklügelt, ergeben 
kompakten und schnellen Code. :-)

Beispiel: "3x4 Matrix keypad Routine"

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=699758&sid=84007a05eee6cd43a18ed6804d63caa4#699758

Aber Dein Problem liegt ganz wo anders, dass Du nicht weist, wie ein 
|#inlcude "<DATEI.H>"| funktioniert.

Das Prinzip nennt man modularisieren.

_

von Andreas M. (andreas2461988)


Lesenswert?

Hallo,

das hatte ich übersehen, das dies bereits von Peter war.

Der Sinn einer Header Datei ist mir schon klar, wie gesagt hatte es aber 
auf die schnlle nicht funktioniert und ich wollte es nach zwei tagen 
schaffen den Eingang zu lesen! Es wird auch noch eine weile dauern bis 
alles so funktioniert wie es soll, inklusive header!

Danke!

von Jannik O. (jannipanni)


Lesenswert?

Also ich schreibe das immer so:

if((PORTB&1)==1) {

}

Da wird zuerst das relevante Bit ausgeundet und dann wird verglichen, ob 
dieses 1 oder 0 ist.
Ist für mich auch übersichtlicher.

von Adam P. (adamap)


Lesenswert?

hallo andreas,

eine kleine anmerkung meinerseits:
da du gerad erst anfängst zu "programmieren", gewöhn dir lieber direkt
eine korrekten aufbau deines codes an.
z.b. richtige einrückungen, weniger leerzeilen etc.

dadurch wird der code für andere besser leesbar und du selbst findest
evtl. auch schneller einen fehler!

gruß

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.