Pin an PortC

Gast #181169
Lesenswert?

int main(void) {

  DDRB = (1 << DDB1) | (1 << DDB2) | (1 << DDB3);

  DDRC = (1 << DDC0) | (1 << DDC1) | (1 << DDC2);

  PORTC |= (1<<PC2);
...

Natürlich wird er erreicht.
Interrupts gibt's im Programm keine und die Beschaltung habe ich auch
schon überprüft :-(
Gast #181173
Lesenswert?

Nein, die Fusebits haben keinen Einfluss auf den ADC.  Da du an den
ADC-Registern nichts getan hast, ist das auch alles erstmal
abgeklemmt.

Wenn wirklich das von dir genannte Einfachst-Progrämmchen das nicht
tut (und nicht gerade deine externe Hardware einen Kurzschluss am
Portpin hat ;-), dann ist dein Controller breit.
Gast #181175
Lesenswert?

Hallo,

ich habe genau das gleiche Problem.
Wenn ich allerdings nachdem setzen des Pins eine Warteschleife aufrufe,
ist der Pin solage gesetzt, wie diese Schleife braucht.

Kann diese Verhalten bei verschiedenen Pins nachvollziehen und bin echt
verzweifelt. Es ist als ob er vergessen würde die Spannung am Pin zu
halten, da er was anderes zu tun bekommt.

mfg
Alex
Gast #181177
Lesenswert?

Hallo,

das Problem an der Sache ist allerings, dass er davor und danach
weitermacht als ob es den Befehl "Pin auf HIGH" nie gegeben hätte.
Endlosschleife ist natürlic drin. Was wär das denn sonst für n
sinnloses Programm??

mfg
Alex
Gast #181178
Lesenswert?

Leider bin ich noch ablosluter Anfänger in C...
Doch gestern hatte ich ein ähnliches Problem. So wie es aussieht willst
Du ja den dritten Pin an Port C (PC2) auf high setzen, oder?

PORTC |= (1<<PC2);

Ich bin mir jetzt leider nicht mehr sicher ob es so funktioniert, da
ich meinen Code nicht hier habe. Aber ein versuch ist es Wert...
(oder die Profis fangen zum schimpfen an... :-))

PORTC |= (4<<PC2);
(der 3. Pin wird mit einer binären 4 auf high gesetzt)
Gast #181179
Lesenswert?

Das funktioniert bei mir:

#include "stdafx.h"

#define PC2 1

int main(void)
{
  char portc = 0;
  portc |= (2 << PC2); // Die 2 setzt die Bitposition des PORTC fest
  printf("\nportc = %X\r\n", portc);
  return 0;
}

Ich habe das kleine Program soeben in MS C++ getestet und funktioniert.
PORTC wird als 4 ausgegeben.

Gruss,
Gerhard
Gast #181181
Lesenswert?

> PORTC |= (4<<PC2);
Pfui ;-)

PORTC |= (1<<PC2); ist schon richtig, wenn PC2 den Wert 2 hat. Damit
wird die "1" (die links in "1<<PC2" steht) um 2 (Binär-)Stellen (da
PC2 den Wert 2 hat) nach links geschoben. Damit ergibt wird dann aus
(1<<PC2) -> die Zahl 0b00000100 =0x04 =4dez. Das wird dann auf PORTC
verodert und schon passt das.

> portc |= (2 << PC2); // Die 2 setzt die Bitposition des PORTC fest
Riesenzufall! Dein 'Prinzip' funktioniert so aber wirklich nur für
PC4 - nicht bei anderen Bitpositionen. Und wieso schreibst du PC2 in
den Sourcecode obwohl du PC4 setzen willst? Unlogisch. Wie das richtig
geht, siehe Erklärung oben.

> Aber vielleicht fängst Du ja nicht bei PC0 sondern bei PC1 zum zählen
an...
Das, oder er hat AGND und/oder Aref nicht angeschlossen?!? Anschluss
von AVCC hat ja oben schon bestätigt.

----, (QuadDash).
Gast #181182
Lesenswert?

Ich zitiere mich mal selbst:
> Und wieso schreibst du PC2 in den Sourcecode obwohl du PC4 setzen
willst?

Ich habe erst eben gesehen, daß du noch was ganz seltsames defined
hast:
> #define PC2 1
damit setzt du PortC auf 0x04 (wie du schreibst), nicht PORTC4 auf 1
(wie ich fälschlicherweise annahm). Aber das ist ja genauso verbockt
und führt nur zu Problemen, da dein Konzept nicht durchgängig
konsistent ist. (z.B. Wie würdest du PC0 auf 1 setzen?). Also lieber
die 'mitgelieferten' PCn defines belassen.
Aber wenn du von PortC nur das Bit2 (=PC2) setzen willst, dann kannst
du auch gleich PORTC|=0x04; schreiben, dann hat sich die Bitschieberei
sowieso erledigt.
Das Bitschieben hat sich doch nur eingebürgert, da es leichter zu lesen
ist, da ja der PinName drin vorkommt und man nicht weiter nachdenken
muß.

