Erstes Programm in C (PIC18F2550)

OP Persönliche Seite #1393110
Lesenswert?

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
Angehängte Dateien:
#1393296
Lesenswert?

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.
Gast #1393331
Lesenswert?

jup.

normal sieht das so aus:
1
void main (void)
2
{
3
   StartUpCode(); // Initialisiere deine Register, Hardware usw.
4

5
   while(1)
6
   {
7
      // Das hier ist deine Hauptschleife, hier wird die Applikation ausgefuehert
8
     App();
9
   }
10
   return 1;
11
}
(Firma: www.pcb-devboards.de) #1393632
Lesenswert?

>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
  void main(void)         // Anfang      
2
  { 
3

4
    TRISA = 0x00;        // PORTA ist als Output konfiguriert
5
 
6
    TRISB = 0xE0;        // PORTB,5,6,7 ist als Input konfiguriert
7
    TRISC = 0x00;        // PORTC ist als Output konfiguriert
8

9
    PORTC = 0x00;
10

11
  while (1)
12
    {            
13
       if(PORTB == 0xE0) {
14
        PORTCbits.RC4 = 1;
15
        }
16
        else {
17
        PORTCbits.RC4 = 0;
18
        }
19
    }
20
  }
OP Persönliche Seite #1393780
Lesenswert?

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?
Gast #1395067
Lesenswert?

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
OP Persönliche Seite #1395377
Lesenswert?

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 :)
OP Persönliche Seite #1399541
Lesenswert?

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

1
/**********************************************************************************************/
2
//  Include Dateien
3
/**********************************************************************************************/
4
  
5
#include <p18cxxx.h>                   // Für den PIC - wird autom. erkannt
6
#include "delays.h"                    // Für die Warteschleife 
7

8
/**********************************************************************************************/
9
//  Konfiguration
10
/**********************************************************************************************/
11

12
#pragma config FOSC = HS
13
#pragma config PWRT = ON
14
#pragma config BOR = OFF
15
#pragma config WDT = OFF  
16
#pragma config LVP = OFF
17
#pragma config PBADEN = OFF
18
#pragma config VREGEN = OFF
19
#pragma config MCLRE = ON            
20
      
21
/**********************************************************************************************/
22
//  Unterprogramm
23
/**********************************************************************************************/
24

25
  void someLittleFunction(void)
26
  {
27
    LATCbits.LATC7 = 1;
28
    Delay10KTCYx(1);
29
    LATCbits.LATC7 = 0;
30
    Delay10KTCYx(1);
31
  }
32

33
/**********************************************************************************************/
34
//  Hauptprogramm
35
/**********************************************************************************************/
36

37
  void main(void)               // Anfang      
38
{ 
39

40
    TRISA = 0x00;                // PORTA ist als Output konfiguriert 
41
    TRISB = 0xE0;                // PORTB,5,6,7 ist als Input konfiguriert
42
    TRISC = 0x00;                // PORTC ist als Output konfiguriert          
43

44
  while(1) 
45
  { 
46
    if (PORTB && 224)
47
    {
48
      someLittleFunction();
49
    }
50
    else
51
    {
52
      LATCbits.LATC7 = 0;
53
    }
54
  }
55
  return(0);
56
}
OP Persönliche Seite #1401973
Lesenswert?

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:
1
eins |0|0|0|0|0|0|0|1| (1)
2
------------&-------------
3
zwei |0|0|0|0|1|1|1|1| (15)
4
------------=-------------
5
erg  |0|0|0|0|0|0|0|1| (1)

Also folgender Code...
1
/**********************************************************************************************/
2
//  Unterprogramm
3
/**********************************************************************************************/
4

5
  void someLittleFunction(void)
6
  {
7
    LATCbits.LATC7 = 1;
8
    Delay10KTCYx(1);
9
    LATCbits.LATC7 = 0;
10
    Delay10KTCYx(1);
11
  }
12

13

14
/**********************************************************************************************/
15
//  Hauptprogramm
16
/**********************************************************************************************/
17

18
  void main(void)               // Anfang      
