Hallo Leute.
Ich bin neu auf dem Gebiet µC.
Es wäre schön wenn ihr mir bei einem einfachen Problem(...für mich
nicht!)helfen könntet.
Ich habe Makros für bestimmte Pins festgelegt. Ich hoffe das ist richtig
so.
Bsp.:
1
/**
2
Portdefinition für ADC0
3
*/
4
#define PORT_ADC_0 PORTA
5
#define PIN_ADC_0 PINA
6
#define BIT_ADC_0 0
Nun mein Problem. Wie übergebe ich dies einer Funktion?
Wenn ich z.B. ein Funktion habe int GetADC(???), wie übergebe ich der
Funtion jetzt den richtigen Kanal für die AD-Messung? Und wie kann ich
in der Funktion damit arbeiten. Muss ich den Pin oder das Bit übergeben?
sind #defines, die bei der Nutzung von PORTC als Standard-IO sinnvoll
sind. Nutzt du dagegen den ADC, helfen die dir nicht weiter.
Ist der ADC aktiviert, dann wird der ADC-Kanal in den unteren Bits des
ADMUX-Registers eingestellt. Insofern wäre eine brauchbare Definition
für deine Funktion:
Danke, aber so habe ich das nicht gemeint. Vieleicht verstehe ich auch
was falsch. Ich will z.B. in einem "switch case" abfragen, welches
define übergeben wurde. Oder ist das nicht so einfach?
Weisst Du, das ist eigentlich eine C-Frage und hat erstmal nichts mit
Ports oder so zu tun. Das ist auch in Ordnung so. Aber ich schreibe das,
damit Du mitbekommst, wie Du selbst Deine Fragen einordnen kannst, wenn
später mal neue kommen.
>Ich will z.B. in einem "switch case" abfragen, welches>define übergeben wurde.
Ein define wird nicht "übergeben". Mit defines wird einfach nur
Textersatz definiert, der vom Preprozessor_ _vor dem kompilieren
behandelt wird.
Schreibst Du also z.b.
1
#define NETT FREUNDLICH
2
3
DubistNETTzumir.
dann macht der Preprozessor (natürlich ist das obige kein C-Programm,
aber der Preprozessor würde das machen. Probiere es.) daraus
1
#define NETT FREUNDLICH
2
3
DubistFREUNDLICHzumir.
Lies dazu mal in einem guten C-Buch das Kapitel über den Preprozessor.
D.h. also, wenn Du mit define letzlich an die Stelle, wo der definierte
Name auftaucht, eine Zahl setzt, dann musst Du damit umgehen, als wenn
da von Anfang an eine Zahl gestanden hätte.
In einem C-Programm kann man eine Zahl z.B. an eine Funktion übergeben.
Und was muss eine Funktion an dieser Stelle in ihrer Deklaration haben?
Richtig, einen Parameter. Und wenn der Parameter eine Zahl ist? Richtig,
einen integralen Typ wie int, unsigned, char usw.
Das lies bitte auch mal in einem C-Buch nach.
OK?
OK verstanden! Danke.
Dann aber noch eine Frage.
Wie definiere ich dann zentral irgendwelche PORTs, PINs, um im Programm
immer damit arbeiten zu können. Auch Funktionen übergeben und so?
Kann ich da vieleicht mit Enumeratoren arbeiten?
z.B. so?
Mach es doch mit defines. Es ging nur darum, das Du defines nicht
"übergeben" kannst. Das sind einfach Zahlen. Enums gehen natürlich auch.
Aber Du musst halt aufpassen, wie die Nummerierung wird. Lies bitte
erstmal ein C-Buch gründlich durch. Dann klären sich viele Fragen.
die PORTs und PINs sind doch definiert als :
PORTB und DDRB usw ..
wenn du einen pin setzen willst musst du ihn vorher als ausgang setzen
DDRB |= (1<<PB0)
setzt PB0 als ausgang
PORTB |= (1<<PB=0)
setzt den ausgang PB0 auf 1
PORTB &= ~(1<<PB0)
löscht den ausgang
wenn du den Analogeingang nutzt
muss du dem ADC MUX register sagen welchen eingan du gerne messen willst
das ergebniss steht dann im ADCH und ADCL register
für mehrer messungen musst du den MUX umschalten und messen
die ergebnisse kannst du in variablen speichern und verwenden
ansonst sind alle pins des AVRs schon drin
also PORT für die ports eben DDR für datenrichtung
PIN für die eingangsabfrage
PB3 ist das 4te Bit von PORTB
weil PB0 .......PB7 sind 8 bit
So hab ich das nicht gemeint. Natürlich sind alle PINs/PORTs schon
definiert. Wenn in meinem Programm aber zB. der PORTB 100mal auftaucht
und mir fällt ein, dass ich doch den PORTC nehmen will, dann muss ich
alles ändern und nicht nur ein "define"! verstehst du was ich meine?
Wie macht man sowas???
Bei einer Zahl ist das kein Problem.
#define PI 3,141
Aber wie mache ich das mit PORTs und PINs.
Kann aber auch sein, dass ich zu blöd bin!
Danke
Anfänger schrieb:
> So hab ich das nicht gemeint. Natürlich sind alle PINs/PORTs schon> definiert. Wenn in meinem Programm aber zB. der PORTB 100mal auftaucht> und mir fällt ein, dass ich doch den PORTC nehmen will, dann muss ich> alles ändern und nicht nur ein "define"! verstehst du was ich meine?>> Wie macht man sowas???
Du denkst zu komplizert
1
#define LED_PORT PORTB
2
3
voidfoo()
4
{
5
LED_PORT=0x20;
6
}
7
8
voidfoo2()
9
{
10
LED_PORT=0x80;
11
}
12
13
voidfoo3()
14
{
15
LED_PORT=0x45;
16
}
Wenn deine LEDS jetzt vom PORTB auf den PORTC umziehen, änderst du
einfach das #define und bist fertig.
Denk immer daran: #define macht nur Textersetzungen. Im nachfolgenden
Text wird überall LED_PORT durch PORTB textuell ersetzt noch ehe der
Compiler den Code zu Gesicht bekommt.
Anfänger schrieb:
> Und wenn ich jetzt eine einzelne LED am PIN 1 anschalten will. Muss ich> das das Bit oder den Pin angeben.
Stell dir vor, wie das tatsächliche Ergebnis aussehen soll
Du willst haben, dass der Compiler dieses zu Gesicht bekommt
1
voidfoo()
2
{
3
PORTB|=(1<<PB1);
4
}
weil an Pin 1 vom Port B momentan deine LED hängt.
Jetzt möchtest du das aber besser konfigurierbar haben, was ja
grundsätzlich gut ist.
Also nennst du PORTB den LED_PORT und anstelle von PB1 möchtest du
ERROR_LED schreiben, weil das die Funktion der Led ist
1
#define LED_PORT PORTB
2
#define ERROR_LED PB1
3
4
voidfoo()
5
{
6
LED_PORT|=(1<<ERROR_LED);
7
}
Mach einfach mal gedanklich jetzt die Textersetzungen. Ersetze den Text
LED_PORT durch PORTB und den Text ERROR_LED durch PB1
Es kommt genau das Gewünschte PORTB = ( 1 << PB1 ); heraus. Und so
wird es dann auch durch den Compiler gejagt.
Mittels #define kannst du jeden beliebigen Text durch irgendeinen
anderen Text ersetzen lassen. Wichtig ist aber: Es ist nur eine
Textersetzung, die abläuft ehe der Compiler den Code zu Gesicht bekommt.
Wenn du in deinem Editor die Replace Funktion benutzt und LED_PORT durch
PORTB ersetzt, dann machst du genau das was auch der Präprozessor macht.
>Und wenn ich jetzt eine einzelne LED am PIN 1 anschalten will. Muss ich>das das Bit oder den Pin angeben.
ACHTUNG: Was in diesem Zusammehang "PIN" heisst, also PINA, usw. bezieht
sich auf den gesamten Port von 8 Bit nicht auf einen einzelnen Anschluss
des IC, der im englischen "Pin", im deutschen "Stift" heisst. Es steht
glaube ich für "Port INput" im Unterschied zur DDR (wie DDRA) oder PORT
(wie PORTA) die für die Datenrichtung und den Ausgang zuständig sind.
Die Pins sind durchnummeriert und jeweils einem Bit des Port zugeordnet.
Gewöhnlich ist PIN0 auch Bit 0 usw. (Möglicherweise fangen die Ports mit
1 ein, dann ist PIN1 dem Bit 0 zugeordnet. Ich weiss gerade nicht wie es
bei den AVR-Definitionen ist).
Ja danke, das habe ich auch verstanden.
Aber jetzt habe ich eine Funktion.
Dieser Funktion möchte ich übergeben, welcher PIN geschaltet werden
soll.
Und ich hab geschrieben:
#define LED_PORT PORTB
#define ERROR_LED PB1
Die Funktion:
void SetLED(???)
{
}
Ich kann ja nicht schreiben:
SetLED(ERROR_LED);
Da habe ich ein wenig schlecht geschrieben. Es muss heissen:
Ein einzelner Pin, also ein einzelner Anschluss oder Stift wird durch P
gefolgt von dem Portnamen A, B usw. gefolgt von einer Ziffer
gekennzeichnet.
Die Pins sind also durchnummeriert und jeweils einem Bit des Port
zugeordnet.
Gewöhnlich ist PA0 auch Bit 0 usw. (Möglicherweise fangen die Ports mit
1 ein, dann wäre PA1 dem Bit 0 zugeordnet. Ich weiss gerade nicht wie es
bei den AVR-Definitionen ist).
Anfänger schrieb:
> Ja danke, das habe ich auch verstanden.> Aber jetzt habe ich eine Funktion.> Dieser Funktion möchte ich übergeben, welcher PIN geschaltet werden> soll.>> Und ich hab geschrieben:>> #define LED_PORT PORTB> #define ERROR_LED PB1>> Die Funktion:>> void SetLED(???)> {>> }>> Ich kann ja nicht schreiben:>> SetLED(ERROR_LED);
Warum nicht?
Klar kannst du. ERROR_LED ist eine andere Schreibweise für PB1. Und das
wiederrum ist nur eine andere Schreibweise für 1
Wenn der Präprozessor kommt, ersetzt er ERROR_LED durch PB1
Aus
SetLED(ERROR_LED);
wird so
SetLED(PB1);
Nun ist aber PB1 seinerseits wieder ein Makro, welches in io.h definiert
ist
#define PB1 1
Also erfolgt konsequenterweise die nächste Ersetzung und da steht
SetLED(1);
Also muss deine Funktion so aussehen
Karl heinz Buchegger schrieb:
> Also muss deine Funktion so aussehen>>
1
>voidSetLED(inti)
2
>{
3
>...
4
>}
5
>
Aber aus mehreren Gründen ist das keine so wahnsinnig gute Idee.
Zum einen ist der int überkandidelt. Ein unsigned char tut es an dieser
Stelle auch.
Zum zweiten, und das ist schwerwiegender, ... geht es denn in der
Funktion weiter:
1
voidSetLED(unsignedcharledNr)
2
{
3
LED_PORT|=(1<<ledNr);
4
}
Dieses 1 << ledNr ist aber eine teure Operation, weil der AVR keine
Operation hat um eine 1 in einem Rutsch um eine variable Bitanzahl nach
links zu schieben.
>Ich kann ja nicht schreiben:>SetLED(ERROR_LED);
Doch! Genau so schreibst Du das.
Aber Du musst natürlich die Funktion SetLED irgendwie füllen.
Du übergibst eine Zahl. Also
1
setLED(charLedNr){
2
LED_PORT|=(1<<LedNr);
3
}
Hinweis:
Da steht "char", was für einen Anfänger etwas verwirrend sein kann. Das
spielt hier keine Rolle, das das nach "character" aussieht. Denn man
kann die Werte auch als ganze Zahlen (die von 0 bis 255 gehen können)
interpretieren. Gleichzeitig steht die Zahl dezimal 49 auch für das
Zeichen '1', also die Ziffer Eins.
Anfänger schrieb:
> Also kann ich doch "defines" an Funtionen übergeben ?!?
Nein!!!!!!
#defines werden abgearbeitet, noch bevor der Compiler irgendetwas mit
deinem Code macht.
Wenn sich der Compiler die Frage stellt, wie Funktionen aufgerufen
werden und welche Argumente übergeben werden, existieren #define ganz
einfach nicht mehr!
Stell es dir so vor:
Du schreibst deinen Code.
Und bevor du den Code compilierst, gehst du in deinem Editor her und
benutzt die Replace-Funktion deines Editors um den Text LED_PORT durch
den Text PORTB zu ersetzen.
Mehr passiert da nicht! Der Quelltext, der durch den Compiler geht, wird
verändert noch bevor ihn der Compiler zu Gesicht bekommt.
Da wird nichts übergeben, da werden keine Datentypen ausgewertet.
Da wird einfach nur ein Text durch einen anderen Text ersetzt!
>Also kann ich doch "defines" an Funtionen übergeben ?!?
Ein "define" kann nicht "übergeben" werden. Das ist ein bischen so, als
wenn Du fragst ob man das Wort "Kirsche" essen kann.
Zulu schrieb:
> Und jetzt, Karl-Heinz erklär mal warum das unsigned char und nicht char> heissen muss. Nicht das die LED quiekt anstatt zu leuchten. ;-)
Gewöhn dir an auf Byteebene mit unsigned char zu arbeiten und du hast
weniger Probleme. Selbst dann, wenn in einem speziellen Fall es keinen
Unterschied macht ob char nun signed ist oder nicht.
Du musst den Text, mit dem Du ein Programm/Algorithmus beschreibst
streng von dem Programm selbst trennen.
Hier kommt nun noch dazu, das zwei "Programmiersprachen" übereinander
gestapelt sind. Erst der Preprozessor. Er kann nur Textersatz
beschreiben. Mehr nicht. Keine Verarbeitung, keine Formeln, keine
Berechnungen. (Naja. Man kann mit Textersatz auch rechnen, aber das ist
was für die Informatik-Vorlesungen). Dann erst kommt der C-Compiler. Und
der rechnet auch nur teilweise mit konstanten Werten. Erst dann kommt
das Programm selbst, das dann wirklich was berechnet.
@ Karl-Heinz
>> Und jetzt, Karl-Heinz erklär mal warum das unsigned char und nicht char>> heissen muss. Nicht das die LED quiekt anstatt zu leuchten. ;-)>Gewöhn dir an auf Byteebene mit unsigned char zu arbeiten und du hast>weniger Probleme. Selbst dann, wenn in einem speziellen Fall es keinen>Unterschied macht ob char nun signed ist oder nicht.
Da hast Du recht. Aber im Moment arbeite ich gerade mit guint8 und wälze
mich durch die gtk-docu. Da war mir das erstmal egal.
OK, jetzt bin ich vom Schlauch runter gestiegen. Ich habs kapiert!
Ich hab wirklich zu kompliziert gedacht.
Danke nochmal an alle, jetzt hats geklappt.
Dieses Forum und seine Gemeinde sind echt hilfsbereit, auch wenn ein
dummer Anfänger Fragen stellt.
Bis dann ...
Dieser Funktion kannst du einen Port übergeben (als Adresse),
sowie eine Bitnummer und einen Wert (0 oder 1).
Der entsprechende Ausgangspin wird dann gesetzt oder gelöscht.
Z.B. könnte man mit:
1
while(1)
2
{
3
4
bitset(&PORTD,7,1);
5
_delay_ms(500);
6
bitset(&PORTD,7,0);
7
_delay_ms(500);
8
}
eine LED blinken lassen.
Nachtrag:
Das funktioniert nicht mit allem, was man mit #define so
definieren kann.
Glücklicherweise sind bei einem AVR die Ports in den Adreßspeicher
eingeblendet (also wie jede Variable auch über die Adresse erreichbar)
und die PORT... sind etwa in der Art definiert:
1
#define PORTA (*(uint8_t*)42)
(falls jetzt beispielsweise PORTA an der Stelle 42 eingeblendet ist,
was wahrscheinlich nicht ganz stimmen wird).
Bei bitset( &PORTA, 7, 1 ) würde also der erste Parameter zum
Wert &*(uint8_t*)42 werden, mithin 42 als uint8_t-Wert.
In der Funktion wird dann mit *(uint8_t*)42 wieder auf das Register
zugegriffen.