Forum: Compiler & IDEs Pin an PortC


von Willi (Gast)


Lesenswert?

Ich finde den Fehler in folgendem Code einfach nicht:

DDRC = (1 << DDC0) | (1 << DDC1) | (1 << DDC2);  //Port C Ausgänge

PORTC |= (1<<PC2);

Der Pin geht nicht auf High :-(

von Sebastian (Gast)


Lesenswert?

Vielleicht ist da der jtag drauf und muß deaktiviert werden

von Willi (Gast)


Lesenswert?

Es ist ein ATmega8

von Jörg Wunsch (Gast)


Lesenswert?

Wird der genannte Code denn überhaupt erreicht?  Vielleicht startet ja
deine Applikation immer wieder von Neuem, weil ein Interrupt zieht,
der keinen Vektor definiert hat?

von Willi (Gast)


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 :-(

von Jörg Wunsch (Gast)


Lesenswert?

Dann ist dein Ausgangstreiber von PORTC2 kaputt...

von Jörg Wunsch (Gast)


Lesenswert?

Errm, AVcc hast du aber beschaltet, ja?

von Willi (Gast)


Lesenswert?

AVCC ist beschaltet.
Wie muss ich die Fusebits setzen?
Kann eines davon Einfluss auf den ADC Port haben?
Oder muss man noch irgendwas in einem ADC Kontrollregister einschalten
/ ausschalten?

von Jörg Wunsch (Gast)


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.

von Stefan Sczekalla (Gast)


Lesenswert?

Hast Du alternativ mal einen anderen Port, bzw einen anderen Pin
probiert ?

Grüße,

Stefan

von Alexander (Gast)


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

von Dirk (Gast)


Lesenswert?

Hi,

tja die main routine sollte immer eine endlosschleife sein. Der µc
rennt ins nirvana ohne richtigen quellcode.

mfg
dirk

von Alexander (Gast)


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

von Ralf (Gast)


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)

von Gerhard (Gast)


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

von Ralf (Gast)


Lesenswert?

Mhhh....
Eigentlich dachte ich der erste Pin wird mit 1, der zweite mit 2, der
dritte mit 4 angesteuert.
Aber vielleicht fängst Du ja nicht bei PC0 sondern bei PC1 zum zählen
an...

von ---- (Gast)


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).

von ---- (Gast)


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).

von Gerhard (Gast)


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

von Stefan Kleinwort (Gast)


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

von ---- (Gast)


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).

von Gerhard (Gast)


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

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.