19
{ 
20

21
    unsigned char eins, zwei, erg;
22
    erg = eins & zwei;
23
    eins = 1;
24
    zwei = 15;
25

26
    TRISA = 0x00;                // PORTA ist als Output konfiguriert 
27
    TRISB = 0xE0;                // PORTB,5,6,7 ist als Input konfiguriert
28
    TRISC = 0x00;                // PORTC ist als Output konfiguriert          
29

30
  while(1) 
31
  { 
32
    if (erg == 1)
33
    {
34
      someLittleFunction();
35
    }
36
    else
37
    {
38
      LATCbits.LATC7 = 0;
39
    }
40
  }
41
  return(0);

...müsste die Funktion "someLittleFunction" aufrufen, oder?
Vielen Dank schonmal vorweg.

LG
OP Persönliche Seite #1408589
Lesenswert?

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
void main(void)                   // Main wie bei Assemblar          
2
{                                   // Anfang
3
    int ADCw;
4
    int ADCe;
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?
Persönliche Seite #1408600
Lesenswert?

Hallo,

du hast nen 10bit Analog Wert. Warum addierst du High/Lowbyte???

So sieht es bei mir aus:
1
void Setup_ADC(void)
2
{
3
  ADCON0bits.ADON=0;
4
  TRISAbits.TRISA0=1;
5
  ADCON2=0x3C;
6
  ADCON2bits.ADFM = 1;
7
  ADCON0bits.ADON=1;
8
}
9

10
unsigned int Read_ADC(unsigned char Channel)
11
{
12
  unsigned int ADWERT;
13
  switch(Channel)
14
    {
15
    case 0:
16
      ADCON0bits.CHS0=0;
17
      ADCON0bits.CHS1=0;
18
      ADCON0bits.CHS2=0;
19
      ADCON0bits.CHS3=0;
20
      break;
21
    case 1:
22
      ADCON0bits.CHS0=1;
23
      ADCON0bits.CHS1=0;
24
      ADCON0bits.CHS2=0;
25
      ADCON0bits.CHS3=0;
26
      break;
27
    case 2:
28
      ADCON0bits.CHS0=0;
29
      ADCON0bits.CHS1=1;
30
      ADCON0bits.CHS2=0;
31
      ADCON0bits.CHS3=0;
32
      break;
33
    case 3:
34
      ADCON0bits.CHS0=1;
35
      ADCON0bits.CHS1=1;
36
      ADCON0bits.CHS2=0;
37
      ADCON0bits.CHS3=0;
38
      break;
39
    case 4:
40
      ADCON0bits.CHS0=0;
41
      ADCON0bits.CHS1=0;
42
      ADCON0bits.CHS2=1;
43
      ADCON0bits.CHS3=0;
44
      break;
45
    case 5:
46
      ADCON0bits.CHS0=1;
47
      ADCON0bits.CHS1=0;
48
      ADCON0bits.CHS2=1;
49
      ADCON0bits.CHS3=0;
50
      break;
51
    case 6:
52
      ADCON0bits.CHS0=0;
53
      ADCON0bits.CHS1=1;
54
      ADCON0bits.CHS2=1;
55
      ADCON0bits.CHS3=0;
56
      break;
57
    case 7:
58
      ADCON0bits.CHS0=1;
59
      ADCON0bits.CHS1=1;
60
      ADCON0bits.CHS2=1;
61
      ADCON0bits.CHS3=0;
62
      break;
63
    case 8:
64
      ADCON0bits.CHS0=0;
65
      ADCON0bits.CHS1=0;
66
      ADCON0bits.CHS2=0;
67
      ADCON0bits.CHS3=1;
68
      break;
69
    case 9:
70
      ADCON0bits.CHS0=1;
71
      ADCON0bits.CHS1=0;
72
      ADCON0bits.CHS2=0;
73
      ADCON0bits.CHS3=1;
74
      break;
75
    case 10:
76
      ADCON0bits.CHS0=0;
77
      ADCON0bits.CHS1=1;
78
      ADCON0bits.CHS2=0;
79
      ADCON0bits.CHS3=1;
80
      break;
81
    case 11:
82
      ADCON0bits.CHS0=1;
83
      ADCON0bits.CHS1=1;
84
      ADCON0bits.CHS2=0;
85
      ADCON0bits.CHS3=1;
86
      break;
87
    case 12:
88
      ADCON0bits.CHS0=0;
89
      ADCON0bits.CHS1=0;
90
      ADCON0bits.CHS2=1;
91
      ADCON0bits.CHS3=1;
92
      break;
93
    default:
94
      ADCON0bits.CHS0=0;
95
      ADCON0bits.CHS1=0;
96
      ADCON0bits.CHS2=0;
97
      ADCON0bits.CHS3=0;
98
    }
99

100
  ADCON0bits.GO = 1;              // Start AD conversion
101
    while(ADCON0bits.NOT_DONE);     // Wait for conversion
102
  ADWERT=ADRESH;
103
  ADWERT=ADWERT<<8;
104
  ADWERT=ADWERT+ADRESL;
105
  return ADWERT;
106
}


Gruß Sascha
OP Persönliche Seite #1408607
Lesenswert?

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?
OP Persönliche Seite #1408697
Lesenswert?

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 =)
Persönliche Seite #1408728
Lesenswert?

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
unsigned int ADWERT;
3
unsigned int ADCe;
4

5
#pragma code
6
void main(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
void Setup_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
void Read_ADC(unsigned char Channel)
44
{
45
//  unsigned int ADWERT; // fällt weg, da global definiert!!!
46
  switch(Channel)
47
    {
48
    case 0:
49
      ADCON0bits.CHS0=0;
50
      ADCON0bits.CHS1=0;
51
      ADCON0bits.CHS2=0;
52
      ADCON0bits.CHS3=0;
53
      break;
54
    case 1:
55
      ADCON0bits.CHS0=1;
56
      ADCON0bits.CHS1=0;
57
      ADCON0bits.CHS2=0;
58
      ADCON0bits.CHS3=0;
59
      break;
60
    case 2:
61
      ADCON0bits.CHS0=0;
62
      ADCON0bits.CHS1=1;
63
      ADCON0bits.CHS2=0;
64
      ADCON0bits.CHS3=0;
65
      break;
66
    case 3:
67
      ADCON0bits.CHS0=1;
68
      ADCON0bits.CHS1=1;
69
      ADCON0bits.CHS2=0;
70
      ADCON0bits.CHS3=0;
71
      break;
72
    case 4:
73
      ADCON0bits.CHS0=0;
74
      ADCON0bits.CHS1=0;
75
      ADCON0bits.CHS2=1;
76
      ADCON0bits.CHS3=0;
77
      break;
78
    case 5:
79
      ADCON0bits.CHS0=1;
80
      ADCON0bits.CHS1=0;
81
      ADCON0bits.CHS2=1;
82
      ADCON0bits.CHS3=0;
83
      break;
84
    case 6:
85
      ADCON0bits.CHS0=0;
86
      ADCON0bits.CHS1=1;
87
      ADCON0bits.CHS2=1;
88
      ADCON0bits.CHS3=0;
89
      break;
90
    case 7:
91
      ADCON0bits.CHS0=1;
92
      ADCON0bits.CHS1=1;
93
      ADCON0bits.CHS2=1;
94
      ADCON0bits.CHS3=0;
95
      break;
96
    case 8:
97
      ADCON0bits.CHS0=0;
98
      ADCON0bits.CHS1=0;
99
      ADCON0bits.CHS2=0;
100
      ADCON0bits.CHS3=1;
101
      break;
102
    case 9:
103
      ADCON0bits.CHS0=1;
104
      ADCON0bits.CHS1=0;
105
      ADCON0bits.CHS2=0;
106
      ADCON0bits.CHS3=1;
107
      break;
108
    case 10:
109
      ADCON0bits.CHS0=0;
110
      ADCON0bits.CHS1=1;
111
      ADCON0bits.CHS2=0;
112
      ADCON0bits.CHS3=1;
113
      break;
114
    case 11:
115
      ADCON0bits.CHS0=1;
116
      ADCON0bits.CHS1=1;
117
      ADCON0bits.CHS2=0;
118
      ADCON0bits.CHS3=1;
119
      break;
120
    case 12:
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren