Hallo,
ich habe Heute mein erstes Programm in C geschrieben und dazu direkt mal
eine Frage. Mein Programm macht nicht das was ich gerne möchte.
Vielleicht hat jemand von euch mal 'ne Minute und kann sich den
Quellcode anschauen.
Das Programm soll folgendes machen:
Wenn an PORTB 0xE0 anliegt (also PORTB 5,6 und 7 auf High liegen), dann
soll eine LED geschaltet werden (über Transistor) und zwar PORTC,4.
Das wars auch schon. Ich habe als Takt einen 4Mhz Quarz gewählt also
müsste die Konfiguration mit 'HS' doch stimmen.
Naja mal schaun was ihr dazu sagt, freue mich schon auf Rückmeldungen.
PS: Der PIC18F2550 hat 2x Vss... Muss ich die beide auf 0V ziehen?
Und was soll das bezwecken?
Lieben Gruß Nico
Betriebsspannungen und GNDs sollten ALLE angeschlossen werden. Außerdem
ist bei einem 4MHz-Quarz die Einstellung XT die richtige, wenn ich mich
nicht irre.
Hi, danke für die schnelle Antowrt.
Also XT geht bis 4Mhz und HS ab 4Mhz von daher sollte das eigentlich so
funktionieren. Aber ich werde den 2. Vss auf nochmal auf 0V ziehen mal
sehen ob das was hilft...
Nicolas Meyertöns schrieb:
> Hallo Stefan,>> ich habe doch unten in main return stehen, hab das grad nochmal> verbessert durch return 0;
und was hat return mit einer Schleife zu tun?
Nicolas Meyertöns schrieb:
> ich habe doch unten in main return stehen, hab das grad nochmal> verbessert durch return 0;>> Oder meinst du jetzt was anderes?
Ja, meine ich.
Nach einem Reset wird dein Programm einmal durchlaufen, und was passiert
dann? Was passiert nach dem return? Nun, das hängt vom Compiler ab, von
leerer Endlosschleife über Software-Reset bis hin zum Absturz ist da
alles möglich.
>Wenn an PORTB 0xE0 anliegt (also PORTB 5,6 und 7 auf High liegen), dann>soll eine LED geschaltet werden (über Transistor) und zwar PORTC,4.
Versuch mal so:
1
voidmain(void)// Anfang
2
{
3
4
TRISA=0x00;// PORTA ist als Output konfiguriert
5
6
TRISB=0xE0;// PORTB,5,6,7 ist als Input konfiguriert
Hallo, danke für die Antworten ich bin im Augenblick nicht an meinem
Platz aber werde es dann mal ausprobieren.
>Verstehe dein Programm nicht. Lies dein Programm>nochmal durch und dann die Kommentare dahinter. Passt>irgendwie nicht zusammen.
Ja ich weiß die Kommentare sind noch veraltet, sorry das hab ich
verpennt.
Ok wenn man PORTC nicht als Ausgang definieren kann dann werde ich da
mal umstruckturieren.
1
while(1)
2
{
3
if(PORTB==0xE0){
4
PORTCbits.RC4=1;
5
}
6
else{
7
PORTCbits.RC4=0;
8
}
9
}
*PORTCbits.RC4 = 1* Der Befhel steuert nur ein einzelnes Bit an richtig?
*while (1)* Die 1 in der Klammer was für eine Bedingung stellt diese
dar? Läuft der jetzt immer durch die While Schleife durch?
das while stellt die endlosschleife dar.
mit der 1 legst du quasi den zustand true fest. dieser gilt immer und
somit wird die schleife nicht abgebrochen.
Hallo Nicolas,
ich kann dir nur raten dir ein C - Buch zu kaufen, es aufmerksam zu
lesen und die darin enthaltenen Beispiele durch zu denken und
auszuprobieren.
Auch wenn du Anfänger bist, ein µController Programm ohne Endlosschleife
zu schreiben, zeigt davon dass du einfach mal aufs geradewohl drauf
losprogrammierst und du dann mit Fehlersuche viel mehr Zeit verschei..
als mit schreiben.
Das ist der falsche Weg!
Nicht böse gemeint, ich habe auch so angefangen wie du, aber recht
schnell meine Rangehensweise geändert...
Wünsche dir noch viel Spass beim Lernen!
mfg
Hallo, danke für eure Antworten!
Also ich habe schon einiges in Assembler programiert. Von daher ich weiß
schon, dass es einer Schleife beadarf. Ich habe nur angenommen, dass es
bei dem Return dann im "main" von vorne los geht, habe sowas nämlich in
einem Tutorial gelesen und wohl falsch interpretiert, denn dort hieß es:
>> So muss ein C - Programm mindestens aussehen!
Naja okay jetzt weiß ich es besser =) Man lernt doch nie aus :)
Okay habe jetzt mal wieder ein bisschen ausprobiert und festgestellt es
lag tatsächlich am Pin, welcher nur als Input benutzt werden kann.
Aber jetzt geht es weiter... Ich bekomme die LED jetzt zum leuchten aber
sobald ich irgendwas in Abhängigkeit der Eingänge (RB7,6,5) machen
möchte läuft nix mehr so wie ich will.
Zunächst konfiguriere ich unter main die TRIS Register, dann geht es
direkt in die Schleife wo eine Bedingung zu finden ist und zwar "PORTB
&& 224" also wenn PORTB7,6 und 5 High haben (entspricht doch dez. 224),
wenn das also eine 1 liefert (true) dann soll das Unterprogramm
aufgerufen werden und die LED blinkt vor sich hin.
Ist die Bedingung nicht erfüllt, so wird einfach der Ausgang gelöscht.
So jetzt kommt das interessante: Beim Starten des PICs also bei
Spannungszufuhr fängt die LED sofort an zu blinken obwohl RB7,6 und 5
LOW sind! Komischerweise sind RB4,3,2 und 0 auf HIGH. Wobei es im
Datenblatt eigentlich heisst, dass alle Pull-Ups beim POR disabled sind.
Zum testen habe ich das INTCON2 Register auch nochmal mit FF geflutet
aber das hat auch nix geholfen. Ich habe mich jetzt auch nicht getraut
die PINs auf Masse zu ziehen weil ich mir den PIC nicht weghauen möchte.
Vielleicht weiß ja jemand was ich übersehen habe.
PS: Alle Pins am PORTB sind offen bis eben auf meine Eingänge (7,6,5)
aber dass sollte ja nicht weiter stören da ich sie doch als Output
initialisiert habe...
> wo eine Bedingung zu finden ist und zwar "PORTB> && 224" also wenn PORTB7,6 und 5 High haben
In einem C-Buch den Unterschied zwischen & und && nachschlagen.
Hallo,
ein geeignetes C-Buch ist m.E.:
H.Herold C Kompaktreferenz
isbn 3-8273-2286-3
Ich sehe mich veranlasst, zur Benutzung dieses Buches mit grossem
Nachdruck zu raten!
Gruss
Robert
Hallo Robert,
danke für deinen Buch Tipp, das werde ich mir mal ansehen.
Ich habe trotzdem vorab jetzt schonmal eine kurze Frage!
Folgende Variablen habe ich als unsigned char deklariert:
"eins", "zwei" und "erg"
wobei "eins" den Wert 1 "zwei" den Wert 15 zugeordnet bekommt.
"erg" soll die Bitweise Operation & der beiden anderen Variablen sein!
Also müsste es doch so ablaufen:
Ich habe mich erst gefragt ob es wohl wichtig ist, dass ich die
Operation nach den beiden deklarationen schreibe.. mh..
Danke für die schnelle Antwort =)
Gut das Programm läuft schon wollt mich jetzt gleich weiter versuchen!
Habe mir einiges über ADC durchgelesen und ein Programm geschrieben aber
es ist natürlich wieder irgendwo der Wurm drin =)
1
voidmain(void)// Main wie bei Assemblar
2
{// Anfang
3
intADCw;
4
intADCe;
5
ADCe=1023;
6
7
8
LATA=0x00;// PORTA löschen (kann beim Start undef. Zustand annehmen)
9
LATB=0x00;// PORTB löschen (kann beim Start undef. Zustand annehmen)
10
LATC=0x00;// PORTC löschen (kann beim Start undef. Zustand annehmen)
11
12
ADCON0=0x01;// AD Wandlung auf RA0
13
ADCON1=0x0E;// RA0 ist ein Analog Eingang
14
ADCON2=0x3E;// Left,Geschwindigkeit,Time
15
16
17
TRISA=0x01;// PORTA,0 ist als Input konfiguriert
18
TRISB=0x00;// PORTB,7 ist als Output konfiguriert
19
TRISC=0x00;// PORTC ist als Output konfiguriert
20
21
Delay10KTCYx(10);// ADC Aquisition Time
Bis hier hin stelle ich erstmal die Grundlegenden Parameter ein!
1
while(1)// Endlosschleife muss vorhanden sein
2
{// Start ab jetzt kommt euer main Programmcode
3
4
ADCON0=0x03;// Analog Digital Messung starten
5
6
while(ADCON0==3)// Warten bis der ADC fertig ist
7
{
Hier soll der ADC gestartet werden und abgewartet werden, bis die
Messung fertig ist.
1
Delay10KTCYx(10);// ADC Aquisition Time
Hier ist dann wieder eine Verschnaufpause für den ADC.
1
ADCw=ADRESH+ADRESL;
Hier möchte ich die beiden Ergebnis Register addieren.
1
if(ADCw>ADCe)// Solange ADRESH größer als 128 ist
2
{
3
LATCbits.LATC7=0;// Bleibt der PORTC,7 aus
4
}
5
else
6
{
7
LATCbits.LATC7=1;// Sonst geht er an!
8
}
9
10
}
11
}
Und hier soll entschieden werden ob LED an oder aus und zwar, wenn die
Spannung über 2,5V liegt (1023) soll sie aus bleiben unter 2,5V soll sie
an gehen.
Wo ist der Fehler?
Hallo Sascha,
ich wollte eigentlich erstmal nur herrausfinden ist der Wert unter oder
über 2,5V. Aber gut dann versuche ich es gleich vernünftig habe da aber
noch eine Frage.
>>while(ADCON0bits.NOT_DONE);
Fehlen hier nicht die beiden Klammern {} ?
>>ADWERT=ADRESH;>>ADWERT=ADWERT<<8;>>ADWERT=ADWERT+ADRESL;>>return ADWERT;
Was genau machst du hier?
Da wird aus den beiden 8Bit Werten ein 16Bit Wert gemacht, einfach
schieben + addieren. Aus High/Lowbyte ein unsigned integer bilden.
Um auf auf 2.5V zu testen dann 512 als Wert nehmen, da dein AD von
0-1023 geht.
Gruß Sascha
Gut jetzt hab ich es fast, nur noch eine Kleinigkeit;
"Channel" legst du irgendwo anders im Programm fest, richtig?
Ich möchte zunächst nur 1 AD Pin benutzen und zwar RA0, also bräuchte
ich nur schreiben:
ADCON0=0x01;
...denn die restlichen möchte ich ja eh nicht abfragen.
Hallo,
soviel Speicher kostet der Code nicht.
So kannst du einfach mit dem Aufruf von Read_ADC(0) den Kanal 0
aufrufen, oder Read_ADC(1) für Kanal 1. Ist später mal einfacher zu
lesen....
Brauchst so halt nur schaun welchen AN-Pin du nimmst und nicht mehr
schauen, wie du den einstellen mußt.
Gruß Sascha
Naja gut da hast du wohl recht! Jetzt noch 1 letzte Frage;
Wenn ich z.B. mein main Programm habe und dort drin dann
das UP oder Funktion Read_ADC(0) aufrufe, dann misst er ja den AN0
und speichert den in der uint ADWERT ab. Zum Schluss kommt dann ja
der Befehl Return ADWERT;
womit ich ja wieder in mein main Programm, mit dem Rückgabewert "ADWET",
komme oder? Wenn ja, wenn ich nun den ADWERT unter main als Bedingung
einsetzte krieg ich nen Error weil der ADWERT unbekannt ist.
Wie kann ich das richtig stellen, muss ich zusätzlich den Wert unter
main auch nochmal deklarieren, dass es ein uint ist?
Schonmal 1000 dank für deine Hilfe hast mir echt gut geholfen =)
Die Variable ADWERT existiert nur local in der Funktion Read_ADC.
Deshalb auch der Aufruf mit ADCw=Read_ADC(0).
Es geht aber auch, wenn die AD-Funktionen in deiner main.c sind,
eine unsigned int ADWERT Variable anlegen.
1
#pragma udata
2
unsignedintADWERT;
3
unsignedintADCe;
4
5
#pragma code
6
voidmain(void)
7
{// Anfang
8
ADCe=511;
9
10
11
LATA=0x00;// PORTA löschen (kann beim Start undef. Zustand annehmen)
12
LATB=0x00;// PORTB löschen (kann beim Start undef. Zustand annehmen)
13
LATC=0x00;// PORTC löschen (kann beim Start undef. Zustand annehmen)
14
15
TRISB=0x00;// PORTB,7 ist als Output konfiguriert
16
TRISC=0x00;// PORTC ist als Output konfiguriert
17
18
Setup_ADC();
19
while(1)
20
{
21
Read_ADC(0);
22
if(ADWERT>ADCe)// Solange ADRESH größer als 128 ist
23
{
24
LATCbits.LATC7=0;// Bleibt der PORTC,7 aus
25
}
26
else
27
{
28
LATCbits.LATC7=1;// Sonst geht er an!
29
}
30
}
31
}
32
33
34
voidSetup_ADC(void)
35
{
36
ADCON0bits.ADON=0;
37
TRISAbits.TRISA0=1;
38
ADCON2=0x3C;
39
ADCON2bits.ADFM=1;
40
ADCON0bits.ADON=1;
41
}
42
43
voidRead_ADC(unsignedcharChannel)
44
{
45
// unsigned int ADWERT; // fällt weg, da global definiert!!!
46
switch(Channel)
47
{
48
case0:
49
ADCON0bits.CHS0=0;
50
ADCON0bits.CHS1=0;
51
ADCON0bits.CHS2=0;
52
ADCON0bits.CHS3=0;
53
break;
54
case1:
55
ADCON0bits.CHS0=1;
56
ADCON0bits.CHS1=0;
57
ADCON0bits.CHS2=0;
58
ADCON0bits.CHS3=0;
59
break;
60
case2:
61
ADCON0bits.CHS0=0;
62
ADCON0bits.CHS1=1;
63
ADCON0bits.CHS2=0;
64
ADCON0bits.CHS3=0;
65
break;
66
case3:
67
ADCON0bits.CHS0=1;
68
ADCON0bits.CHS1=1;
69
ADCON0bits.CHS2=0;
70
ADCON0bits.CHS3=0;
71
break;
72
case4:
73
ADCON0bits.CHS0=0;
74
ADCON0bits.CHS1=0;
75
ADCON0bits.CHS2=1;
76
ADCON0bits.CHS3=0;
77
break;
78
case5:
79
ADCON0bits.CHS0=1;
80
ADCON0bits.CHS1=0;
81
ADCON0bits.CHS2=1;
82
ADCON0bits.CHS3=0;
83
break;
84
case6:
85
ADCON0bits.CHS0=0;
86
ADCON0bits.CHS1=1;
87
ADCON0bits.CHS2=1;
88
ADCON0bits.CHS3=0;
89
break;
90
case7:
91
ADCON0bits.CHS0=1;
92
ADCON0bits.CHS1=1;
93
ADCON0bits.CHS2=1;
94
ADCON0bits.CHS3=0;
95
break;
96
case8:
97
ADCON0bits.CHS0=0;
98
ADCON0bits.CHS1=0;
99
ADCON0bits.CHS2=0;
100
ADCON0bits.CHS3=1;
101
break;
102
case9:
103
ADCON0bits.CHS0=1;
104
ADCON0bits.CHS1=0;
105
ADCON0bits.CHS2=0;
106
ADCON0bits.CHS3=1;
107
break;
108
case10:
109
ADCON0bits.CHS0=0;
110
ADCON0bits.CHS1=1;
111
ADCON0bits.CHS2=0;
112
ADCON0bits.CHS3=1;
113
break;
114
case11:
115
ADCON0bits.CHS0=1;
116
ADCON0bits.CHS1=1;
117
ADCON0bits.CHS2=0;
118
ADCON0bits.CHS3=1;
119
break;
120
case12:
121
ADCON0bits.CHS0=0;
122
ADCON0bits.CHS1=0;
123
ADCON0bits.CHS2=1;
124
ADCON0bits.CHS3=1;
125
break;
126
default:
127
ADCON0bits.CHS0=0;
128
ADCON0bits.CHS1=0;
129
ADCON0bits.CHS2=0;
130
ADCON0bits.CHS3=0;
131
}
132
133
ADCON0bits.GO=1;// Start AD conversion
134
while(ADCON0bits.NOT_DONE);// Wait for conversion
135
ADWERT=ADRESH;
136
ADWERT=ADWERT<<8;
137
ADWERT=ADWERT+ADRESL;
138
// return ADWERT; //diese Zeile fällt dann weg!!!!
139
}
Hoffe mal, ich habe jetzt nix vergessen :)
Gruß Sascha
Ah gut, das hat mir noch gefehlt.Also wenn ich Variablen oberhalb meines
Codes deklariere gelten sie global und ich kann sie überall abrufen.
Danke es funktioniert jetzt! Übrigens Deutschland (Damen) ist
Europameister 6:2 gegen England gewonnen =) Schönen Abend noch..