Forum: Mikrocontroller und Digitale Elektronik Ausgang auf "1" schalten, wenn Eingang auf "0" ist


von Susanne (Gast)


Lesenswert?

Hallo zusammen,

ich habe folgendes Problem:
Ich benutze einen ATMEga32

Nun würde ich gerne PB0 auf "1" setzen wenn der Eingang PC6 auf "0" 
geht.
Mein Programmcode sieht wie folgt aus:

#ifdef F_CPU
#undef F_CPU
#define F_CPU 8000000UL
#endif


#include <avr/io.h>
#include <util/delay.h>

int main(void){
    DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang
    DDRB &= ~(1 << PC6);      // damit ist dann PB1 ein Eingang

    while(1){

      if(!(PINC & (1 << PINC6)))
      {
        PORTB |= (1 << PB0);  //PB0 im PORTB setzen
        delay_ms(250);       //250ms warten
      }

    }

    return 0;
}


kann mir jemand sagen, was ich falsch mache?

vielen Dank

von Michael B. (laberkopp)


Lesenswert?

Susanne schrieb:
> DDRB &= ~(1 << PC6);      // damit ist dann PB1 ein Eingang

Nein, Pin 6 und das auch noch von PortB

Susanne schrieb:
> if(!(PINC & (1 << PINC6)))

PINC6 ist schon geschoben
pub const PINC6: u8 = 1 << 6

Susanne schrieb:
> PORTB |= (1 << PB0);  //PB0 im PORTB setzen

Und wann willst du ihn wieder ausschalten ?

Susanne schrieb:
> kann mir jemand sagen, was ich falsch mache?

So ziemlich alles. Keine Aufmerksamkeit.

von TestX (Gast)


Lesenswert?

fehlt da vlt ein else ?

und wie sieht es mit der eingansbeschaltung aus ? schaltplan?

von Philipp G. (geiserp01)


Lesenswert?

Susanne schrieb:
> PORTB |= (1 << PB0);  //PB0 im PORTB setzen
>         delay_ms(250);       //250ms warten

mach es so:


PORTB ^= (1 << PB0);
delay_ms(250);

von Jörg B. (jbernau)


Lesenswert?

Philipp G. schrieb:
> PORTB ^= (1 << PB0);
> delay_ms(250);

@Susanne: Ich möchte das nur unterstützen. Das ist der Klassiker, wenn 
ein Pin "wackeln" soll. Es lohnt sich also das sich zu merken :-)

VG Jörg

von Dietrich L. (dietrichl)


Lesenswert?

Philipp G. schrieb:
> PORTB ^= (1 << PB0);
> delay_ms(250);

Das toogelt den Ausgang. Das ist aber nicht das, was Susanne will:

Susanne schrieb:
> Nun würde ich gerne PB0 auf "1" setzen wenn der Eingang PC6 auf "0"
> geht.

Allerdings hat sie nicht geschrieben, was bei PC6="1" passieren soll, 
also ob
- PC6 den Eingang PB0 invertiert abbilden oder
- PB0 beim ersten Auftreten von PC6="0" auf "1" gehen und dann so 
bleiben soll.

von Susanne (Gast)


Lesenswert?

Eine "else" brauch ich hier nicht unbedingt.
Es soll ja nur ein Testprogramm sein.

Will ja nur, dass Wenn am Pin 28 ein "0" Signal anliegt. Pin 1 auf "1" 
geht.

#ifdef F_CPU
#undef F_CPU
#define F_CPU 8000000UL
#endif


#include <avr/io.h>
#include <util/delay.h>

int main(void){
    DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang
    DDRC &= ~(1 << PC6);      // damit ist dann PC6 ein Eingang

    while(1)
    {
      if(PINC & (1 << PINC6)) // Wenn am Port C Pin 6 = "1" ist, wird 
PB0 gesetzt
      {
        PORTB |= (1 << PB0);  //PB0 im PORTB setzen
      }
    }
    return 0;
}

von Jörg B. (jbernau)


Lesenswert?

... ok für Menschen mit wenig Abstraktionsvermögen:

        PORTB ^= ( PINC & (1 << PINC6) );