----, (QuadDash).
Gast #181183
Lesenswert?

Jetzt sehe ich meinen Fehler - Danke!. Da habe ich aber sehr  blamiert!
PCx bestimmt die Bitposition, wo x dann zwischen 0 und 7 legen darf. so
muesste es gehen:

PORTC |= (1 << Portbitnummer);
Ruecksetzen
PORTC &= (1 << ~Portbitnummer);

Ich setze meine Bits sonst auch wie bei Dir genannt: PORTC |= 0x04;
oder ruecksetzen PORTC &= ~0x04; . Ich mag das Bitschieben auch nicht.
Gruss,
Gerhard
Gast #181184
Lesenswert?

Schon fast gut.
Beim Rücksetzen noch die Tilde an die richtige Stelle:
PORTC &= ~(1 << Portbitnummer);

Beispiel: Portbitnummer = 4:
 (1 << Portbitnummer)  entspricht dann 0x10 hex oder 00010000 binär
~(1 << Portbitnummer)  entspricht dann 0xEF hex oder 11101111 binär
Im PORTC wird durch das &= also Bit 4 gelöscht, alle anderen behalten
den alten Wert.

Ich benutze übrigens lieber das Makro _BV() (Bit-Value), das sieht dann
nicht so kryptisch aus.

Falls Du doch lieber den direkten Weg nehmen willst, also:
PORTC |= 0x04;
dann ersetze 0x04 möglichst durch
#define Portbitmaske 0x04  // nur 1* machen, am Besten in einem.h-File
PORTC |= Portbitmaske;

oder besser (Bsp. zum Setzen einer LED):
#define Ledbitmaske 0x04
#define Ledport     PORTC
Ledport |= Ledbitmaske;

Falls Du jemals eine Änderung in Deiner Hardware hast, dann ist die
Anpassung dann sehr einfach - nur an einer Stelle muss geändert
werden.

Viele Grüße, Stefan
Gast #181185
Lesenswert?

Na bevor ich "Ledport |= Ledbitmaske;" schreiben würde, würde ich eher
zu:
SetLed(n);
greifen. Wobei:
#define SetLed(x)     (x ? PORTC|=0x04 : PORTC&=~0x04)
ggf. die beiden Ausdrücke nochmal auflösen/definen...

Oder vom "Compilerhersteller" fordern, daß er Bitvariablen für
Portzugriffe bereitstellt... :-) Aber das hatten wir ja alles schon...
dann wärs nämlich nur:
#define SetLed(x)     (PORTC_PC1=x)
oder so ähnlich.

_BV() finde ich persönlich unschön, da ich das bisher nur bei
AVR-GCC-Code gesehen habe...
Aber wie immer im Leben... alles Geschmackssache.

----, (QuadDash).
Gast #181186
Lesenswert?

Hi,

nochmals vielen Dank zum Thema und der Richtigstellung meines letzten
Fehlers (Gebrauch der TILDE beim Ruecksetzen und Bitschieben). Zu
meiner Entschuldigung moechte ich bemerken, dass ich bis vor kurzem nur
mit dem PIC CCS Compiler gearbeitet habe, wo direkte Portoperationen
eingebaut sind.

Mann kann natuerlich wie beim AVR die PORTS aehnlich ansprechen wenn
man will. Folgend ist ein kurzes Beispiel vom CCS Compiler:

Um ein LED einzuschalten braucht man nur:

#use fast_io(b)
#define PORT_B_MASK  0b11111110  // 0=Output, 1=Input

#define LED PIN_RB0  // Led zwischen PIN_B0 und 5V angeschlossen
#define EIN 0
#define AUS 1

void main()
{
    set_tris_b(PORT_B_MASK);  // Port B Datenrichtungsspeicher

    // Beispiele einiger eingebauten Port Funktionen
    output_low(LED);    // LED ein
    delay_ms(100);
    output_high(LED);   // LED aus
    delay_ms(100);
    output_bit(LED, EIN);
    output_bit(LED, ON);
    delay_ms(100);

    while (1)
    {
        output_toggle(LED); // LED langsam blinken (Normal wuerde ich
                            // das mit Interrupt und timer machen)
        delay_ms(500);
    }

}

Warscheinlich kennt Ihr das sowieso. Wie gesagt das mit dem Bitschieben
ist mir ungewohnt.

Viele Gruesse,
Gerhard

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