Forum: Mikrocontroller und Digitale Elektronik AVR-C Ein/Ausgabe


von O. A. (sokrates1989)


Lesenswert?

Hallo,

ich habe einige Fragen zu diesem Programm.

1. Warum gehen die Leds an, wenn "PORTB = i;"
Welche Information beinhaltet "i"?

unsigned char i;
ist doch die Deklaration.
Aber wo wird das weiterverarbeitet??

2. Was bedeutet das Ausrufungszeichen in (!(PIND&0x04))  ??

Meine Kenntnisse in C sind begrenzt.
;(

: Verschoben durch Moderator
von Frank L. (hermastersvoice)


Lesenswert?

eher nicht vorhanden...

Da ist weder ein Programm noch kann man erahnen welche LED in deiner 
Schaltung wie verschaltet sind.

von Dirk B. (dirkb2)


Lesenswert?

0. Welches Programm?

1.
i wird eine Variable sein, evtl sogar die, die du als nächstes 
Beschreibst.

O. A. schrieb:
> unsigned char i;
> ist doch die Deklaration.

Das ist sogar eine Definition (mit implizierter Deklaration)
Weiter Siehe 0.

2. Das ! ist der NICHT-Operator.
Der negiert einen logischen Wert. Er macht aus 0 eine 1 und aus allen 
Werten ungleich 0 eine 0

3. Bist du dir sicher, dass du im richtigen Unterforum bist?

von O. A. (sokrates1989)


Angehängte Dateien:

Lesenswert?

Frank L. schrieb:
> eher nicht vorhanden...
>
> Da ist weder ein Programm noch kann man erahnen welche LED in deiner
> Schaltung wie verschaltet sind.

Sorry. Habs vergessen.
1
// alle Lichter an
2
// Atmega8 mit 3,6864 MHz
3
// Sprache C
4
//------------------------------
5
6
#define F_CPU 3686400
7
#include <avr/io.h>
8
//#include <stdlib.h>
9
10
11
12
main () 
13
{
14
15
unsigned char i;
16
17
// hier Init-Code eingeben
18
19
DDRB = 0xFF;    // PortB = Ausgang
20
DDRD = 0x00;    // PortD = Eingang
21
PORTD = 0xFF;     // PortD = Pullup
22
23
while   (1)      // mainloop
24
    {
25
    // eine einfache Warteschleife
26
    for (int k=0; k<1000 ; k++) {};
27
    if (! (PIND & 0x04))        // Wenn Bit 2 = 0, dann Taster gedrückt
28
    PORTB = i;              // PortB wird geschaltet, Led an
29
    else
30
    PORTB = 0;              // Leds aus
31
    i++;
32
    }
33
}

von O. A. (sokrates1989)


Lesenswert?

Dirk B. schrieb:


> 3. Bist du dir sicher, dass du im richtigen Unterforum bist?
Nein.
Werde es im richtige Forum noch mal posten.

Beitrag #5005830 wurde von einem Moderator gelöscht.
von Dirk B. (dirkb2)


Lesenswert?

Da fehlt wohl die Initialisierung von i.

Lass den Thread von einem Moderator verschieben (nicht neu posten).

von O. A. (sokrates1989)


Lesenswert?

Dumpfbacke schrieb im Beitrag #5005830:

> Warum lernst du nicht die Sprache wie jeder anständige
> Programmierer/Anfänger auch?

warum schreibst du Dinge die nicht nützlich sind?

von O. A. (sokrates1989)


Lesenswert?

Hallo,

ich habe einige Fragen zu diesem Programm.

1. Warum gehen die Leds an, wenn "PORTB = i;"
Welche Information beinhaltet "i"?

unsigned char i;
ist doch die Deklaration.
Aber wo wird das weiterverarbeitet??

2. Was bedeutet das Ausrufungszeichen in (!(PIND&0x04))  ??

Meine Kenntnisse in C sind begrenzt.
;(
1
// alle Lichter an
2
// Atmega8 mit 3,6864 MHz
3
// Sprache C
4
//------------------------------
5
6
#define F_CPU 3686400
7
#include <avr/io.h>
8
//#include <stdlib.h>
9
10
11
12
main () 
13
{
14
15
unsigned char i;
16
17
// hier Init-Code eingeben
18
19
DDRB = 0xFF;    // PortB = Ausgang
20
DDRD = 0x00;    // PortD = Eingang
21
PORTD = 0xFF;     // PortD = Pullup
22
23
while   (1)      // mainloop
24
    {
25
    // eine einfache Warteschleife
26
    for (int k=0; k<1000 ; k++) {};
27
    if (! (PIND & 0x04))        // Wenn Bit 2 = 0, dann Taster gedrückt
28
    PORTB = i;              // PortB wird geschaltet, Led an
29
    else
30
    PORTB = 0;              // Leds aus
31
    i++;
32
    }
33
}

von Duke Scarring (Gast)


Lesenswert?

O. A. schrieb:
> warum schreibst du Dinge die nicht nützlich sind?
Einen nützlicheren Hinweis konntest Du gar nicht erhalten...

von IronNie (Gast)


Lesenswert?

O. A. schrieb:
> Aber wo wird das weiterverarbeitet??

Zwischen Zeile 11 und Zeile 12

O. A. schrieb:
> 2. Was bedeutet das Ausrufungszeichen in (!(PIND&0x04))  ??

Das bedeutet, dass das eine ganz wichtige Anweisung ist. Es sagt dem 
Compiler, dass er diese Zeile mit Vorsicht komlilieren soll.


Iron

von Walter S. (avatar)


Lesenswert?

O. A. schrieb:
> // eine einfache Warteschleife
>     for (int k=0; k<1000 ; k++) {};

das wird ein aktueller Compiler einfach wegoptimieren

von Oliver S. (oliverso)


Lesenswert?

Der würde auch vor nicht initialisierten Variablen warnen.

Oliver

von MisterD (Gast)


Lesenswert?

> 1. Warum gehen die Leds an, wenn "PORTB = i;"
> Welche Information beinhaltet "i"?


> unsigned char i;
> ist doch die Deklaration.
> Aber wo wird das weiterverarbeitet??

hier:
>     i++;
++ bedeutet das zur variable 1 hinzugezählt wird ist das gleiche wie 
i+=1; oder i=1+i; (geht übrigends mit -- auch)

> 2. Was bedeutet das Ausrufungszeichen in (!(PIND&0x04))  ??
ein ! wird in C immer verwendet um boolsche (1 oder 0) ausdrücke zu 
negieren also wenn das dahinter TRUE ist ist es danach FALSE und 
umgekehrt

> Meine Kenntnisse in C sind begrenzt.
> ;(

Trau dich ruhig zu fragen und ignorier die trolle hier im forum...

von Dirk B. (dirkb2)


Lesenswert?

MisterD schrieb:
> hier:
>>     i++;
> ++ bedeutet das zur variable 1 hinzugezählt wird ist das gleiche wie
> i+=1; oder i=1+i; (geht übrigends mit -- auch)

Allerdings sollte der Compiler an der Stelle eine Warnung geben.
Etwa "Erstbenutzung einer Variablen ohne Initialisierung".

Wenn nicht, dann muss der Warnlevel angeüasst werden.

von O. A. (sokrates1989)


Lesenswert?

Dirk B. schrieb:
> MisterD schrieb:
>> hier:
>>>     i++;
>> ++ bedeutet das zur variable 1 hinzugezählt wird ist das gleiche wie
>> i+=1; oder i=1+i; (geht übrigends mit -- auch)
>
> Allerdings sollte der Compiler an der Stelle eine Warnung geben.
> Etwa "Erstbenutzung einer Variablen ohne Initialisierung".
>
> Wenn nicht, dann muss der Warnlevel angeüasst werden.

Ja er gibt auch eine Warnmeldung.
Aber ich habe das Programm 1 zu 1 aus einem Buch übernommen.

Was müsste ich tun um es richtig zu machen?

von Dirk B. (dirkb2)


Lesenswert?

Ein anderes Buch nehmen.
Evtl. gibt es aber eine Fehlerlist für das Buch.


Du kannst i mit 255 initialisieren oder mit dem Wert, dem der Port für 
deine LED entspricht.

Und dann das i++; weglassen.

EDIT:
Wenn du aber 8 LEDs hast, dann initiaöisiere mit 1 und lass das i++; 
drin.

: Bearbeitet durch User
von R. F. (rfr)


Lesenswert?

Ich kommentiere das mal...:-)

---------------------------------------------------------

// alle Lichter an
// Atmega8 mit 3,6864 MHz
// Sprache C    == unsinnig! das sieht man am Quelltext oder 
fileextension.
//------------------------------

#define F_CPU 3686400
#include <avr/io.h>
//#include <stdlib.h>



main ()
{

unsigned char i;   == initialisiere hier!! zB.: unsigned char i = 0;

// hier Init-Code eingeben  == und warum steht dann da nix?

DDRB = 0xFF;    // PortB = Ausgang
DDRD = 0x00;    // PortD = Eingang
PORTD = 0xFF;     // PortD = Pullup

while   (1)      // mainloop  == nicht erforderlich
    {
    // eine einfache Warteschleife  == nicht erforderlicher Kommentar, 
schreibe statt dessen: delay xyz ms
    for (int k=0; k<1000 ; k++) {};
    if (! (PIND & 0x04))        // Wenn Bit 2 = 0, dann Taster gedrückt
    PORTB = i;              // PortB wird geschaltet, Led an  == wenn 
richtig initialisiert. Tip zum Vermeiden von Missverständnissen: 
Schliesse hier den code mit {} ein, um dangling elses zu vermeiden.
    else
    PORTB = 0;wenn richtiginitialisiert.      // Leds aus
    i++; == wann hat i welchen Inhalt??
    }
}

: Bearbeitet durch User
von O. A. (sokrates1989)


Lesenswert?

ich verstehe das schon nicht.

 if (! (PIND & 0x04))

das "!" ist eine Negation.

"&" ist ein ein bitweises UND, also werden zwei binärzahlen addiert.

also steht da wenn (4 und 4) was ja "8" ergibt, das wiederum negiert...

wird der nächste Befehl ausgeführt,.



was soll eine negierte "8" bedeuten?

von O. A. (sokrates1989)


Lesenswert?

R. F. schrieb:
> Ich kommentiere das mal...:-)
> und warum steht dann da nix?

Ich habe das 1 zu 1 aus einem Buch.

Falls du das Programm ergänzen könntest dann wäre ich dir sehr sehr 
dankbar.
Ich weiß leider nicht welcher Init-Code da reinkäme
und richtig initialisieren wäre nur "unsigened char i=1" ?

von R. F. (rfr)


Lesenswert?

Hallo nochmal,


es sie PIND = '00000100'
und es gelte :   PIND & 04h

es folgt:   '00000100'
     &      '00000100'
--------------------------
            '00000100' als Ergebnis. Die 'UND'-Verknüpfung erfolgt 
bitweise.


Sei nuin PIND = 00h
            '00000000'
     &      '00000100'
--------------------------
            '00000000'

da ds bitweise 'UND' nicht erfüllt wird. Diesen Vorgang nennt man 
maskieren. In deinem Code ist 04h die Maske.

Das '!' bildet das Komplement: Es wird

'0000 0100'    zu
'1111 1011'     invertiert.

Gruss

Robert

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

O. A. schrieb:
> "&" ist ein ein bitweises UND,

Ja.

> also werden zwei binärzahlen addiert.

Nein. Wieso reimst Du Dir so etwas zusammen?

Eine bitweise AND-Operation arbeitet für jedes Bit nach dieser 
Wahrheitstafel:
1
  A B  A&B
2
  0 0  0
3
  0 1  0
4
  1 0  0
5
  1 1  1

Also: A&B ist nur dann 1, wenn A und B gleich 1 sind.

> also steht da wenn (4 und 4) was ja "8" ergibt, das wiederum negiert...

Nein, da gibt überhaupt nichts 8.

Nehmen wir mal an, dass der Pin D4 high ist, also 1.

Dann ist

  PIND = 00001000

0x04 ist binär:

  0x04 = 00001000

Und nur dann(!) ist:

  (PIND & 0x04) identisch mit 0001000

Da in C alle Werte wahr sind, die nicht 0 sind, ist dieser Ausdruck 
wahr. Da der Programmierer aber das genau den negierten Wert haben will, 
stellt er dem Ausdruck (PIND & 0x04) noch ein Ausrufungszeichen um. Das 
dreht nach der AND-Operation den Wahrheitsgehalt des Ausdrucks um.

: Bearbeitet durch Moderator
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

R. F. schrieb:
> Das '!' bildet das Komplement: Es wird
>
> '0000 0100'    zu
> '1111 1011'     invertiert.

Falsch! Dafür ist der Operator '~'.

Das Ausrufungszeichen negiert nur den Wahrheitswert einer Zahl. Für 
Bit-Operationen ist er schlecht bis gar nicht brauchbar, siehe auch 
Bitmanipulation

 - Aus der Zahl 0 wird 1.
 - Aus allen anderen Zahlen wird 0.

Beispiel:
1
  a = !0      // a ist danach 1
2
  a = !1234   // a ist danach 0

: Bearbeitet durch Moderator
von Dirk B. (dirkb2)


Lesenswert?

Wenn ich das Programm richtig verstehe, es heißt ja "alle Lichter an", 
dann wird bei jedem Tastendruck ein anderes Muster auf die Ports 
gegeben, so dass irgendwann "alle Lichter an" sind.

O. A. schrieb:
> Ich weiß leider nicht welcher Init-Code da reinkäme
> und richtig initialisieren wäre nur "unsigened char i=1" ?

Es wäre ein sinnvoller Wert, damit gleich die erste LED an Port B.0 
angeht,

von R. F. (rfr)


Lesenswert?

1
/* neue Version, by RFr  */
2
/* Programm Licht_an schaltet auf Tastendruck die LED um  */
3
4
#define F_CPU 3686400
5
#include <avr/io.h>
6
/* Atmega8 mit 3,6864 MHz */
7
8
9
main () {
10
  unsigned char i;
11
  
12
  DDRB = 0xFF;    // PortB = als Ausgang gesetzt, LED wird eingeschaltet wenn 'H'  
13
  DDRD = 0x00;    // PortD = als Eingang gesetzt  
14
  PORTD = 0xFF;     // PortD = Pullup eingeschaltet   Taste legt Eingang auf 'H' wenn nicht gedrückt  
15
  
16
  
17
  while   (1)  {
18
    for (int k=0; k<1000 ; k++) {};    /* delay xyz ms */
19
    
20
    if (! (PIND & 0x04)) {PORTB = i}
21
    else {PORTB = 0};              // Leds aus
22
    /*   i++;  erforderlich für Lauflicht?? Schaltplaninformation zufügen!!  */
23
  }

[Mod: Obigen Code in [ c ] ... [ /c ] eingeklammert, damit er lesbar 
wird]

: Bearbeitet durch Moderator
von Dirk B. (dirkb2)


Lesenswert?

Was in den anderen Beispielen mit dem & etwas untergeht, ist der 
Augsangswert vom Port D.
Der kann auch andere Werte haben.
Mit dem & 0x04 maskierst du aber nur das eine Bit raus.

 0111 0110
&0000 0100
-----------
=0000 0100

Darauf wird das ! angewandt und dann kommt 0 raus. Also unwahr -> Taster 
nicht gedrückt

Oder:

 0111 0010
&0000 0100
-----------
=0000 0000

Darauf wird das ! angewandt und dann kommt 1 raus. Also wahr -> Taster 
gedrückt

von R. F. (rfr)


Lesenswert?

>  - Aus der Zahl 0 wird 1.
>  - Aus allen anderen Zahlen wird 0.

Aus dem Wahrheitswert TRUE wird FALSE.
Und umgekehrt.
Bezüglich des Operators hat FramkM recht.
>
> Beispiel:
>
1
>   a = !0      // a ist danach TRUE, also irgendeinen von NULL verschiedenen Wert
2
>   a = !1234   // a ist danach False, entsprechend NULL.
3
>

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

R. F. schrieb:
> - Aus der Zahl 0 wird 1.
>  - Aus allen anderen Zahlen wird 0.
>
> Aus dem Wahrheitswert TRUE wird FALSE.

Das sind nur andere Namen für 0 oder 1.

>   a = !0      // a ist danach TRUE, also irgendeinen von NULL verschiedenen Wert

Falsch, es hat nicht "irgendeinen" von NULL verschiedenen Wert, a ist 
danach definitiv 1. Probiere es einfach aus. Jeder C-Compiler, der 
sich so nennt, wird dafür sorgen, dass nachher 1 in der Variablen steht.

von R. F. (rfr)


Lesenswert?

Richtig ist, dass ddie negierte Null eine eins ergibt und TRUE ist.
Allerdings ist jeder Wert ungleich Null TRUE.

Gruss

Robert

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

R. F. schrieb:
> Richtig ist, dass ddie negierte Null eine eins ergibt und TRUE
> ist.
> Allerdings ist jeder Wert ungleich Null TRUE.

Ich weiß, was Du meinst und Deine Aussage steht auch in keinem 
Widerspruch zu den meinen oben. Aber bitte vermeide es, den Eindruck zu 
vermitteln, man könnte schreiben:
1
    int a = 42;
2
3
    if (a == TRUE)
4
    {
5
        printf ("Der Ausdruck ist wahr\n");
6
    }
7
    else
8
    {
9
        printf ("Der Ausdruck ist falsch\n");
10
    }

Denn das geht so nicht. TRUE ist in C nicht definiert. Das musst Du 
schon selber machen. Wie willst Du das hintricksen, dass obige Bedingung 
(a == TRUE) für alle Zahlen != 0 funktioniert?

Ich kenne nur einen Weg:
1
#define TRUE  1    // jawohl, 1 und nichts anderes!
2
#define FALSE 0
3
#define TRUTH(x) (!!(x))

Dann kannst Du obige Bedingung folgendermaßen schreiben:
1
    if (TRUTH(a) == TRUE)

und es funktioniert für alle a != 0.

Oder Du hast einen C-Compiler, der etwas weniger verstaubt ist. Dann 
kannst Du oben auch einfügen:
1
#include <stdbool.h>

und die Bedingung folgendermaßen schreiben:
1
    if ((bool) a == true)

Auch hier wird es ohne den cast "(bool)" nicht gehen. Der Ausdruck:
1
    if (a == true)

fliegt für a = 42 auf die Nase.

Wenn man aber mal neugierig ist und herausfinden will, was denn nun 
dieses kleingeschriebene "true" aus stdbool.h denn wirklich ist, dann 
fügt man in sein C-Programm mal ein:
1
    printf ("%d\n", true);

und wird sich über die Ausgabe "1" überhaupt nicht mehr wundern.

Fazit:

Du wirst TRUE oder true (aus stdbool.h) nicht anders als 1 definieren, 
um damit arbeiten zu können. Am besten lässt man es und schreibt direkt:
1
    if (a)

Dann muss man über TRUE oder true überhaupt nicht nachdenken.

: Bearbeitet durch Moderator
von Joachim B. (jar)


Lesenswert?

dann kann man ja auch gleich schreiben

if(a) denn alles !=0 ist wahr

upps steht ja schon

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Frank M. schrieb:
> #define TRUE  1    // jawohl, 1 und nichts anderes!
> #define FALSE 0

So z.B.:
#define FALSE 0
#define TRUE  (!FALSE) // ergibt 1 denn das ist so im Standard definiert

und

if (a != FALSE)

Ja, das != FALSE ist überflüssig und man sollte wissen, warum da kein == 
TRUE steht.

von O. A. (sokrates1989)


Lesenswert?

Frank M. schrieb:
> 0x04 ist binär:
>
>   0x04 = 00001000

Frank du meinst bestimmt 0x04 = 0000 0100?

von O. A. (sokrates1989)


Angehängte Dateien:

Lesenswert?

R. F. schrieb:
> i++;  erforderlich für Lauflicht?? Schaltplaninformation zufügen!!  */

Ich habe mal die Infos aus dem Buch hochgeladen.

von O. A. (sokrates1989)


Lesenswert?

Ich habe mal eine andere Frage.

Wie kann ich diesen Delay Code, mit einer Tasterabfrage wie in dem 
ersten Code am Anfang kombinieren?

Delay:
1
#include <avr/io.h>
2
#define F_CPU 1000000UL
3
#include <util/delay.h>
4
5
int main( void )
6
{
7
    DDRB |= (1 << PB0);
8
9
    while(1) {
10
        PORTB ^= (1 << PB0);
11
        _delay_ms(1000);
12
    }
13
    return 0;
14
}

Dieser Code bringt eine Led zum blinken. Wie könnte ich das aber per 
Taster starten?

D.h. ich drücke einen Taster und dann startet die LED zu blinken.

Ich habe es schon versucht, bekomme aber Fehler und Warnungen....

von O. A. (sokrates1989)


Lesenswert?

Habe einen einfacheren delay gefunden.
diesen kann ich wenigstens verstehen.

1
int main( void )
2
{
3
    DDRB = 0b000000001;    // Port B.0 als Ausgang
4
5
    while(1) 
6
    {
7
        PORTB = 0b00000001; _delay_ms(1000);
8
    PORTB = 0b00000000; _delay_ms(1000);
9
10
      }
11
    return 0;
12
  }

von Dirk B. (dirkb2)


Lesenswert?

Das delay ist ja noch dasselbe.

Was du nicht verstehst ist der Exclusiv-Oder-Operator ^ (das Zirkumflex)
Aber das sollte doch das Buch erklären

https://de.wikipedia.org/wiki/Bitweiser_Operator#XOR

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.