Mit "( PINC & (1 << PINC6) )" wird das sechste Bit extrahiert und dann 
mit "PORTB ^= [...]" EXOR zugewiesen.

VG

Jörg

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Susanne schrieb:
> Eine "else" brauch ich hier nicht unbedingt.
> Es soll ja nur ein Testprogramm sein.
>
> Will ja nur, dass Wenn am Pin 28 ein "0" Signal anliegt. Pin 1 auf "1"
> geht.

Wechsel mal nicht dauernd die Bezeichnungen. Die physikalischen 
Pinnummern deines Gehäuses sind was anderes als die logischen Pinnamen.

> int main(void){
>     DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang
>     DDRC &= ~(1 << PC6);      // damit ist dann PC6 ein Eingang

Stimmt.

>
>     while(1)
>     {
>       if(PINC & (1 << PINC6)) // Wenn am Port C Pin 6 = "1" ist, wird
> PB0 gesetzt

Das ist aber was anderes, als du in deinem 1. Betriag geschrieben hast? 
Ja was denn nun?

"Nun würde ich gerne PB0 auf "1" setzen wenn der Eingang PC6 auf "0"
geht."

Ansonsten ist das eher trivial, siehe Bitmanipulation.

von Einer K. (Gast)


Lesenswert?

Michael B. schrieb:
> PINC6 ist schon geschoben
> pub const PINC6: u8 = 1 << 6

Da biste aber im falschen Film!
Irgendwo, wo es keinen AVR-GCC und die üblichen *.h Dateien für die 
Atmels gibt.

von Jörg B. (jbernau)


Lesenswert?

Jörg B. schrieb:
> "PORTB ^= [...]" EXOR zugewiesen.

Ich vergass: Abschreiben gilt nicht.

@Susanne: Du scheinst am Lernen zu sein. Deshalb habe ich dir die Lösung 
nicht explizit verraten. Hinweis: Das Shiften fehlt noch...

VG Jörg

von HildeK (Gast)


Lesenswert?

Michael B. schrieb:
> Susanne schrieb:
>> if(!(PINC & (1 << PINC6)))
>
> PINC6 ist schon geschoben
> pub const PINC6: u8 = 1 << 6

Imho ist PINC6 nicht geschoben. Das findet man in den *.h-Files:
1
#define PINC _SFR_IO8(0x06)
2
#define PINC0 0
3
#define PINC1 1
4
#define PINC2 2
5
#define PINC3 3
6
#define PINC4 4
7
#define PINC5 5
8
#define PINC6 6
9
#define PINC7 7
Wo hast du deine Info her?

von Dominik (Gast)


Lesenswert?

Hallo Susanne,

womit setzt du den PINC6 denn auf 0? Mit einem Taster?
Dann am Besten mit einem Pullup den Pin gegen Vcc ziehen und mit dem 
Taster gegen Masse!
Dann hast du schon mal einen definierten Eingangszustand!

Den Rest kannst du dir hier mal anschauen:
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Zugriff_auf_IO-Ports

Ansonsten:
Was genau funktioniert denn nicht?

von Michael B. (laberkopp)


Lesenswert?


von Jörg B. (jbernau)


Lesenswert?

Hallo HildeK,

du weist schon, dass man für das Arduino Framework die Arduino.h 
incluidiert und nicht die avr/io.h? Letzteres ist namlich die avr-libc.

VB

Jörg

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Michael B. schrieb:
> HildeK schrieb:
>> Wo hast du deine Info her
>
> https://docs.rs/arduino/0.1.0/arduino/constant.PINC6.html
Wir sind hier in C, oder C++ ... nix Rust.
Also falsche Baustelle.


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



Jörg B. schrieb:
> du weist schon, dass man für das Arduino Framework die Arduino.h
> incluidiert
Richtig!
bzw. passiert das meist automatisch

Jörg B. schrieb:
> und nicht die avr/io.h?
Falsch!
In der Arduino.h wird die  avr/io.h eingebunden.

Also Gesamtmaussage leider falsch.

Jörg B. schrieb:
> Letzteres ist namlich die avr-libc.
Die AVR-LIBC steht vollumfänglich in Arduino bereit.
Wird intensiv genutzt.
(natürlich nur für die AVRs)

von Jörg B. (jbernau)


Lesenswert?

Du hast sicherlich recht, aber die TOin hat laut ihrem Quellcode die 
AVR-Libc verwendet. Das ist meine Aussage, die ich machen wollte.

VG

Jörg

von Einer K. (Gast)


Lesenswert?

Und damit hast du wiederum recht.
Dann ist allerdings deine Kritik an Hilde k. auch hinfällig, denn der 
hat in dem Punkt ebenso recht.

von Route_66 H. (route_66)


Lesenswert?

Jörg B. schrieb:
> die TOin hat laut ihrem Quellcode die

laut ihres Quellcodes

->Bastian Sick

von Jörg B. (jbernau)


Lesenswert?

Route 6. schrieb:
> Jörg B. schrieb:
>> die TOin hat laut ihrem Quellcode die
>
> laut ihres Quellcodes

Gibt es den Genitiv noch? Ich dachte er wäre faktisch abgeschafft ;-P

VG  Jörg

von konrad duden (Gast)


Lesenswert?

Route 6. schrieb:
> Jörg B. schrieb:
>> die TOin hat laut ihrem Quellcode die
>
> laut ihres Quellcodes

Dativ ist hier laut Duden korrekt. Genitiv ist möglich.

von HildeK (Gast)


Lesenswert?

Arduino wurde vor meinem Post nicht erwähnt - nur im Namen vom Arduino 
Fanboy :-).
Wenn es um Arduino geht, halte ich mich raus.

von Einer K. (Gast)


Lesenswert?

HildeK schrieb:
> Wenn es um Arduino geht, ....
Geht es offensichtlich nicht.

Es ist der  Michael B. gewesen, welcher (versehentlich) Rust für Arduino 
ins Spiel gebracht hat.

von M. Н. (Gast)


Lesenswert?

Susanne schrieb:
> #include <avr/io.h>
> #include <util/delay.h>
>
> int main(void){
>     DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang
>     DDRC &= ~(1 << PC6);      // damit ist dann PC6 ein Eingang
>
>     while(1)
>     {
>       if(PINC & (1 << PINC6)) // Wenn am Port C Pin 6 = "1" ist, wird
> PB0 gesetzt
>       {
>         PORTB |= (1 << PB0);  //PB0 im PORTB setzen
>       }
>     }
>     return 0;
> }


Dieser Code setzt, wie korrekt im Kommentar steht, PB0, wenn PINC6 auf 1 
ist.
Also genau das umgedrehte verhalten. Der Pin wird allerdings nie mehr 
zurückgesetzt.

Susanne schrieb:
> #ifdef F_CPU
> #undef F_CPU
> #define F_CPU 8000000UL
> #endif

Das ist auch komisch. Wenn F_CPU gesetzt ist, wird es überschrieben. 
Wenn es nicht gesetzt ist, passiert nichts.

von Susanne (Gast)


Lesenswert?

Habe den Programmcode angepasst.
funktioniert leider immer noch nicht.

kann mir jemand sagen, was ich genau falsch mache?
eventuell Berichtigen, bekomme es alleine nicht hin :-(

#define F_CPU 8000000UL



#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang
    DDRC &= ~(1 << PC6);      // damit ist dann PC6 ein Eingang

    while(1)
    {
        if(PINC & (0 << PINC6)) // Wenn am Port C Pin 6 = "0" ist, wird 
PB0 gesetzt
        {
            PORTB |= (1 << PB0);  //PB0 im PORTB setzen
        }
    }
     return 0;
}

von Michael B. (laberkopp)


Lesenswert?

Susanne schrieb:
> kann mir jemand sagen, was ich genau falsch mache?

Was meinst du, was aus einer 0 wird, wenn man sie 5 Stellen nach links 
schiebt ?

: Bearbeitet durch User
von HildeK (Gast)


Lesenswert?

Susanne schrieb:
> if(PINC & (0 << PINC6))

Überlege mal, was passiert, wenn du in eine temporäre Variable eine 0 
schreibst und die nach links schiebst?

von Susanne (Gast)


Lesenswert?

sorry bin blutige Anfängerin.
meinst du in der If Anweisung oder bei der Initalisierung?

von Susanne (Gast)


Lesenswert?

Kann mir es jemand berichtigen, damit ich es vergleichen kann. Weiß 
absolut nicht wie es funktioniert.
Wenn ihr gute links wisst gerne senden :-)

