Hallo Leute.
Ich bastle hier eine Terrariensteuerun mit einem pic18f4550 im C18.
USB, DS1307 und feuchtesensor HYT221 habe ich zum laufen gebracht(bin
noch am lernen).
Nun scheitere ich aber an der "Zeitschaltuhr"! eigentlich nur am
speichern eines portpins in einer variable. Wen ich in der Function
chek_jops() den pin pseudo: PORTx.bits.XX = 1; funzt das super. nur
brauche ich das "dynamisch".
Habe eine strukt arrey mit jops erstellt:
Die Kanäle für die Relais habe ich mit #define KANAL1 LATEbits.LATE0 be
named:
1
typedefstructjop{
2
unsignedcharhpts;
3
unsignedcharehr;
4
unsignedcharemin;
5
unsignedcharahr;
6
unsignedcharamin;
7
unsignedcharaktion;
8
unsignedcharkanal;
9
unsignedcharstatus;
10
}jop_t;
11
12
13
jop_ttestjop[15];
14
15
testjop[0].hpts=1;
16
testjop[0].ehr=18;// einschalten
17
testjop[0].emin=0;
18
testjop[0].ahr=18;//ausschalten
19
testjop[0].amin=12;
20
testjop[0].aktion=1;
21
testjop[0].kanal=KANAL1;// hier scheiterts wohl!????!!
22
testjop[0].status=0;
In der Funktion chek_jops() wollte ich mit testjop[i].kanal = 1 den
Kanal einschalten -> funzt nicht, weil ich damit ja nur den wert 1 an
die variable zuweise!
leider übe ich schon eine Woche an dem Problem aber find keine lösung!
geht das überhaubt in der art oder bin ich total auf dem holzwg?
Hier noch die Funktion
Du musst rausfinden, was genau sich hinter LATEbits verbirgt. Der Syntax
nach wird das wohl irgendeine Struktur sein, die auf nicht-Standard-C
Art mit dem realen physischen Port verknüpft wird.
In deine Struktur muss dann ein Pointer auf genau so eine Struktur rein.
Allerdings: mit dem Pin an sich wird das höchst wahrscheinlich nichts
werden. D.h. du wirst mit Byte vom Port holen und ausmaskieren arbeiten
müssen.
Ich kenn den C18 nicht.
Aber auf einem AVR mit GCC würde das so gehen.
ein Port hat den Datentyp *(volatile unsigned char*)
in eine Struktur muss also rein
struct PortKonfig {
volatile unsigned char* pPort;
unsigned char PortMask;
}
eine derartige Konfiguration wäre zb
struct PortKonfig LedPort = { &PORTA, 0x01 }; // Pin 0 am Port A
normalerweise würde man so den Pin auf 1 setzen
PORTA |= 0x01;
in der indirekten Variante ist das dann
*(LedPort.pPort) |= (LedPort.Mask);
Hallo Karl Heinz
Danke für Deine super schnelle Antwort.
Habe es auch schon mit pointer versucht. Nur unterstüzt der C18 keine
Pointer auf einzelne bit's(wie Du erwartet hast:-))
1
externvolatilenearunsignedcharPORTE;
2
externvolatilenearunion{
3
struct{
4
unsignedRE0:1;
5
unsignedRE1:1;
6
unsignedRE2:1;
7
unsignedRE3:1;
8
unsigned:3;
9
unsignedRDPU:1;
10
};
11
struct{
12
unsignedCK1SPP:1;
13
unsignedCK2SPP:1;
14
unsignedOESPP:1;
15
};
Die Idee mit maske und pointer auf port bin ich nicht gekommen! Werde
das mahl probieren.
Ist mir noch ne andere Idee gekommen:-)
Habe mir überlegt ob es nicht einfacher währe nur die Nr des Kanals
zu speichern und mit switch auszuwerten:
1
#define KANAL1_ON() KANAL1 = 1;
2
#define KANAL1_OFF() KANAL1 = 0;
3
4
switchtestjop[i].kanal:
5
case1:
6
KANAL1_ON();
7
break;
8
//usw für jeden kanal
Dies nur weil nicht alle Kanäle auf einem Port liegen.
Weis nur nicht wie "elegannt" das ist und ob das nicht mein code extrem
aufbläst?
Für alle Special Function Register gibts solche Einträge in den Header
Files, auch für Felder mit mehr als einem Bit. Die Bezeichnungen
entsprechen den im Datenblatt.
MfG Klaus
Klaus schrieb:> Die PIC Leute machen das etwas anders.
Das war mir schon klar.
Nur: wie machst du das indirekt?
zb wie übergibst du einer Funktion eine Referenz auf den Portpin, den
sie schalten soll.
Da klappt das dann nicht mehr.
Karl Heinz Buchegger schrieb:> zb wie übergibst du einer Funktion eine Referenz auf den Portpin, den> sie schalten soll.
Ich bin da nicht so der C-Experte, deshalb hab ich ja den Ausschnitt aus
dem Headerfile gepostet. Sollte es nicht möglich sein, einen Pointer auf
ein Strukturelement aus einer Portstruktur zu bekommen?
MfG Klaus
Klaus schrieb:> Karl Heinz Buchegger schrieb:>> zb wie übergibst du einer Funktion eine Referenz auf den Portpin, den>> sie schalten soll.>> Ich bin da nicht so der C-Experte, deshalb hab ich ja den Ausschnitt aus> dem Headerfile gepostet. Sollte es nicht möglich sein, einen Pointer auf> ein Strukturelement aus einer Portstruktur zu bekommen?
Genau da liegt das Problem. Sowas ist in C nicht vorgesehen.
Die kleinste addressierbare Einheit ist das Byte (vulgo unsigned char).
Klaus schrieb:> Sollte es nicht möglich sein, einen Pointer auf> ein Strukturelement aus einer Portstruktur zu bekommen?
Ist denn ein dein PIC bitadrtessierbar?
gänzi schrieb:> Klaus schrieb:>> Sollte es nicht möglich sein, einen Pointer auf>> ein Strukturelement aus einer Portstruktur zu bekommen?> Ist denn ein dein PIC bitadrtessierbar?
Ich glaube, das sind sie. Seit ich die größeren (PIC24) benutze, habe
ich aber noch keinen Blick auf den Assemblercode geworfen. Wichtig ist
aber eigentlich, daß der Compiler den passenden Code generiert, ob
direkt oder mit Maske.
Karl Heinz Buchegger schrieb:> Genau da liegt das Problem. Sowas ist in C nicht vorgesehen.> Die kleinste addressierbare Einheit ist das Byte (vulgo unsigned char).
Ich glaube zu verstehen was du meinst. Ist aber nicht inzwischen soetwas
wie:
1
unsignedRB0:1;
2
unsignedRB1:1;
auch Standard C mit der Garantie, daß die beiden Bits hintereinander im
selben Byte liegen?
MfG Klaus
Klaus schrieb:> Ich glaube zu verstehen was du meinst. Ist aber nicht inzwischen soetwas> wie:>
1
>unsignedRB0:1;
2
>unsignedRB1:1;
3
>
> auch Standard C mit der Garantie,
natürlich sind Bitfelder schon lange Standard
> daß die beiden Bits hintereinander im> selben Byte liegen?
Das ist IMHO nicht definiert. Spielt aber auch keine so grosse Rolle in
diesem Fall. Der springende Punkt ist: Du kannst keinen Pointer bilden,
der auf einen derartigen Member zeigt. Es gibt schlicht und ergreifend
keinen Datentyp dafür.
(UNd das zeigt auch wo das Problem beim Bitfield liegt: Ein Bit in einem
Bitfield wird durch eine Zusatzinfo 'erzeugt', die aber nicht Teil des
Datentyps ist. Damit kann man auch keinen Pointer daraus bilden)
Karl Heinz Buchegger schrieb:>> auch Standard C mit der Garantie,>> natürlich sind Bitfelder schon lange Standard>>> daß die beiden Bits hintereinander im>> selben Byte liegen?
Du hast meinen Satz elegant in zwei Teile geteilt. Na klar sind
Bitfelder Standard, ich habe sie aber selten verwendet, weil der
Compiler die Freiheit hat, aus jedem Bitfeld ein int zu machen und ich
damit nicht die Kontrolle über eine bestimte Bitposition habe.
Wenn ich dich also richtig verstehe, funktioniert dieses Konstruct aus
dem C30 Header File
Klaus schrieb:> Karl Heinz Buchegger schrieb:>>> auch Standard C mit der Garantie,>>>> natürlich sind Bitfelder schon lange Standard>>>>> daß die beiden Bits hintereinander im>>> selben Byte liegen?>> Du hast meinen Satz elegant in zwei Teile geteilt. Na klar sind> Bitfelder Standard, ich habe sie aber selten verwendet, weil der> Compiler die Freiheit hat, aus jedem Bitfeld ein int zu machen und ich> damit nicht die Kontrolle über eine bestimte Bitposition habe.>> Wenn ich dich also richtig verstehe, funktioniert dieses Konstruct aus> dem C30 Header File>
1
>typedefstructtagPORTBBITS{
2
>unsignedRB0:1;
3
>unsignedRB1:1;
4
>.
5
>.
6
>
> nur beim GCC für PICs.
Dieses Konstruct wird schon überall funktionieren (wenn wir mal
unterstellen, dass Compilerbauer das naheliegenste tun, an den Stellen
an denen der C-Standad Freiräume lässt)
Aber das hier
1
voidfoo(######*bitPos)
2
{
3
*bitPos=1;
4
}
5
6
intmain()
7
{
8
structtagPORTBITSmyBits;
9
10
foo(&myBits.RBO);
11
}
kriegst du nicht gebacken, weil es in C keinen Datentyp gibt, den man an
der Stelle ###### einsetzen könnte. Und was damit zusammenhängt: Der
Adressoperator in &myBits.RBO kann nicht bis in das Bitfeld hinein
adressieren. So gesehen hat das Bit RBO innerhalb der Struktur keine
Adresse, die es von RB1 unterscheidbar machen würde.
Der Krampf ist, dass mir ausser sowas
struct PortKonfig {
volatile unsigned char* pPort;
unsigned char PortMask;
}
nix zu dem Thema einfällt.
C++ wär gut, dann könnte man das alles, samt Zuweisung, wenigstens in
einer Klasse verstecken und kann die Syntax auf das Gewünschte
hindrehen.
void foo( const BitAddr& bit )
{
bit = 1;
}
kein Problem. Aber in C .... hmmmm .... und dann auch noch elegant ....
hmmm
Hallo Leute
Habe da etwas rumgetestet. Pointer auf einzelne bit's funzt definitif
nicht!
Steht so sogar irgendwo im C18 manual(finds grad nicht mehr).
Das mit der switch anweisung geht wunderbahr, gefählt mir aber nicht so
toll.
Schreibe am week mahl die andere variante und versuche den generierten
code zu vergleichen (gröse).
Danke für eure Ausführungen. Wieder etwas gelernt!
ANDERE FRAGE
Irgendwie geht mir der Schpeicher aus!
Wen ich schreibe jop_t testjop[20]; für 20 jop's, erhalte ich
Linkerfehler:
Error - section '.udata_main.o' can not fit the section. Section
'.udata_main.o' length=0x00000116
mit ...[15]; gehts dan tip tip
Hat das was mit #pragma udata zu tun;
währe es besser das in die user_init() zu paken -> bringt das überhaubt
was?
Etwas mehr jops wären schon anzustreben!
1
#pragma udata
2
charUSB_In_Buffer[64];
3
charUSB_Out_Buffer[64];
4
unsignedchartemphigh;
5
unsignedchartemplow;
6
unsignedcharfeuchtehigh;
7
unsignedcharfeuchtelow;
8
jop_ttestjop[15];Hiergernemehrwenirgendwiemöglich
Sorry proge hobbymäsig und erst ca 1 jahr. Habe noch nicht so den
überblick
über die speicher.
Grus Marcel
rechne dir halt mal aus, wieviel Speicher das alles verbraucht.
Dann vergleichst du noch mit dem Speicher, den dein µC in Form von SRAM
hat und denkst daran, dass du den nicht komplett mit Variablen anfüllen
kannst, weil du ja auch noch SRAM zur Laufzeit für Stack und lokale
Variablen brauchst.
Aber wenn diese Variablen da oben schon mal mehr als, sagen wir mal, 80%
deines SRAM ausmachen, dann wirds sowieso schon eng.
Und PS:
Das Wort im Englischen heißt "Job". mit weichem b.