Forum: Mikrocontroller und Digitale Elektronik C Programmierung struktur, pointrer


von Gast (Gast)


Lesenswert?

Ich habe hier kleine logische Verständnisprobleme:


Hier wird eine Struktur definiert mit dem Namen Zugriff.
Ich stelle mir ds so vor:
int x = (int test, char test_2) Zugriff
Also eine Variable Zugriff von Typ(int test, char test)
1
typedef struct  
2
{
3
    int test;
4
   char test_2;
5
6
} Zugriff; 
7
8
Hier wird eine Variable definiert (com_var_1), die auf Struktur Zugriff verweist.
9
Also hat diese Variable alle in Stuct definierte Datentypen?
10
11
 Zugriff com_var_1;

In main() wird die funktion aufgerufen mit der Adresse der Variable 
com_var_1.
Also habe ich die Funktion mit den Adressen von Werten int test, char 
test_2 aufgerufen?
In com_var_1
1
int main (void) 
2
{
3
  funktion_mit_pcd_werten_fuehlen(&com_var_1);
4
}

In dieser Funktion befühle ich die Struktur Zugriff mit Werten, die ich 
mit der Pointervariable *pointer an die Struktur übergeben.
1
 funktion_mit_pcd_werten_fuehlen(COM_TYP *pointer)
2
{
3
  (*pointer).baudrate = 9600;
4
  (*pointer).dataBits = 8;
5
  (*pointer).stopBits =  2;
6
  (*pointer).parity   =1;
7
  (*pointer).PCD_adress = 77;
8
}
Das Resultat:
funktion_mit_pcd_werten_fuehlen(&com_var_1) holt sich die 
Werte(Adressen) aus der Struktur.
funktion_mit_pcd_werten_fuehlen(COM_TYP *pointer) befühlt diese mit 
konkreten Werten.

Ist das so richtig?

von yalu (Gast)


Lesenswert?

> Ist das so richtig?

Ja, wobei der Typ des Arguments com_var_1 aber COM_TYP * und nicht
Zugriff * sein muss.

Außerdem:
1
  (*pointer).baudrate = 9600;

schreibt man üblicherweise so:
1
  pointer->baudrate = 9600;

Das ist zwar semantisch das Gleiche, aber etwas übersichtlicher und
weniger Tipparbeit.

> funktion_mit_pcd_werten_fuehlen(COM_TYP *pointer) befühlt diese mit
> konkreten Werten.

Ich habe das Gefüll, du solltest noch ein klein wenig an deiner
Rechtschreibung feilen ;-)

von Tuffke (Gast)


Lesenswert?

Hallo!

> Hier wird eine Variable definiert (com_var_1), die auf Struktur Zugriff 
verweist.
> Also hat diese Variable alle in Stuct definierte Datentypen?
--> Na ja! Also Typedef definiert keine wirklichen Speicherbereich so 
wie es Variablen tun. In erster Linie ist ein struct nur eine Art 
Schablone, wie die Speicherbereiche einer Variable logisch zugeordnet 
werden.

> Zugriff com_var_1;
--> Erst hiermit wird wirklich Speicher reserviert. An der Adresse von 
der Variablen com_var_1 findest Du eine Struktur der Form "Zugriff", 
sprich, erst 4 Byte (?) die test repräsentieren, gefolgt von 1 Byte das 
test_2 darstellt.


> In main() wird die funktion aufgerufen mit der Adresse der Variable com_var_1.
> Also habe ich die Funktion mit den Adressen von Werten int test, char test_2 
aufgerufen?
--> Nein, es ist so wie Du davor geschrieben hast. Du rufst die Funktion 
mit der Adresse von com_var_1 auf. Der Kompiler "weiß" jedoch, dass 
diese Variable den Typ Zugriff ist und daher kann man darin 
(*pointer).test verwenden. Der Kompiler übersetzt dann wie folgt:
1
(*pointer).test  --> Speicheradresse = Basisadresse von com_var_1 (z.B. [003] )
2
(*pointer).test2 --> Speicheradresse = Basisadresse von com_var_1 + Größe von Test ( z.B. [007])