von Einer K. (Gast)


Lesenswert?

if(!(PINC & (1 << PINC6))) // Ausdruck wird true, wenn der Pin low ist

von HildeK (Gast)


Lesenswert?

Susanne schrieb:
> meinst du in der If Anweisung oder bei der Initalisierung?
Schon in der if-Anweisung.
Dieser Befehl
> if(PINC & (0 << PINC6))
macht folgendes:
- in ein temporäres Register wird eine Null hineingeschrieben
- diese Null wird dann um den Wert von PINC6, also um 6 Stellen nach 
links geschoben.
- was bleibt: Null!
- UND-Verknüpfung einer Null mit irgendwas bleibt Null. Die if-Abfrage 
ist immer falsch. Wobei es mit PORTC verknüpft werden muss!

Der Befehl müsste lauten:
if ( !(PORTC & (1<<PINC6)))
Da passiert dann:
- in ein temporäres Register wird eine Eins hineingeschrieben
- diese Eins wird um 6 Stellen nach links geschoben
- es steht dann drin 0b01000000
- und das wird UND-Verknüpft mit dem PORTC ergibt dann eine Eins, wenn 
der Pin C8 HIGH ist. Deshalb die Invertierung ("!") bei der Abfrage, 
'if' also dann wahr, wenn der Pin Null ist.

