Archiv verlassen und diese Seite im Standarddesign anzeigen : Register an Funktion übergeben
EDatabaseError
01.11.2008, 11:25
Hallo,
wie kann ich die Adresse eines Registers an eine Funktion übergeben?
uint8_t outSet(uint8_t *port, uint8_t pin, uint8_t level) {
uint8_t *DDR = 0;
if (*port == PORTA) { *DDR = DDRA; }
if (*port == PORTB) { *DDR = DDRB; }
if (*port == PORTC) { *DDR = DDRC; }
if (*port == PORTD) { *DDR = DDRD; }
asm("nop");
if (level) {
*port |= (pin << *port);
} else {
*port &= ~(pin << *port);
}
return level;
}
Aufruf: outSet(&PORTA,3,1);
Nur der Compiler meldet: ../main.c:84: warning: passing argument 1 of 'outSet' discards qualifiers from pointer target type
Was mache ich falsch?
Gruß
uint8_t outSet(volatile uint8_t *port, uint8_t pin, uint8_t level) {
Außerdem:
if (*port == PORTA) { *DDR = DDRA; }
->
if (port == &PORTA) { DDR = &DDRA; }
Aber wozu das, du verwendest DDR doch gar nicht?
Diese Warnung bringt er gerne, wenn man mit Pointer arbeitet, das sagt garnix.
Übrigens: es ist nicht notwendig, aus den Pointer das DDRx Register zu ermitteln: Alle IO Register haben die gleiche struktur
typedef struct {
uint_8_t Pin; // in
uint_8_t Ddr; // control
uint_8_t Port; // out
} IO_REG;
// Aufruf
outSet((IO_REG*)&Pinb, 3, 1 )
uint8_t outSet(IO_REG* port, uint8_t pin, uint8_t level)
{
port->Ddr |= (1 << pin); // DDR auf Output
if (level)
port->Port |= (1 << pin); // Port.pin = 1
else
port->Port &= ~(1 << pin); // Port.pin = 0
return level;
}
Eventuell mit ausreichend "volatile"s beflastern
Diese Warnung bringt er gerne, wenn man mit Pointer arbeitet, das sagt garnix.
Das sagt in diesem Fall, dass das Ziel vom Zeiger port in der Funktion nicht mehr volatile ist, und das ist alles andere als "garnix".
thewulf00
01.11.2008, 12:41
Du weißt das vielleicht, weil Du Dich auskennst. Aber mir, PicNick und dem Topic-Eröffner sagte diese Meldung offensichtlich "garnix".
Du weißt das vielleicht, weil Du Dich auskennst. Aber mir, PicNick und dem Topic-Eröffner sagte diese Meldung offensichtlich "garnix".
Es besteht aber ein wichtiger Unterschied zwischen "das sagt garnix" und "das sagt mir garnix". PicNick sagt mit dem Satz, dass die Warnung quasi keine Bedeutung hat und einfach ignoriert werden sollte, und das ist ein ziemlich schlechter Rat.
@sternst: jetzt ist die Spannung der Laien am Höhepunkt:
sag' uns doch endlich, was genau passiert, wenn wir die Warnung ignorieren und das Programm einfach starten.
sag' uns doch endlich, was genau passiert, wenn wir die Warnung ignorieren und das Programm einfach starten.
In diesem konkreten Fall wohl nichts. Aber wenn du z.B. bei dieser Funktion diese Warnung ignorierst, hast du bei eingeschalteter Optimierung eine sehr gute Chance auf eine Endlosschleife (außer natürlich, das Register ist bei Betreten der Funktion schon null):
void WaitForZero ( uint8_t *port ) {
while (*port);
}
...
WaitForZero(&PINC);
[...] was genau passiert, wenn wir die Warnung ignorieren und das Programm einfach starten.
Warnungen einfach zu ignorieren ist, so wie ich finde, generell eine sehr schlechte Angewohnheit. Es ist zwar so, dass oft nicht schlimmes passiert, wenn man es tut, manchmal (siehe sternst`s Beispiel) hat es aber unangenehme Fehler zur Folge, wo man unnötig lange nach einer Lösung sucht. Daher mein Rat: Immer den Code so schreiben, dass keine Warnungen mehr vorhanden sind!
EDatabaseError
01.11.2008, 17:11
Hab mir mal PicNics Vorschlag näher angeschaut..
Über die Typendefinition hab ich automatisch DDR,PIN und PORT? Wenn ja wäre dies ja super.
typedef struct {
uint8_t PIN;
uint8_t DDR;
uint8_t PORT;
} IO_REG;
uint8_t outSet(IO_REG* port, uint8_t pin, uint8_t level) {
port->DDR |= (1 << pin); //DDR as output
if (level) {
port->PORT |= (1 << pin);
} else {
port->PORT &= ~(1 << pin);
}
return level;
}
uint8_t inGet(IO_REG* port, uint8_t pin, uint8_t pullup) {
port->DDR &= ~(1 << pin); //DDR as input
if (pullup) {
port->PORT |= (1 << pin);
} else {
port->PORT &= ~(1 << pin);
}
if (port->PIN & (1 << pin)) {
return 1;
} else {
return 0;
}
}
Könnt ja nochmal über diesen code schauen. Compiliert mit 0 warnings. Noch nicht getestet.
Gruß
Ja, die drei Register für ein IO port sind immer gleich aufsteigend hintereinander
+0 PINx
+1 DDRx
+2 PORTx
Bei inGet(...) gibt es nur ein theoretisches Risiko: die Zeit zwischen Pullup einschalten und Pin abfragen ist sehr kurz, ev. ist da noch kein stabiler Zustand auf der Leitung (von wegen Kapazitäten etc.).
EDatabaseError
01.11.2008, 18:24
wie lange sollte man den elektonen zeit geben?.. mehrere nops?..
muss man das PIN register übergeben oder kann man in die Funktion auch den Port übergeben?
bspw: outSet((IO_REG*)&PORTB, 3, inGet((IO_REG*)&PORTB,2,1) );
EDatabaseError
01.11.2008, 19:15
ok.. hat sich erledigt.. da sie aufeinanderfolgend sind sollte das erste übergeben werden. also PINA.. dann ist das nächste DDRA..
du kannst natürlich auch den PORT übergeben, dann musst du halt in deiner Funktion ein wenig umrechnen...
D.h. am Anfang von inGet und outSet musst du noch port -= 2; schreiben.
Dann musst du allerdings auch wirklich immer &PORTx übergeben.
Dann ist die Sache aber nicht mehr wirklich koscher. denn dann ist ja das funktions-argument nicht wirklich korrekt. Und das wiederum betrachte ich als "bäh", andere stören sich mehr an Warnings
Ich glaube schon, dass man sich daran gewöhnen kann, immer "PINx" zu verwenden.
EDatabaseError
02.11.2008, 14:10
genau so mache es ich jetzt auch.
Warnings sind halt "unschön" manche kann man zwar ignorieren aber mir ist es immer lieber wenn da steht das er mit 0 warnings compiliert hat ;)
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.