> funktion_mit_pcd_werten_fuehlen(COM_TYP *pointer)
> {
>   (*pointer).baudrate = 9600;
>   (*pointer).dataBits = 8;
>   (*pointer).stopBits =  2;
>   (*pointer).parity   =1;
>   (*pointer).PCD_adress = 77;
> }

Ok, Dein struct heißt dann eigentlich COM_TYP, oder? ;-)
Der Typ in der Variablen in main() als auch hier in dieser Funktion 
sollte der Selbe sein - damit das funktioniert.
Also gehört dann eher sowas dazu:
1
typedef struct  
2
{
3
 int  baudrate;
4
 char dataBits;
5
 char stopBits;
6
 char parity;
7
 char PCD_adress;
8
} COM_TYP;

Gruß Tuffke

P.S.: Es heißt befüLLen nicht befüHLen ... wobei das andere eigentlich 
auch eine schöne Vorstellung ist ... :-D

von Gast (Gast)


Lesenswert?

Danke, konstruktive Kritik ist zur Kenntniss genommen!:)

Im nächsten Schritt will ich UART mit Daten füttern:

  baudrate = 9600;
  dataBits = 8;
  stopBits =  2;
  parity   = 1;

main()
Aufruf der Funktion mit der Adresse von com_var_1, diese verweist auf 
die Struktur mit Daten.

1
uart0_init(&com_var_1);


Die Funktion bekommt konkrete Werte (z.B dataBits = 8)
1
int uart0_init( COM_TYP *pointer )
2
{ 
3
  unsigned char dataBits;
4
  unsigned char stopBits;
5
  unsigned char parity;
6
  unsigned long int baudrate;
7
        unsigned char Temp;
8
   
9
Abfrage: Wie viele dataBits, laut Definition 8
10
  ........
11
12
       if (dataBits == 8)
13
    Temp |= 0x03;
14
  else if (dataBits ==  7)
15
    Temp |= 0x02;
16
  else
17
    return(1);
18
19
  .......
20
21
Register U0LCR erhält 8 dataBits
22
  U0LCR  = Temp;


Leider liefert die Funktione int uart0_init( COM_TYP *pointer ) keine 
richtigen Werte an die IF-Abfragen.
Wenn ich in der Funktion die Variablen Fest definiere z.B. :unsigned 
char dataBits=8;
Dann werden die Register richtig gesetzt, Also es liegt nicht an den 
Abfragen.


Hilfe.

von Gast (Gast)


Lesenswert?

Danke für die tolle Erkläreung.
Ja min struct-Type heißt COM_TYP

Diese Werte brauch ich eigenlich in der Funktin nicht zu deklarieren
1
  unsigned char dataBits;
2
  unsigned char stopBits;
3
  unsigned char parity;
4
  unsigned long int baudrate;


diese müssen doch durch COM_TYP *pointer an die Funktion übergeben 
werden
int uart0_init( COM_TYP *pointer )

Das passiert aber nicht, der Compiler meldet:
Blinky.c(52): error:  #20: identifier "dataBits" is undefined
Also erhält er die Werte nicht.

von Sebastian B. (mircobolle)


Lesenswert?

Gast schrieb:
> Danke, konstruktive Kritik ist zur Kenntniss genommen!:)
>
> Im nächsten Schritt will ich UART mit Daten füttern:
>
>   baudrate = 9600;
>   dataBits = 8;
>   stopBits =  2;
>   parity   = 1;
>
> main()
> Aufruf der Funktion mit der Adresse von com_var_1, diese verweist auf
> die Struktur mit Daten.
>
>
>
1
uart0_init(&com_var_1);
>
>
> Die Funktion bekommt konkrete Werte (z.B dataBits = 8)
>
1
> int uart0_init( COM_TYP *pointer )
2
> {
3
>   unsigned char dataBits;
4
>   unsigned char stopBits;
5
>   unsigned char parity;
6
>   unsigned long int baudrate;
7
>         unsigned char Temp;
8
9
Hast du das hier nur zum Test deklariert?
10
11
> 
12
> Abfrage: Wie viele dataBits, laut Definition 8
13
>   ........
14
> 
15
>        if (dataBits == 8)
16
>     Temp |= 0x03;
17
>   else if (dataBits ==  7)
18
>     Temp |= 0x02;
19
>   else
20
>     return(1);
21
> 
22
ich würde daraus erstmal ein switch-case machen ist übersichtlicher:
23
24
switch(dataBits)
25
{
26
case 8:
27
Temp |= 0x03;
28
break;
29
case 7:
30
break;
31
Temp |= 0x02;
32
default:
33
break;
34
}
35
>   .......
36
> 
37
> Register U0LCR erhält 8 dataBits
38
>   U0LCR  = Temp;
39
>
>
>

Mhm... also deine Datenstruktur die du übergibst muss natürlich 
initialisiert sein. Also in dataBits muss konkret auch ein vernünftiger 
Wert stehen.

Ansonsten sollte es keinen Unterschied machen, ob du die Werte lokal 
definierst und dann zuweist oder global definierst und dann zuweist.


> Leider liefert die Funktione int uart0_init( COM_TYP *pointer ) keine
> richtigen Werte an die IF-Abfragen.

Siehe oben.

> Wenn ich in der Funktion die Variablen Fest definiere z.B. :unsigned
> char dataBits=8;
> Dann werden die Register richtig gesetzt, Also es liegt nicht an den
> Abfragen.

Richtig, der Fehler muss als bei der Übergabe deiner globalen 
Datenstruktur an deine lokale Variable liegen.

Warum legst du eigentlich noch eine lokale Variable an? Du hast wohl 
zuviel Stack oder wie? ;)

Gruß

>
> Hilfe.

von Sergey S. (Firma: ARM LPC2134, uVision3, in C) (serik00)


Lesenswert?

So Leute das ist mein kompletter Quellcode.

Der Funktion(int uart0_init(COM_TYP *pointer))
müssen diese Werte übergeben werden:

   pointer->baudrate = 9600;
   pointer->dataBits = 8;
   pointer->stopBits =  1;
   pointer->parity   =   0;
   pointer->PCD_adress = 77;


funktion_mit_pcd_werten_fuellen(COM_TYP *pointer)
 {
   pointer->baudrate = 9600;
   pointer->dataBits = 8;
   pointer->stopBits =  1;
   pointer->parity   =   0;
   pointer->PCD_adress = 77;
 }

Wie läuft die Übergabe.
Bin bemühter Anfänger.
Vielen Dank im Voraus.

1
#include <stdio.h>                         /* standard I/O .h-file */
2
#include <LPC213x.H>                       /* LPC213x definitions  */
3
4
 typedef struct  
5
{
6
   unsigned long int baudrate;
7
  unsigned char dataBits;
8
  unsigned char stopBits;
9
  unsigned char parity;
10
  unsigned char PCD_adress;
11
} COM_TYP; 
12
13
 COM_TYP com_var_1;
14
/******************************************************************************/
15
 void init_serial (void)  
16
{               
17
  IODIR1  =   0x03000000;          /* LEDs P1.24,P1.23 defined as Outputs  */          
18
     PINSEL0  =  0x00050005;      /*Enable TxD1,TxD0,RxD1,RxD0*/
19
  IODIR0  =  0x10400410;      /*OUT: RTS0_P0.4, RTS1_P0.14, COM1_P0.22, COM0_P0.28*/
20
  IOCLR0  =  0x10400010;      /*LOW auf 0 COM1,0 = 0(RS485), RTS0=0(Sender)*/
21
  IOSET0  =  0x00000400;      /*HIGH auf 1 RTS1=1(Empfänger),P0.10*/                           
22
}
23
/******************************************************************************/
24
void init_uart1(void)
25
{
26
  U1LCR    =  0x83;    /*8 bits, 1 stopbit, no Parity, enable DLAB*/
27
  U1DLM    =  0x01;    /*9600 Baud Rate, 55.296.000 PCLK*/
28
  U1DLL    =  0x68;    /*360dez=0x0168*/
29
  U1LCR    =  0x03;    /*disable DLAB*/
30
  U1FCR    =  0x01;    /*enable UART1-FIFO*/ 
31
}
32
/******************************************************************************/
33
funktion_mit_pcd_werten_fuellen(COM_TYP *pointer)
34
 {
35
   pointer->baudrate = 9600;
36
   pointer->dataBits = 8;
37
   pointer->stopBits =  1;
38
   pointer->parity =   0;
39
   pointer->PCD_adress = 77;
40
 }
41
/******************************************************************************/
42
int uart0_init(COM_TYP *pointer)
43
{ 
44
  unsigned char ucTemp;
45
46
  ucTemp = 0;
47
  // Word Lenght Select
48
  if (dataBits == 8)
49
    ucTemp |= 0x03;
50
  else if (dataBits ==  7)
51
    ucTemp |= 0x02;
52
  else
53
    return(1);
54
55
  // Stop Bit Select
56
  if (stopBits == 1 )
57
    ucTemp |= 0x00;
58
  else if ( stopBits == 2 )
59
    ucTemp |= 0x04;
60
  else
61
    return(1);
62
63
  // Parity Enable
64
   if (parity == 0)    //disable
65
     ucTemp |= 0x00;
66
  else if (parity == 1)  //enable
67
    ucTemp |= 0x04;
68
  else
69
    return(1);
70
71
  //Parity Select
72
  if (parity == 'o')
73
    ucTemp |= 0x00;
74
  else if (parity == 'e')
75
    ucTemp |= 0x10;
76
  else if (parity == 1)
77
    ucTemp |= 0x20;
78
  else if (parity == 0)
79
    ucTemp |= 0x30;
80
  else
81
    return(1);
82
83
  // Devisor Latch Access Bit(DLAB) enable
84
  ucTemp |= 0x80; 
85
  U0LCR  =  ucTemp;    /*8 bits, 1 stopbit, no Parity, enable DLAB*/
86
87
  // Baudrate Select  
88
  switch ( baudrate )
89
  {
90
    case 4800:  
91
      U0DLM    =  0x02;    /*4800 Baud Rate, 55.296.000 PCLK*/
92
      U0DLL    =  0xD0;    /*720dez=0x02Do*/
93
      break; 
94
    case 9600:  
95
      U0DLM    =  0x01;    /*9600 Baud Rate, 55.296.000 PCLK*/
96
      U0DLL    =  0x68;    /*360dez=0x0168*/
97
      break; 
98
    case 19200:  
99
      U0DLM    =  0x00;    /*19200 Baud Rate, 55.296.000 PCLK*/
100
      U0DLL    =  0x64;    /*180dez=0x0064*/
101
      break; 
102
    case 38400:  
103
      U0DLM    =  0x00;    /*38400 Baud Rate, 55.296.000 PCLK*/
104
      U0DLL    =  0x5A;    /*90dez=0x005A*/
105
      break; 
106
    case 76800:  
107
      U0DLM    =  0x00;    /*9600 Baud Rate, 55.296.000 PCLK*/
108
      U0DLL    =  0x68;    /*45dez=0x003D*/
109
      break; 
110
    default:
111
      //return(ERR_COM_INIT_LINE_SETTINGS);
112
      break;
113
      
114
  }
115
116
  // Devisor Latch Access Bit(DLAB) disable
117
  ucTemp = 0;
118
  ucTemp |= 0x00;
119
  U0LCR    =  ucTemp;
120
  
121
  //FIFO UART enable    
122
  U0FCR    =  0x01;
123
  return 1;    
124
}
125
/******************************************************************************/
126
void sendchar (void)  {                 /* Write character to Serial Port    */
127
  while (!(U0LSR & 0x20));
128
  (U0THR = 0x89);
129
  (U0THR = 0x89);
130
  (U0THR = 0x89);
131
  (U0THR = 0x89);
132
  (U0THR = 0x89);
133
  (U0THR = 0x89);
134
  (U0THR = 0x89);
135
  (U0THR = 0x89);
136
}
137
/******************************************************************************/
138
int receivechar (void)  {                     /* Read character from Serial Port   */
139
140
  while (!(U1LSR & 0x01));
141
142
  return (U1RBR);
143
}
144
/******************************************************************************/
145
146
int main (void) 
147
{
148
 
149
  init_serial();                   /* Initialize Serial Interface   */
150
  funktion_mit_pcd_werten_fuellen(&com_var_1);
151
  init_uart1();
152
  uart0_init(&com_var_1);
153
  do 
154
  {                               /* Loop forever */
155
  {
156
   sendchar ();
157
  }
158
  }  while(1);
159
}

von Sergey S. (Firma: ARM LPC2134, uVision3, in C) (serik00)


Lesenswert?

Hab das Problem endllich gelöst und zwar der Zugriff auf die Variablen 
muss so erfolgen:
pointer->Variable


  ucTemp = 0;
  // Word Lenght Select
  if (pointer->dataBits == 8)
    ucTemp |= 0x03;
  else if (pointer->dataBits ==  7)
    ucTemp |= 0x02;
  else
    return(1);

  // Stop Bit Select
  if (pointer->stopBits == 1 )
    ucTemp |= 0x00;
  else if ( pointer->stopBits == 2 )
    ucTemp |= 0x04;
  else
    return(1);

  // Parity Enable
   if (pointer->parity == 0)    //disable
     ucTemp |= 0x00;
  else if (pointer->parity == 1)  //enable
    ucTemp |= 0x04;
  else
    return(1);

  //Parity Select
  if (pointer->parity == 'o')
    ucTemp |= 0x00;
  else if (pointer->parity == 'e')
    ucTemp |= 0x10;
  else if (pointer->parity == 1)
    ucTemp |= 0x20;
  else if (pointer->parity == 0)
    ucTemp |= 0x30;
  else

von Sebastian B. (mircobolle)


Lesenswert?

Eugen Spaß schrieb:
> Hab das Problem endllich gelöst und zwar der Zugriff auf die Variablen
> muss so erfolgen:
> pointer->Variable

Richtig. Aus dem ersten Codeschnippsel kam nicht heraus was du 
tatsächlich falsch gemacht hast.

Noch eine kleine Anmerkung:
Mehrere returns innerhalb einer Funktion sind unschön und eine 
potentielle Fehlerquelle. Gut, in dieser kleinen Funktion vielleicht 
noch nicht, aber wenn man den Stil beibehält, fängt man sich früher oder 
später Probleme ein.

Besser:
sich oben eine return Variable definieren. Diese dann im 
Funktionsverlauf setzen (dort wo du direkt dein return gemacht hättest) 
und dann am Ende EIN return.

Gruß

PS: Ist es Absicht, dass du bei parity und stop bit die gleichen Bits 
setzt?!

>
>
>   ucTemp = 0;
>   // Word Lenght Select
>   if (pointer->dataBits == 8)
>     ucTemp |= 0x03;
>   else if (pointer->dataBits ==  7)
>     ucTemp |= 0x02;
>   else
>     return(1);
>
>   // Stop Bit Select
>   if (pointer->stopBits == 1 )
>     ucTemp |= 0x00;
>   else if ( pointer->stopBits == 2 )
>     ucTemp |= 0x04;
>   else
>     return(1);
>
>   // Parity Enable
>    if (pointer->parity == 0)    //disable
>      ucTemp |= 0x00;
>   else if (pointer->parity == 1)  //enable
>     ucTemp |= 0x04;
>   else
>     return(1);
>
>   //Parity Select
>   if (pointer->parity == 'o')
>     ucTemp |= 0x00;
>   else if (pointer->parity == 'e')
>     ucTemp |= 0x10;
>   else if (pointer->parity == 1)
>     ucTemp |= 0x20;
>   else if (pointer->parity == 0)
>     ucTemp |= 0x30;
>   else

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.