Andernfalls: es gibt hier im Forum das AVR-GCC-Tutorial. Das sagt dir 
alles!

von HildeK (Gast)


Lesenswert?

HildeK schrieb:
> Wobei es mit PORTC verknüpft werden muss!
>
> Der Befehl müsste lauten:
> if ( !(PORTC & (1<<PINC6)))

Mal wieder irren lassen: es muss doch PINC statt PORTC heißen.
Also:
if ( !(PINC & (1<<PINC6)))

von Susanne (Gast)


Lesenswert?

ok, ich hätte nun gedacht, dass wenn ich den Taster drücke, dass dann 
der Ausgang auf "1" geht, wenn ich den Taster wieder los lassen, dann 
geht der Ausgang wieder auf "0".
Leider funktioniert dies nicht.
Es hat keinen wechsel zur folgen wenn ich den Taster drücke:

#define F_CPU 8000000UL



#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  DDRC &= (1 << PC6);       // damit ist dann PC6 ein Eingang
  DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang


    while(1)
    {
      if ( !(PORTC & (1<<PINC6))) // Wenn am Port C Pin 6 = "0" ist, 
wird PB0 gesetzt
        {
        PORTB |= (1 << PB0);  //PB0 High
        }
      else
    {
        PORTB &= ~(1 << PB0); //PB0 Low
    }
    }
     return 0;
}

von Max B. (citgo)


Lesenswert?

Ich frage nochmal:
Wie sieht dein Aufbau aus?
Wie hast du deinen Taster angeklemmt?

von quengel (Gast)


Lesenswert?

Susanne schrieb:
>   DDRC &= (1 << PC6);       // damit ist dann PC6 ein Eingang

Da stimmt was nicht. Geht zufällig trotzdem.

>       if ( !(PORTC & (1<<PINC6))) // Wenn am Port C Pin 6 = "0" ist,
> wird PB0 gesetzt

Am Eingang muß PINC Register und nicht PORTC abgefragt werden.

von Hubert G. (hubertg)


Lesenswert?

Unter der Voraussetzung das du den Taster nach GND geschaltet hast, 
fehlt im main noch ein
PORTC |= (1<<PC6);
um den internen PullUp zu aktivieren.

von Hubert G. (hubertg)


Lesenswert?

quengel schrieb:
> Susanne schrieb:
>>   DDRC &= (1 << PC6);       // damit ist dann PC6 ein Eingang
>
> Da stimmt was nicht. Geht zufällig trotzdem.

Sollte doch so sein
DDRC &= ~(1 << PC6);

und das sollte so sein
if ( !(PINC & (1<<PINC6)))

Vielleicht hier mal nachsehen:
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial

: Bearbeitet durch User
von Thomas E. (thomase)


Lesenswert?

Susanne schrieb:
> DDRC &= (1 << PC6);       // damit ist dann PC6 ein Eingang

Ist falsch und sinnlos. Funktioniert nur, weil DDRC6 sowieso 0 ist.
1
DDRC &= ~(1 << 6);

wäre richtig. Ist aber unnötig, da der Port sowieso auf Eingang steht.

Wie ist der Taster angeschlossen? Wahrscheinlich wie 99,99% aller Taster 
gegen GND. Deshalb: Wo ist der PullUp? Ohne Pullup kannst du darauf 
rumdrücken bis du schwarz wirst.
1
PORTC |= (1 << 6);  //Pullup ein


Susanne schrieb:
> if ( !(PORTC & (1<<PINC6)))

Ist falsch. Es muß:
1
if ( !(PINC & (1 << 6)))

heissen. Das war ursprünglich aber schon mal richtig.

von HildeK (Gast)


Lesenswert?

Thomas E. schrieb:
> Ist falsch. Es muß:
> if ( !(PINC & (1 << 6)))
>
> heissen. Das war ursprünglich aber schon mal richtig.

Ja.
Sorry, das habe ich hier durcheinander gebracht.

von Andreas (Gast)


Lesenswert?

Hab mir gerade den Thread von Susanne angeschaut.
Da ich auch Anfänger bin, wäre ich für eine kleine Hilfe sehr Dankbar.

Meines erachtes müsste dies so heißen:
wenn am PINC6 eine "0" anliegt, dann schaltet der Ausgang PB0 und PB1 
auf "1"

sehe ich das richtig?

#define F_CPU 8000000UL


#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang
    DDRB |= (1 << PB1);       // damit ist dann PB1 ein Ausgang
    DDRB &= ~(1 << PINC6);      // damit ist dann PINC6 ein Eingang

    while(1)
    {
        if(!(PINC & (1<<PINC6)))
        {
            PORTB |= (1 << PB0);  //PB0 im PORTB setzen
            PORTB |= (1 << PB1);  //PB0 im PORTB setzen
        }
        else
        {
          PORTB |= (0 << PB0);  //PB0 im PORTB setzen
          PORTB |= (0 << PB1);  //PB0 im PORTB setzen
        }
    }
    return 0;
}

von Sebastian R. (sebastian_r569)


Lesenswert?

Abgesehen davon, dass das mit dem Ausschalten nicht klappt, weil 1 OR 0 
immer noch 1 ist.

Zum Bit löschen braucht es PORTx &= ~(1<<Pxn);

von Andreas (Gast)


Lesenswert?

also so:

#ifdef F_CPU
#undef F_CPU
#define F_CPU 8000000UL
#endif


#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang
    DDRB |= (1 << PB1);       // damit ist dann PB1 ein Ausgang
    DDRB &= ~(1 << PINC6);      // damit ist dann PINC6 ein Eingang

    while(1)
    {
        if(!(PORTC &= ~(1<<PINC6)))
        {
            PORTB |= (1 << PB0);  //PB0 im PORTB setzen
            PORTB |= (1 << PB1);  //PB0 im PORTB setzen
        }
        else
        {
          PORTB |= (0 << PB0);  //PB0 im PORTB setzen
          PORTB |= (0 << PB1);  //PB0 im PORTB setzen
        }
    }
    return 0;
}

von quengel (Gast)


Lesenswert?

Andreas schrieb:
>         if(!(PORTC &= ~(1<<PINC6)))

Ohne Worte

von Andreas (Gast)


Lesenswert?

Sorry, ich bin 12 und würde mir gerne die Basics aneignen.
Ich brauch einfach ein paar Beispiele, damit ich das nachvollziehen und 
auch nacharbeiten kann!

von Andreas (Gast)


Lesenswert?

quengel schrieb:
> Andreas schrieb:
>>         if(!(PORTC &= ~(1<<PINC6)))
>
> Ohne Worte

was bedeutet das jetzt? Ist es nun richtig oder falsch?

von Sebastian R. (sebastian_r569)


Lesenswert?

Dass es falsch ist.

Deine if-Bedingung war schon richtig. Nur eben die Stelle, an der du die 
LEDs wieder ausschalten möchtest (Bits im Register löschen) ist falsch 
und muss durch meine Variante ausgetauscht werden.

Weil |= beinhaltet unter anderem eine logische Oder-Operation. Und wenn 
das Bit schon gesetzt ist, kann man es durch Oder nicht wieder auf null 
bringen.

von quengel (Gast)


Lesenswert?

Andreas schrieb:
> quengel schrieb:
>> Andreas schrieb:
>>>         if(!(PORTC &= ~(1<<PINC6)))
>>
>> Ohne Worte
>
> was bedeutet das jetzt? Ist es nun richtig oder falsch?

Ist nicht richtig. Der Pin 6 auf Portc ist als Eingang konfiguriert und 
du möchtest doch wissen, wie der Pegel auf dem Eingang ist. Um das 
festzustellen, mußt du das PINC und nicht das PORTC Register abfragen. 
Das war schon mal weiter oben richtig.

von Sebastian R. (sebastian_r569)


Lesenswert?

PORTB |= (1 << PB0);
Entspricht: PORTB = PORTB oder 0b00000001.

Ist das letzte Bit in PORTB eine Null, dann ergibt 0 oder 1 eine 1. Also 
wird die LED eingeschaltet.


PORTB |= (0 << PB0);
Entspricht: PORTB = PORTB oder 0b00000000.

Wenn das Bit in PORTB schon gesetzt ist, dann ist die Operation 1 oder 
0. Was immer noch 1 ist, also bleibt die LED an.

PORTB &= ~(1<<PB0)
Entspricht: PORTB = PORTB und 0b11111110.

1 und 1 = 1, 0 und 1 = 0, 0 und 0 = 0.

Damit behalten andere 0 und 1 in dem Register ihren Wert und nur PB0 
wird durch "1 und 0" auf 0 gesetzt.

: Bearbeitet durch User
von HildeK (Gast)


Lesenswert?

Andreas schrieb:
> if(!(PORTC &= ~(1<<PINC6)))
       ^
 muss PINC heißen (da hatte ich oben was falsches behauptet, aber 
korrigiert).
>         {
>             PORTB |= (1 << PB0);  //PB0 im PORTB setzen
>             PORTB |= (1 << PB1);  //PB0 im PORTB setzen
                                    //PB1 ....
>         }
ok, bis auf Kommentar :-)
>         else
>         {
>           PORTB |= (0 << PB0);  //PB0 im PORTB setzen
            PORTB &= ~(1<<PB0);
>           PORTB |= (0 << PB1);  //PB0 im PORTB setzen
            PORTB &= ~(1<<PB1);       ^
                                  //PB1
>         }

Du musst dir überlegen, was in der Operation
   PORTB |= (0 << PB1);
passiert und damit herausfinden, warum es so nicht geht.

PB1 ist eine Defnition und steht für die Zahl 1.
Deine Anweisung nimmt also 0b00000000 und schiebt sie um eine Stelle 
nach links. Bleibt Null.
Im if-Zweig hatte der Befehl PORTB |= (1<<PB1) das IO-Register mit dem 
Wert 0b00000010 gefüllt.
Jetzt machst du eine bitweise ODER-Verknüpfung von PORTB=0b00000010 mit 
0b00000000. Das ändert aber nichts!
Deshalb kann man so keine Null an eine bestimmte Stelle schreiben!

Was muss passiern:
Du hast also in PORTB 0b00000010 stehen.
(1<<PB1) ist immer noch 0b00000010 und ~(1<<PB1) ergibt 0b11111101.
Jetzt erfolgt eine bitweise UND-Verknüpfung von PORTB und 0b11111101.
Durch die eine Null wird exakt diese Stelle zu Null, die Einsen lassen 
das, was vorher in PORTB stand, unverändert. In dem Fall trivial, aber 
es hätten  noch andere Ausgänge gesetzt gewesen sein können, je nach 
Programm.
Würde also aus eine vorherigen Operation PORTB = 0b01100011 sein, dann 
wird es nach dem Befehl PORTB &= ~(1<<PB1)zu PORTB = 0b01100001 werden.

von Andreas (Gast)


Lesenswert?

Ich gebe es auf:

nach meinem Verständnis ist es nun so:
liegt am Eingang PINC6 = 0 (! = Negation)
wird der Ausgang PB0 und PB1 auf 1 gesetzt.

liegt dagegen eine "1" am PINC6 wird der Ausgang PB0 auf "0" gesetzt

es geht aber nicht.

kann mir bitte jemand den code so berichtigen, dass es klappt, würde es 
dann gerne nachvollziehen können. alles andere frustiriert gerade :-(


#define F_CPU 8000000UL

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB |= (1 << PB0);       // damit ist dann PB0 ein Ausgang
    DDRB |= (1 << PB1);       // damit ist dann PB1 ein Ausgang
    DDRB &= ~(1 << PC6);      // damit ist dann PINC6 ein Eingang

    while(1)
    {
      if(!(PORTC &= ~(1<<PINC6)))
        {
        PORTB &= ~(1<<PB0);  //PB0 im PORTB setzen
        }
      else
      {
        PORTB &= ~(0<<PB0);  //PB0 im PORTB setzen
      }
    }
    return 0;
}

von Sebastian R. (sebastian_r569)


Lesenswert?

Und schon wieder übers Ziel hinaus geschossen...
1
if(!(PINC & (1<<PINC6)))
2
        {
3
          PORTB |= (1 << PB0);  //PB0 im PORTB setzen
4
        }
5
        else
6
        {
7
          PORTB &= ~(1 << PB0);  //PB0 im PORTB löschen
8
        }

: Bearbeitet durch User
von Effektiver (Gast)


Lesenswert?

Klasse. 50 Mann bemühen sich seit 8 Tagen, in C ein Programm zu 
schreiben, was ein invertiertes Eingangssignal an einem anderen Portpin 
ausgibt.

Das nenne ich eine effektive Programmiersprache.

von Einer K. (Gast)


Lesenswert?

Andreas schrieb:
> nach meinem Verständnis ist es nun so:
> liegt am Eingang PINC6 = 0 (! = Negation)
So ist es aber nicht.
Du prüfst das falsche Register!

Andreas schrieb:
> if(!(PORTC &= ~(1<<PINC6)))

Du möchtest PINC6 prüfen.
Prüfst aber in Wirklichkeit den Zustand von PORTC6
Das bringt dich aber nicht zum Ziel.

Andreas schrieb:
> wird der Ausgang PB0 und PB1 auf 1 gesetzt.
PB0 sehe ich, PB1 nicht

1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <util/delay.h>
5
6
int main(void)
7
{
8
    DDRB |= (1 << DDB0)|(1 << DDB1);       // damit ist dann PB0 und PB1 ein Ausgang
9
    DDRC &= ~(1 << PC6);      // damit ist dann PINC6 ein Eingang
10
11
    while(1)
12
    {
13
      if(!(PINC &= ~(1<<PINC6))) // teste Eingang auf Low
14
        {
15
        PORTB |= (1<<PORTB0)|(1<<PORTB1);  //PB0 und PB1 im PORTB setzen
16
        }
17
      else
18
      {
19
        PORTB &= ~((1<<PORTB0)|(1<<PORTB1));  //PB0 und PB1 im PORTB löschen
20
      }
21
    }
22
    return 0;
23
}

von MaWin (Gast)


Lesenswert?

Susanne schrieb:
> ok, ich hätte nun gedacht, dass wenn ich den Taster drücke, dass dann
> der Ausgang auf "1" geht, wenn ich den Taster wieder los lassen, dann
> geht der Ausgang wieder auf "0".

Nein, es wurde bereits ganz zu Beginn erwähnt, dass in deinem code 
vergessen wurde ihn wieder auszuschalten.

Andreas schrieb:
> Meines erachtes müsste dies so heißen:
> wenn am PINC6 eine "0" anliegt, dann schaltet der Ausgang PB0 und PB1
> auf "1"

Hier gibt es wenigstens code zum Ausschalten, aber er ist falsch. Es 
wurde weit vorher schon erwähnt, dass es nichts bringt, eine 0 zu 
schieben.

Arduino wäre einfacher gewesen.

von Sebastian R. (sebastian_r569)


Lesenswert?

Effektiver schrieb:
> Das nenne ich eine effektive Programmiersprache.

Was kann eine Sprache dafür, wenn ein Anwender sie nicht versteht?

von Einer K. (Gast)


Lesenswert?

Hach... da habe ich auch wieder eine kleine Unsauberkeit eingebaut....
(funktioniert aber trotzdem)

Arduino Fanboy D. schrieb:
> DDRC &= ~(1 << PC6);      // damit ist dann PINC6 ein Eingang

Besser/korrekter:
>  DDRC &= ~(1 << DDC6);

von HildeK (Gast)


Lesenswert?

Effektiver schrieb:
> Klasse. 50 Mann bemühen sich seit 8 Tagen, in C ein Programm zu
> schreiben, was ein invertiertes Eingangssignal an einem anderen Portpin
> ausgibt.
>
> Das nenne ich eine effektive Programmiersprache.

Das hat gar nichts mit der Programmiersprache zu tun, nur mit der 
Unfähigkeit von (mehreren) Fragenden das umzusetzen, was mehrfach 
ausführlich und korrekt geantwortet wurde. Immerhin scheint Susanne seit 
Sonntag zufrieden zu sein, es ist Andreas, der das selbe nochmals.

Da kommt dann nach rund 50 Antworten in drei Zeilen Code noch immer drei 
Fehler, siehe:
1
    while(1)
2
    {
3
      if(!(PORTC &= ~(1<<PINC6)))  // FALSCH ist PORTC, richtig wäre PINC
4
        {
5
        PORTB &= ~(1<<PB0);  //PB0 im PORTB setzen //FALSCH: hier wird rückgesetzt, richtig wäre '|= (1<<PB0)'
6
        }
7
      else
8
      {
9
        PORTB &= ~(0<<PB0);  //PB0 im PORTB setzen // FALSCH ist (0<<PB0), weil wirkungslos, richtig wäre '(1<<PB0)'
10
      }
11
    }
Andreas, vergleich einfach mal den nächsten Block mit deinem Code:
1
    while(1)
2
    {
3
      if(!(PINC &= ~(1<<PINC6))) // der erste Fehler: muss PINC sein!
4
        {
5
        // zweiter Fehler: Setzen tut man mit dem Kommando
6
        PORTB |= (1<<PB0);  //PB0 im PORTB setzen
7
        }
8
      else
9
      {
10
        // dritter Fehler: '0' schieben nützt nichts und du willst eigentlich rücksezten
11
        PORTB &= ~(1<<PB0);  //PB0 im PORTB rücksetzen 
12
      }
13
    }

von FleiLeikAnIgel (Gast)


Lesenswert?

Sebastian R. schrieb:
> Effektiver schrieb:
>> Das nenne ich eine effektive Programmiersprache.
>
> Was kann eine Sprache dafür, wenn ein Anwender sie nicht versteht?

Wenn EIN Anwender sie nicht versteht, dann liegt das wahrscheinlich an 
dem einen Anwender. Wenn aber 49 von 50 Anwendern diese Sprache nicht 
verstehen, dann liegt es sicher nicht an all diesen.

von Arno (Gast)


Lesenswert?

HildeK schrieb:
1
> if(!(PINC &= ~(1<<PINC6))) // der erste Fehler: muss PINC sein!
2
            ^^ vierter Fehler

Das ist gleichzeitig der einzige Fehler, zu dem ich C eine kleine 
Teilschuld geben würde - eine strenger typisierte Sprache könnte hier 
einen Programmierfehler erkennen. Müsste dann aber auch ein
1
if( (PINC & (1<<PINC6) )

verbieten.

Die anderen drei Fehler sind dagegen wahrscheinlich typische "erst 
kopieren dann kapieren"-Fehler - ohne irgendeine Ahnung davon, was PINC, 
PORTC, PINC6, PB0 und die verschiedenen Operatoren bedeuten, einfach mal 
irgendwas irgendwoher kopiert und leicht geändert und dann gewundert, 
dass es nicht funktioniert.

Solche Fehler kann keine Programmiersprache auffangen.

MfG, Arno

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.