Forum: Mikrocontroller und Digitale Elektronik MSP430G2553 als Schnittstelle zwischen MODBUS und I2C


von Vadim D. (vendetta)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

zuerst möchte ich mich bedanken, dass es so eine tolle Community gibt – 
habe schon viel nützliches hier gelesen.

Projektbeschreibung:
In meinem Projekt muss ich ein Energieversorgungsmodul für ein autarkes 
System entwickeln. Das System selbst kommuniziert über den I2C-Bus und 
wird von einem Solarladeregler mit 12V Spannung versorgt. Damit man 
immer weiß, was der Laderegler tut bzw. wie groß sein Strom und Spannung 
sind, habe ich mir einen Laderegler Tracer 1215BN mit dem MODBUS 
ausgesucht. Nun ist das Problem, dass eine Schnittstelle zwischen dem 
MODBUS und dem I2C- organisiert werden muss. Dabei habe ich an den 
MSP430G2553 mit dem Transceiver SP3485 von SparkFun (Breakout RS485) 
gedacht, da sie, meiner Meinung nach, die Voraussetzungen dafür 
erfüllen.

Voraussetzungen:
Auf der I2C-Seite muss der Mikrocontroller als ein Slave-Gerät mit 
400KHz fungieren.
Auf der MODBUS-Seite ist der MSP430G2553 als Master-Gerät mit folgenden 
Einstellungen (laut dem MODBUS-Protokoll vom Laderegler) zu betreiben:
  Modus: RTU
  16bit MODBUS addresses (per the modbus.org spec)
  BPS: 115200 baud
  Parity: none
  Data bits: 8
  Stop bits: 1
  Flow control: none

Kommunikation:
Die Kommunikation zwischen dem System und dem Laderegler stelle ich mir 
folgendermaßen vor:
Das I2C-Master-System sendet eine Anfrage-Nachricht an den 
I2C-Slave-Mikrocontroller und löst eine Interrupt-Routine aus.
Der Mikrocontroller sendet eine Anfrage-Nachricht als Master per MODBUS 
an den Laderegler weiter. Um z.B. den Wert der aktuellen Spannung vom 
Laderegler zu bekommen, wird folgende Nachricht an den Laderegler 
geschickt: 01 04 31 04 00 01 7E F7
01    Device ID
04    Function Code
31 04 Register Address
00 01 Register Count
7E F7 CRC Summe
Der Laderegler antwortet darauf und sendet die Werte von Spannung und 
Strom, die im RAM vom Mikrocontroller gespeichert werden. Die 
Antwort-Nachricht für die Spannung würde z.B. folgendermaßen aussehen: 
01 04 02 04 CE 3A 64
Die hexadezimale Zahl 04 CE würde als dezimale Zahl dem Wert 1230 
entsprechen bzw. 12,3V.
Nachdem die Werte im Speicher vom Mikrocontroller abgelegt sind, werden 
diese per I2C-Bus an das I2C-Mastersystem weiter geschickt.

Frage:
Würde es so, wie ich es beschrieben habe, funktionieren oder ist das 
Konzept nicht zu realisieren?

Bin für jede Hilfe und Kritik sehr Dankbar!

von Nick (Gast)


Lesenswert?

Das sollte soweit als Gateway funktionieren. Die Baudrate kann ggf. Nach 
Gerät abweichen, also Blick ins Datenblatt.  Dazu im Hinterkopf 
behalten, dass je nach modbus Gerät die in ein Timeout laufen können, 
wenn nicht zyklisch Modus Pakete ankommen, aber auch dazu müsste was im 
Datenblatt stehen.

von Vadim D. (vendetta)


Lesenswert?

Danke für die rasche Antwort.
Mir war erstmal wichtig, ob es so überhaupt funktionieren würde.
Das mit der zyklischen Abfrage werde ich dann auch genau anschauen, aber 
soweit ich mich erinner kann, stand im Datenblatt nichts davon.

von Vadim D. (vendetta)


Angehängte Dateien:

Lesenswert?

Hab nun den MSP430G2553 soweit programmiert, dass ich eine Nachricht 
verschicken kann (Bild vom Oszi im Anhang). Allerdings antwortet der 
Laderegler auf die Anfrage nicht...

1. Warum kommt nichts zurück vom Laderegler?
Wenn ich die gleiche Anfrage [01 04 31 04 00 01 7E F7] per Simply Modbus 
Master vom PC->USB-Adapter->Laderegler schicke, dann antwortet mir auch 
der Laderegler zurück.

2. Beim Senden sollte die P1.0 LED angehen - dies passiert aber auch 
nicht...

Hier ist ebenfalls der Code, den ich benutze:
1
  //============================================================================//
2
  //       A small program to transmit a byte through the RS485 network         //
3
  //============================================================================//
4
    // MSP430G2553 on LaunchPad Development board Connected to SP3485.            //
5
    // Clocks   :- DC0 @ 1MHz ,SMCLK @1MHz                                        //
6
    // Baudrate :- 115200 bps                                                     //
7
    // [MSP430] P1.1(RXD) <- R0 [RS485](Receiver Output)                          //
8
    // [MSP430] P1.2(TXD) -> DI [RS485](Driver Input)                             //
9
    // [MSP430] P2.0      -> DE / RE [RS485](Driver Input/ Receiver Out Enable)   //
10
#include "msp430g2553.h"
11
//---------------------------------------------------------------------------------------------------------------------//
12
//                   Folgende Anfragen werden per MODBUS an den Solarladeregler gesendet.                       //
13
//---------------------------------------------------------------------------------------------------------------------//
14
                                      //CRC-MSB-----------------------------------|
15
                                      //CRC-LSB--------------------------------|  |
16
                                      //Registeranzahl-------------------|--|  |  |
17
                                      //Start-Adresse-----------|--|  |  |  |  |
18
                                      //Funktion----------------|  |  |  |  |  |  |
19
                                      //Slave-Adresse--------|  |  |  |  |  |  |  |
20
unsigned char BATT_VOLTAGE[8]= {0x01,0x04,0x31,0x04,0x00,0x01,0x7E,0xF7}; //Batteriespannung     01 04 31 04 00 01 7E F7;
21
//---------------------------------------------------------------------------------------------------------------------//
22
23
unsigned char *Pointer = BATT_VOLTAGE;
24
unsigned int TX_BYTE;
25
unsigned int RX_BYTE;
26
int i;
27
28
void send(unsigned char *DATA)
29
{
30
  P2OUT |= BIT0;            //Put SP3485 in Transmit Mode
31
  for(i=0;i<8;i++)
32
    {
33
        while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
34
      UCA0TXBUF = *DATA++;    // Ein Byte verschicken und Pointer inkrementieren
35
      __delay_cycles(4);      // 4µS Pause zwischen zwei Bytes
36
    }
37
  P2OUT &= ~BIT0;            //Put SP3485 in Receive Mode
38
}
39
40
void main(void)
41
    {
42
  WDTCTL = WDTPW + WDTHOLD;     // Stop the Watch dog
43
44
      //------------------- Configure the Clocks -------------------//
45
46
      if (CALBC1_1MHZ==0xFF)    // If calibration constant erased
47
         {
48
            while(1);              // do not load, trap CPU!!
49
         }
50
51
      DCOCTL  = 0;                 // Select lowest DCOx and MODx settings
52
      BCSCTL1 = CALBC1_1MHZ;       // Set range
53
      DCOCTL  = CALDCO_1MHZ;       // Set DCO step + modulation
54
55
      //---------------- Configuring the LED's ----------------------//
56
57
      P1DIR = 0xFF;     // P1.0 and P1.6 output
58
      P1OUT = 0;  // P1.0 and P1.6 = 0
59
60
    //--------- Setting the UART function for P1.1 & P1.2 ---------//
61
62
    P1SEL = BIT1 + BIT2;      // P1.1 UCA0RXD Eingang
63
    P1SEL2 = BIT1 + BIT2;      // P1.2 UCA0TXD Ausgang
64
65
    //------------ Configuring SP3485 Control Line ---------------//
66
67
    P2DIR = 0xFF;          // P2.0 Ausgang fuer DE und ~RE
68
    P2OUT = 0;           // P2.0 ist HIGH -> DE ist aktiviert und ~RO ist deaktiviert
69
70
    //------------ Configuring the UART(USCI_A0) ----------------//
71
72
      UCA0CTL1 |= UCSSEL_2;      // USCI Clock = SMCLK
73
      UCA0BR0   =  8;            // 8 From datasheet table-
74
      UCA0BR1   =  0;            // -selects baudrate =115200,clk = SMCLK
75
      UCA0MCTL = UCBRS2 + UCBRS0;   // Modulation UCBRSx = 5
76
      UCA0CTL1 &= ~UCSWRST;         // **Initialize USCI state machine**
77
78
      //---------------- Enabling the interrupts ------------------//
79
      //IE2 |= UCA0TXIE;              // Enable USCI_A0 TX interrupt
80
      //UC0IE |= UCA0TXIE; // Enable USCI_A0 TX interrupt
81
      IE2 |= UCA0RXIE;              // Enable USCI_A0 RX interrupt
82
      //_BIS_SR(GIE);                 // Enable the global interrupt
83
84
      __delay_cycles(5000000);
85
      send(Pointer);
86
      _BIS_SR(LPM0_bits + GIE);   // Going to LPM0
87
  }
88
89
//-----------------------------------------------------------------------//
90
//                Transmit and Receive interrupts                        //
91
//-----------------------------------------------------------------------//
92
93
#pragma vector = USCIAB0TX_VECTOR
94
__interrupt void USCI0TX_ISR(void)
95
{
96
  P1OUT  ^= BIT0;          //light up P1.0 Led on Tx
97
}
98
99
#pragma vector = USCIAB0RX_VECTOR  //UART RX USCI Interrupt. This triggers when the USCI receives a char
100
__interrupt void USCI0RX_ISR(void)
101
{
102
  P1OUT ^= BIT6;          // light up P1.6 LED on RX
103
104
105
  /*LPM0_EXIT;
106
  RX_BYTE = UCA0RXBUF;      //Beim Auslesen wird das Flag UCA0RXIFG gelöscht, aber nicht der UCA0RXBUF
107
  if(RX_BYTE == 0x01)        //Toggle green LED if "B" RXed
108
    {
109
    P1OUT ^= BIT6;          // light up P1.6 LED on RX
110
    }*/
111
  //IFG2 &= ~UCA0RXIFG;         // Clear RX flag
112
}
113
114
/*
115
int uart_putchar(int c)
116
{
117
    // Wait for the transmit buffer to be ready
118
    while (!(IFG2 & UCA0TXIFG));
119
120
    // Transmit data //
121
    UCA0TXBUF = (char ) c;
122
123
    return 0;
124
}
125
*/
126
127
128
/*
129
if(UCA0RXBUF == 0x66)              //Toggle red LED if "A" RXed
130
{
131
  P1OUT ^= BIT0;
132
}
133
134
if(UCA0RXBUF == 102)              //Toggle green LED if "B" RXed
135
{
136
  P1OUT ^= BIT6;
137
}
138
*/

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Daß die "Sende"-LED nicht angesteuert wird, ist klar, denn Du verwendest 
kein interruptgesteuertes Senden. Daher wird der Sendeinterrupt nie 
ausgelöst und Deine USCI0TX_ISR nie aufgerufen.

Woher stammt Dein Code zur Ansteuerung der USCI?

Du musst beim 'G2553 sehr genau hinsehen sein, der verwendet zwar wie 
diverse andere MSP430-Varianten auch die USCIA/B, aber mit einer 
ziemlich anderen Interruptverteilung.

von Vadim D. (vendetta)


Lesenswert?

Hallo Rufus,

ich dachte, dass die Sende-ISR wird dann aufgerufen, wenn in TX-Buffer 
was kopiert wird?

Den Code habe ich aus verschiedenen Quellen und Codes im Internet 
zusammengebastelt und er funktioniert, leider nur zum Teil.

Mir fehlt noch, glaube ich zumindest, Pull-UP und Pull-DOWN Widerstand 
am P2.0. Sehe ich das richtig? Mir gefällt das Signal am Oszi irgendwie 
nicht - zu viele Spikes...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Vadim D. schrieb:
> ich dachte, dass die Sende-ISR wird dann aufgerufen, wenn in TX-Buffer
> was kopiert wird?

Nur, wenn der entsprechende Interrupt auch aktiviert ist. Ist er aber 
nicht.

von Vadim D. (vendetta)


Lesenswert?

Rufus Τ. F. schrieb:
> Vadim D. schrieb:
>> ich dachte, dass die Sende-ISR wird dann aufgerufen, wenn in TX-Buffer
>> was kopiert wird?
>
> Nur, wenn der entsprechende Interrupt auch aktiviert ist. Ist er aber
> nicht.

Meinst du dann diese Zeile im Code?
IE2 |= UCA0TXIE;              // Enable USCI_A0 TX interrupt?

Wenn ich sie wieder einklammere, dann geht die P1.0 LED an, selbst wenn 
ich in den TX-Puffer nichts reinschreibe...

Habe ich da einen Denkfehler?

von Max G. (l0wside) Benutzerseite


Lesenswert?

Vadim D. schrieb:

> ich dachte, dass die Sende-ISR wird dann aufgerufen, wenn in TX-Buffer
> was kopiert wird?

Nein. Die Sende-ISR wird aufgerufen, wenn
* der Interrupt aktiviert ist und
* der Sendepuffer leer ist

Der typische Code in der Sende-ISR lautet deswegen
1. Hole nächstes zu sendendes Zeichen
2. Schreibe dieses Zeichen in den Sendepuffer

> Mir gefällt das Signal am Oszi irgendwie nicht - zu viele Spikes...

Das Signal ist doch top.

Max

von Vadim D. (vendetta)


Lesenswert?

Max G. schrieb:
> Vadim D. schrieb:
>
>> ich dachte, dass die Sende-ISR wird dann aufgerufen, wenn in TX-Buffer
>> was kopiert wird?
>
> Nein. Die Sende-ISR wird aufgerufen, wenn
> * der Interrupt aktiviert ist und
> * der Sendepuffer leer ist
>
> Der typische Code in der Sende-ISR lautet deswegen
> 1. Hole nächstes zu sendendes Zeichen
> 2. Schreibe dieses Zeichen in den Sendepuffer
>
>> Mir gefällt das Signal am Oszi irgendwie nicht - zu viele Spikes...
>
> Das Signal ist doch top.
>
> Max

Das mit der Sende-ISR muss ich mich noch beschäftigen...

Aber wenn das Signal in Ordnung ist und auf die gleiche Anfrage vom PC 
der Laderegler sich meldet, warum antwortet er dann in diesem Fall 
nicht?

Ich habe zwischen zwei Bytes eine Pause von 4µS und laut dem MODBUS 
Protokoll müssen es mindestens 3,5µS sein. Mir fällt da momentan nichts 
mehr ein, was ich noch jetzt machen bzw. ändern kann.

von Vadim D. (vendetta)


Angehängte Dateien:

Lesenswert?

Ich habe gerade das Signal noch mal am Oszi angeschaut und es zeigt ein 
Schwingverhalten, was vllt. aber wiederum normal sein kann?

von re (Gast)


Lesenswert?

das sind 100ns pro Abschnitt, das Schwingen ist vollkommen normal bzw 
ein Messfehler, darüber brauchst du dir keine Gedanken zu machen, wenn 
du die Schleife zwischen Messspitze und Messmasse kleiner machst wird 
das Schwingen auch kleiner.

von Vadim D. (vendetta)


Lesenswert?

Das beruhigt etwas :)

Ich werde nun das Signal vom PC für die gleiche Anfrage wie beim µC am 
OSZI anschauen - vllt. sehe ich da dann mehr...

von Vadim D. (vendetta)


Angehängte Dateien:

Lesenswert?

Also ich sehe schon einen gewaltigen Unterschied zwischen dem PC und µC 
beim Versenden der gleichen Anfrage - 01 04 31 04 00 01 7E F7.
Die Anfrage vom PC ist ungefähr 700µS lang und hat am Anfang zwei 
Zeichen gleicher Länge. Bei dieser Anfrage meldet sich der Laderegler 
und sendet eine Antwort.
Beim µC ist die Anfrage ca. 600µS lang und hat am Anfang zwei Zeichen 
mit gleicher Länge nicht.
Screenshots 09,10,11 im Anhang sind vom PC und 07 vom µC.

: Bearbeitet durch User
von Max G. (l0wside) Benutzerseite


Lesenswert?

Wenn man beim PC nun noch etwas erkennen würde...

Was zeigen CH1 und CH2? Während der Übertragung sind beide zueinander 
invers, außerhalb der Übertragung beide Null. Oder sehe ich das falsch?

Max

von Vadim D. (vendetta)


Lesenswert?

Max G. schrieb:
> Wenn man beim PC nun noch etwas erkennen würde...
>
> Was zeigen CH1 und CH2? Während der Übertragung sind beide zueinander
> invers, außerhalb der Übertragung beide Null. Oder sehe ich das falsch?
>
> Max

Bei dem Protokoll wird eine Nachricht verschickt, die über die 
Potenzialdifferenz zwischen dem Kanal A und B übertragen wird. Je 
nachdem, ob zwischen der Datenleitung A und B eine Differenzspannung von 
mind. +/-200mV vorhanden ist, wird eintweder eine 1 oder 0 übertragen.
Bei mir sind beide Leitungen vor dem Übertragen auf GND, so sehe ich es 
zumindest...

von Max G. (l0wside) Benutzerseite


Lesenswert?

OK, danke.

Kannst du die Screenshots der µC-Variante noch mal mit einem Offset 
machen, so dass man auch tatsächlich etwas sieht? Die beiden Linien 
liegen dermaßen übereinander, dass das Nutzsignal nur schwer zu erkennen 
ist. Beim PC-Signal (letztes Bild) ist es ok.

Du könntest alternativ dein Oszi auch per Math-Mode dazu bringen, die 
Differenz der Kanäle auszugeben. Das wäre sogar noch besser.

Und: wo sehe ich eigentlich die zeitliche Auflösung?

Max

von Vadim D. (vendetta)


Angehängte Dateien:

Lesenswert?

Max G. schrieb:
> OK, danke.
>
> Kannst du die Screenshots der µC-Variante noch mal mit einem Offset
> machen, so dass man auch tatsächlich etwas sieht? Die beiden Linien
> liegen dermaßen übereinander, dass das Nutzsignal nur schwer zu erkennen
> ist. Beim PC-Signal (letztes Bild) ist es ok.
>
> Du könntest alternativ dein Oszi auch per Math-Mode dazu bringen, die
> Differenz der Kanäle auszugeben. Das wäre sogar noch besser.
>
> Und: wo sehe ich eigentlich die zeitliche Auflösung?
>
> Max

Im Anhang sind nun alle Screenshots vom µC-Signal.
Die Zeitliche Auflösung steht oben links bei TB.

Mich stört gerade, dass die beiden Signale unterschiedliche Länge 
aufweisen und gar nicht ähnlich sogar am Anfang sind...

Die Math-Mode Funktion ist mir nicht bekannt. Würde dies was bringen? 
Ich meine bloß ich bin der Meinung das Problem liegt eher am falschen 
Signal, das mein µC liefert.

Weiss aber ehrlich gesagt noch nicht warum...

: Bearbeitet durch User
von Vadim D. (vendetta)


Angehängte Dateien:

Lesenswert?

Laut dem MODBUS-Protokoll vom Laderegler handelt es sich um die folgende 
Übertragungsart:
  Modus: RTU
  16bit MODBUS addresses (per the modbus.org spec)
  BPS: 115200 baud (ca. 8,7µS pro Bit)
  Parity: none
  Data bits: 8
  Stop bits: 1
  Flow control: none

Es heißt es sind pro Frame
- 1 Startbit
- 8 Databit
- 1 Stopbit
zu versenden.

Dazu kommt eine Sendepause zwischen 2 Frames von mind. 3,5 µS.
Somit komme ich bei einer Nachricht 01 04 31 04 00 01 7E F7 auf:
8,7µS * 10 (Bit) * 8 (Frames) = 696µS - dies sehe ich auch beim 
PC-Signal(siehe Bild - PC-Signal).

Das µC-Signal mit gleicher Nachricht ist aber kürzer und es sind ca. 
580µS(siehe Bild - µC-Signal).

Wenn ich nun aber nun 1 Byte (0x01) vom µC sende, dann sieht alles top 
aus (siehe Bild - 1 Byte 0x01).

Warum schickt dann der µC die Nachricht nicht komplett?

Jemand eine Idee?

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Miss doch mal nicht am Ausgang Deines CAN-Transceivers, sondern direkt 
am TxD-Ausgang Deines 'G2553.

von Vadim D. (vendetta)


Angehängte Dateien:

Lesenswert?

Also ich habe es hingekriegt!)

Die Anfrage vom µC fiel mir, wie ich schon sagte, etwas kurz auf.
Dann habe ich eine Pause beim Versenden von 2 Bytes hinzugefügt und dann 
am Ende fehlten mir noch 40µS mit dem HIGH Signal (siehe Bild: Signal 
mit Pause). Danach ist es mir gelungen, die Antwort von meinem 
Laderegler zu bekommen (siehe Bild: Anfrage mit Antwort).
Die Anfrage vom µC und die Antwort vom Laderegler sind im Bild 
verschoben, da sie unterschiedliche Groundpotentiale haben: beim µC 
Stromversorgung vom PC und beim Laderegler Stromversorgung von 
Autobatterie. Der DC-DC Wandler für den µC ist momentan nicht 
funktionsfähig, sobald ich einen neuen bekomme, werde ich die Potentiale 
ausgleichen können und das Problem sollte gelöst sein.

Ich hätte aber noch zwei Fragen:

1. In meinem Code verwende ich einen Pointer, der auf eins von 6 Frames 
(Zeilen 20 bis 25) zeigt. Kann ich zum Versenden dieser Frames nur einen 
Pointer mit einer Schleife organisieren oder ist für jedes Frame ein 
eigener Pointer notwendig?

2. Wie würdet ihr das Frame vom Laderegler z.B. [01 04 02 04 CE 3A 64] 
im Speicherregister des µC für weitere Bearbeitung bzw. Weitersenden per 
I2C speichern? Gibt es vllt. irgendwo ein gutes Beispiel?

Hier ist der aktuelle Code, mit dem es bei mir funktioniert:
1
  //============================================================================//
2
  //       A small program to transmit a frames through the RS485 network         //
3
  //============================================================================//
4
    // MSP430G2553 on LaunchPad Development board Connected to SP3485.            //
5
    // Clocks   :- DC0 @ 1MHz ,SMCLK @1MHz                                        //
6
    // Baudrate :- 115200 bps                                                     //
7
    // [MSP430] P1.1(RXD) <- R0 [RS485](Receiver Output)                          //
8
    // [MSP430] P1.2(TXD) -> DI [RS485](Driver Input)                             //
9
    // [MSP430] P2.0      -> DE / RE [RS485](Driver Input/ Receiver Out Enable)   //
10
#include "msp430g2553.h"
11
//---------------------------------------------------------------------------------------------------------------------//
12
//                   Folgende Frames werden per MODBUS an den Solarladeregler gesendet.                       //
13
//---------------------------------------------------------------------------------------------------------------------//
14
                                      //CRC-MSB-----------------------------------|
15
                                      //CRC-LSB--------------------------------|  |
16
                                      //Registeranzahl-------------------|--|  |  |
17
                                      //Start-Adresse-----------|--|  |  |  |  |  |
18
                                      //Funktion----------------|  |  |  |  |  |  |
19
                                      //Slave-Adresse--------|  |  |  |  |  |  |  |
20
unsigned char BATT_VOLTAGE[8]= {0x01,0x04,0x31,0x04,0x00,0x01,0x7E,0xF7}; //Batteriespannung     01 04 31 04 00 01 7E F7;
21
unsigned char BATT_CURRENT[8]= {0x01,0x04,0x31,0x05,0x00,0x01,0x2F,0x37}; //Ladestrom        01 04 31 05 00 01 2F 37;
22
unsigned char LOAD_VOLTAGE[8]= {0x01,0x04,0x31,0x0C,0x00,0x01,0xFF,0x35}; //Lastspannung          01 04 31 0C 00 01 FF 35;
23
unsigned char LOAD_CURRENT[8]= {0x01,0x04,0x31,0x0D,0x00,0x01,0xAE,0xF5}; //Laststrom        01 04 31 0D 00 01 AE F5;
24
unsigned char CHARGER_TEMP[8]= {0x01,0x04,0x31,0x11,0x00,0x01,0x6F,0x33}; //Ladereglertemperatur 01 04 31 11 00 01 6F 33;
25
unsigned char RSENSOR_TEMP[8]= {0x01,0x04,0x31,0x1B,0x00,0x01,0x4F,0x31}; //Remote Temp.sensor   01 04 31 1B 00 01 4F 31;
26
//---------------------------------------------------------------------------------------------------------------------//
27
28
unsigned char *Pointer = BATT_VOLTAGE;
29
unsigned int TX_BYTE;
30
unsigned int RX_BYTE;
31
int i;
32
33
void send(unsigned char *BYTE)
34
{
35
  P2OUT |= BIT0;            //Put SP3485 in Transmit Mode
36
  for(i=0;i<9;i++)
37
    {
38
      //while ((UCA0STAT & UCBUSY)); // Wait if line TX/RX module is busy with data
39
      while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
40
      UCA0TXBUF = *BYTE++;    // Ein Byte verschicken und Pointer inkrementieren
41
      __delay_cycles(4);      // 4µS Pause zwischen zwei Bytes
42
    }
43
  P1OUT  |= BIT2;            // Nach dem letzen Byte Ausgang auf HIGH setzen
44
  __delay_cycles(40);          // Für die Vollständigkeit des Frames fehlen noch 40µS
45
  P2OUT &= ~BIT0;            // Put SP3485 in Receive Mode
46
}
47
48
void main(void)
49
    {
50
  WDTCTL = WDTPW + WDTHOLD;       // Stop the Watch dog
51
52
      //------------------- Configure the Clocks -------------------//
53
54
      if (CALBC1_1MHZ==0xFF)      // If calibration constant erased
55
         {
56
            while(1);                // do not load, trap CPU!!
57
         }
58
59
      DCOCTL  = 0;                   // Select lowest DCOx and MODx settings
60
      BCSCTL1 = CALBC1_1MHZ;         // Set range
61
      DCOCTL  = CALDCO_1MHZ;         // Set DCO step + modulation
62
63
      //---------------- Configuring the LED's ----------------------//
64
65
      P1DIR = 0xFF;             // P1.0 and P1.6 output
66
      P1OUT = 0;              // P1.0 and P1.6 = 0
67
68
    //--------- Setting the UART function for P1.1 & P1.2 ---------//
69
70
    P1SEL = BIT1 + BIT2;        // P1.1 UCA0RXD Eingang
71
    P1SEL2 = BIT1 + BIT2;        // P1.2 UCA0TXD Ausgang
72
73
    //------------ Configuring SP3485 Control Line ---------------//
74
75
    P2DIR = 0xFF;            // P2.0 Ausgang fuer DE und ~RE
76
    P2OUT &= ~BIT0;            // Put SP3485 in Receive Mode
77
78
    //------------ Configuring the UART(USCI_A0) ----------------//
79
80
      UCA0CTL1 |= UCSSEL_2;        // USCI Clock = SMCLK
81
      UCA0BR0   =  8;                // 8 From datasheet table-
82
      UCA0BR1   =  0;                // -selects baudrate =115200,clk = SMCLK
83
      UCA0MCTL = UCBRS2 + UCBRS0;     // Modulation UCBRSx = 5
84
      UCA0CTL1 &= ~UCSWRST;           // **Initialize USCI state machine**
85
86
      //---------------- Enabling the interrupts ------------------//
87
      IE2 |= UCA0RXIE;                // Enable USCI_A0 RX interrupt
88
      IE2 |= UCA0TXIE;                // Enable USCI_A0 TX interrupt
89
      //UC0IE |= UCA0TXIE;         // Enable USCI_A0 TX interrupt
90
91
      __delay_cycles(5000000);
92
      send(Pointer);          // Send frame
93
      _BIS_SR(LPM0_bits + GIE);     // Going to LPM0
94
  }
95
96
//-----------------------------------------------------------------------//
97
//                Transmit and Receive interrupts                        //
98
//-----------------------------------------------------------------------//
99
100
#pragma vector = USCIAB0TX_VECTOR
101
__interrupt void USCI0TX_ISR(void)
102
{
103
  //__bic_status_register_on_exit(LPM0_bits);
104
  P1OUT  ^= BIT0;            //light up P1.0 Led on Tx
105
}
106
107
#pragma vector = USCIAB0RX_VECTOR    //UART RX USCI Interrupt. This triggers when the USCI receives a char
108
__interrupt void USCI0RX_ISR(void)
109
{
110
  P1OUT ^= BIT6;            // light up P1.6 LED on RX
111
112
113
  /*LPM0_EXIT;
114
  RX_BYTE = UCA0RXBUF;        //Beim Auslesen wird das Flag UCA0RXIFG gelöscht, aber nicht der UCA0RXBUF geleert
115
  if(RX_BYTE == 0x01)          //Toggle green LED if "B" RXed
116
    {
117
    P1OUT ^= BIT6;          // light up P1.6 LED on RX
118
    }*/
119
  //IFG2 &= ~UCA0RXIFG;         // Clear RX flag
120
}

P.S.Die ISR sind momentan nur zum Leuchten von LED's da, in Zukunft 
werde ich sie aber schon für sinnvolle Zwecke benutzen.

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Vadim D. schrieb:
> 1. In meinem Code verwende ich einen Pointer, der auf eins von 6 Frames
> (Zeilen 20 bis 25) zeigt. Kann ich zum Versenden dieser Frames nur einen
> Pointer mit einer Schleife organisieren oder ist für jedes Frame ein
> eigener Pointer notwendig?

Die Variable "Pointer" ist überflüssig.

Du kannst Deiner Funktion "Send" auch direkt Deine Arrays übergeben:
1
send(BATT_VOLTAGE);

Ungeschickt ist die Schreibweise dieser Namen; es ist eine verbreitete 
(und sinnvolle) Konvention, daß nur Macros (d.h. #defines) in Versalien 
geschrieben werden - eben um sie auf einen Blick von Variablen, 
Funktionsnamen etc. unterscheiden zu können.

von Vadim D. (vendetta)


Lesenswert?

Danke für die Info!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du könntest Deine Funktion "send" auch universeller gestalten; derzeit 
geht sie fest davon aus, daß sie 8 Bytes zu versenden hat.

Das ist unpraktisch, sobald Du ein Paket anderer Größe versenden 
möchtest, denn dann müsstest Du eine andere "send"-Funktion bauen.

Du solltest der Funktion einen zweiten Parameter mitgeben, die Anzahl 
der zu sendenden Bytes.

Und dann sieht der Aufruf von "send" so aus:
1
send(BATT_VOLTAGE, sizeof (BATT_VOLTAGE));

Nein, der sizeof-Operator muss beim Aufruf der Funktion angewandt 
werden, in der Funktion selbst funktioniert das nicht, da liefert 
sizeof nicht die Größe des (vermeintlich) übergebenen Arrays, sondern 
die Größe der verwendeten Adresse - auf Deinem MSP430, der mit 
16-Bit-Pointern arbeitet, also den für Dich nutzlosen Wert 2.

von Vadim D. (vendetta)


Lesenswert?

Rufus Τ. F. schrieb:
> Du könntest Deine Funktion "send" auch universeller gestalten; derzeit
> geht sie fest davon aus, daß sie 8 Bytes zu versenden hat.
>
> Das ist unpraktisch, sobald Du ein Paket anderer Größe versenden
> möchtest, denn dann müsstest Du eine andere "send"-Funktion bauen.
>
> Du solltest der Funktion einen zweiten Parameter mitgeben, die Anzahl
> der zu sendenden Bytes.
>
> Und dann sieht der Aufruf von "send" so aus:
>
>
1
> send(BATT_VOLTAGE, sizeof (BATT_VOLTAGE));
2
>
>
> Nein, der sizeof-Operator muss beim Aufruf der Funktion angewandt
> werden, in der Funktion selbst funktioniert das nicht, da liefert
> sizeof nicht die Größe des (vermeintlich) übergebenen Arrays, sondern
> die Größe der verwendeten Adresse - auf Deinem MSP430, der mit
> 16-Bit-Pointern arbeitet, also den für Dich nutzlosen Wert 2.

Ich versende zwar immer ein 8-Byte Frame, werde aber aber deinem Tipp 
folgen, da das Programm dadurch flexibler wird :)

Danke!

von Vadim D. (vendetta)


Lesenswert?

Weiss du vllt. noch, wie ich am besten die 6 Frames senden sollte?
Wenn ich send() 6 mal nacheinander aufrufe, dann sieht es nicht schön. 
Ist es möglich alle 6 in ein struct zu packen und dann in einer Scheife 
abzuarbeiten? Bin gerade am Probieren, ob es so geht...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Vadim D. schrieb:
> Wenn ich send() 6 mal nacheinander aufrufe, dann sieht es nicht schön.

Ist das kritisch?

Wenn ja: Pack sie in ein Array. Das kannst Du mit 'ner Schleife 
abarbeiten.
1
uint8_t* MsgArray[] = 
2
{
3
  BATT_VOLTAGE,
4
  BATT_CURRENT,
5
  LOAD_VOLTAGE,
6
  LOAD_CURRENT,
7
  CHARGER_TEMP,
8
  RSENSOR_TEMP
9
};
10
11
#define MSG_ARRAY_COUNT (sizeof MsgArray / sizeof MsgArray[0])
12
13
...
14
15
for (i = 0, i < MSG_ARRAY_COUNT; i++)
16
  send(MsgArray[i]);

Das Macro MSG_ARRAY_COUNT zeigt übrigens, wie man aus einem Array die 
Anzahl der enthaltenen Elemente bestimmen kann; wie Dir vielleicht 
aufgefallen ist, habe ich bei der Deklaration von MsgArray leere eckige 
Klammern verwendet und nicht explizit die Elementanzahl angegeben.

von Vadim D. (vendetta)


Lesenswert?

Danke Rufus, werde ich gleich ausprobieren :)

von Vadim D. (vendetta)


Angehängte Dateien:

Lesenswert?

Das Senden klappt nun einwandfrei.
Das Empfangen geht meiner Meinung nach nicht, da in der Empfang-ISR 
keine Werte in einem Array gespeichert werden. Sie wird nur ein mal 
aufgerufen, wie ich dies der Variable RX_COUNTER nach beurteilen konnte.
Im Anhang habe ich ein Bild hinzugefügt, wie die Kommunikation 
stattfindet. Es werden insgesamt 6 Frames vom µC an den Laderegler 
geschickt, jeweils 8 Byte lang. Nach jedem Frame vom µC antwortet der 
Laderegler mit seinem eigenen Frame, der 7 Byte lang ist.

Weiss vllt. jemand, warum bie mir im Code nicht nach jedem empfangenen 
Byte die Empfang-ISR ausgelöst wird?

Hier ist der Code:
1
#pragma vector = USCIAB0RX_VECTOR    //UART RX USCI Interrupt. This triggers when the USCI receives a char
2
__interrupt void USCI0RX_ISR(void)
3
{
4
  LPM0_EXIT;
5
  P1OUT |= BIT6;            //Gruene LED ist an, wenn Empfangen aktiv ist
6
  RX_BYTE = UCA0RXBUF;        //Beim Auslesen wird das Flag UCA0RXIFG gelöscht, aber nicht der UCA0RXBUF geleert
7
  RX_COUNTER++;            //Nach jedem empfangenen Byte wird der Counter inkrementiert
8
  switch (RX_COUNTER)
9
  {
10
    case  4: REQUEST_FRAMES[0][0] = RX_BYTE;
11
    case  5: REQUEST_FRAMES[0][1] = RX_BYTE;
12
    case 11: REQUEST_FRAMES[1][0] = RX_BYTE;
13
    case 12: REQUEST_FRAMES[1][1] = RX_BYTE;
14
    case 18: REQUEST_FRAMES[2][0] = RX_BYTE;
15
    case 19: REQUEST_FRAMES[2][1] = RX_BYTE;
16
    case 25: REQUEST_FRAMES[3][0] = RX_BYTE;
17
    case 26: REQUEST_FRAMES[3][1] = RX_BYTE;
18
    case 32: REQUEST_FRAMES[4][0] = RX_BYTE;
19
    case 33: REQUEST_FRAMES[4][1] = RX_BYTE;
20
    case 39: REQUEST_FRAMES[5][0] = RX_BYTE;
21
    case 40: REQUEST_FRAMES[5][1] = RX_BYTE;
22
    case 42: ALL_RECEIVED_FLAG = 1;
23
  }
24
25
  P1OUT &= ~BIT6;            //Gruene LED ist aus, wenn Empfangen inaktiv ist
26
  IFG2 &= ~UCA0RXIFG;         // Clear RX flag
27
}

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du solltest Dir noch mal genau ansehen, wie ein switch/case-Statement 
funktioniert, und welche Rolle das von Dir nicht verwendete 
Schlüsselwort break dabei spielt.

> LPM0_EXIT;

Was soll das in Deiner ISR bewirken?

von Vadim D. (vendetta)


Lesenswert?

Das mit dem break; habe ich übersehen, danke)
Es funktioniert aber trotzdem nur zum Teil - die ISR wird nur einmal 
ausgelöst bzw. der RX_COUNTER = 1.

Ich habe das Gefühl, da stimmt was mit dem RXFlag nicht, aber er wird ja 
zurückgesetzt?!

Im Code leichtet die LED P1.0 ein, aber die LEDP1.6 leider nicht...
1
#pragma vector = USCIAB0RX_VECTOR    //UART RX USCI Interrupt. This triggers when the USCI receives a byte
2
__interrupt void USCI0RX_ISR(void)
3
{
4
  P1OUT &= ~BIT0;
5
  P1OUT &= ~BIT6;
6
  RX_BYTE = UCA0RXBUF;        //Beim Auslesen wird das Flag UCA0RXIFG gelöscht, aber nicht der UCA0RXBUF geleert
7
  RX_COUNTER++;             //Nach jedem empfangenen Byte wird der Counter inkrementiert
8
  switch (RX_COUNTER)
9
  {
10
    case  1: P1OUT |= BIT0;; break;
11
    case  2: P1OUT |= BIT6;; break;
12
  }
13
  IFG2 &= ~UCA0RXIFG;         // Clear RX flag
14
}

: Bearbeitet durch User
von Vadim D. (vendetta)


Lesenswert?

Ich habe nun den RXT-Pin und den TXD-Pin vom µC miteinander verbunden 
und auch in dem Fall wird nur das erste Byte empfangen...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dann solltest Du Deinen Code mal genau mit dem Beispielcode von TI 
vergleichen, der den interruptgesteuerten Empfang (und das 
interruptgesteuerte Senden) mit der USCI zeigt.

Achte darauf, daß Du den Code nimmst, der für den 'G2553 gedacht ist, 
und nicht welchen, der beispielsweise für den 'F5438, denn der verwendet 
zwar die gleiche USCI, aber die gesamte Interruptsteuerung sieht anders 
aus.

http://www.ti.com/lit/zip/slac485

von Vadim D. (vendetta)


Lesenswert?

So, jetzt funktioniert alles einwandfrei!!! :))

Das Problem war das, dass ich zuesrt in einer Schleife alle Nachrichten 
per MODBUS geschcikt habe und erst nach dieser Schleife ging der µC in 
LPM und Globale Interrupts aktiviert wurden. Ich habe ohne Schleife und 
ohne delay eine Nachricht geschickt und gleich danach war schon die 
Interrupt aktiv, worauf ich 14 Bytes (1LSB und 1MSB pro Byte) im Puffer 
speichern konnte.

Die send-Funktion habe ich ebenfalls überarbeitet - ein ganz wichtiger 
Punkt bei mir war nählich while(UCA0STAT & UCBUSY) hinter dem letzten 
gesendeten Byte zu schreiben!

Den funktionierenden Code poste ich ebenfalls hier.

Der nächste Schritt ist nun die per MODBUS empfangenen Daten per I2C 
weiter zu schicken. Schauen wir mal, wie schnell es gehen wird :)

Danke Euch allen!
1
//============================================================================//
2
//       A small program to transmit a frames through the RS485 network       //
3
//============================================================================//
4
// MSP430G2553 on LaunchPad Development board Connected to SP3485.            //
5
// Clocks   :- DC0 @ 1MHz ,SMCLK @1MHz                                        //
6
// Baudrate :- 115200 bps                                                     //
7
// [MSP430] P1.1(RXD) <- R0 [RS485](Receiver Output)                          //
8
// [MSP430] P1.2(TXD) -> DI [RS485](Driver Input)                             //
9
// [MSP430] P2.0      -> DE / RE [RS485](Driver Input/ Receiver Out Enable)   //
10
11
/*********************************Programm Code********************************/
12
#include "msp430g2553.h"
13
//-------------------------------------------------------------------------------------------//
14
//           Folgende Anfragen werden per MODBUS an den Solarladeregler gesendet.            //
15
//-------------------------------------------------------------------------------------------//
16
                             //CRC-MSB---------------------------------|
17
                             //CRC-LSB------------------------------|  |
18
                           //Registeranzahl-LSB----------------|  |  |
19
                           //Registeranzahl-MSB-------------|  |  |  |
20
                           //Start-Adresse-LSB-----------|  |  |  |  |
21
                           //Start-Adresse-MSB--------|  |  |  |  |  |
22
                           //Funktion--------------|  |  |  |  |  |  |
23
const unsigned char POLL_FRAMES[6][8]={          //Slave-Adresse------|  |  |  |  |  |  |  |
24
    {0x01,0x04,0x31,0x04,0x00,0x01,0x7E,0xF7}, //Batteriespannung   01 04 31 04 00 01 7E F7;
25
    {0x01,0x04,0x31,0x05,0x00,0x01,0x2F,0x37}, //Ladestrom       01 04 31 05 00 01 2F 37;
26
    {0x01,0x04,0x31,0x0C,0x00,0x01,0xFF,0x35}, //Lastspannung     01 04 31 0C 00 01 FF 35;
27
    {0x01,0x04,0x31,0x0D,0x00,0x01,0xAE,0xF5}, //Laststrom       01 04 31 0D 00 01 AE F5;
28
    {0x01,0x04,0x31,0x11,0x00,0x01,0x6F,0x33}, //Ladereglertemp.  01 04 31 11 00 01 6F 33;
29
    {0x01,0x04,0x31,0x1B,0x00,0x01,0x4F,0x31}  //Remote Temp.sensor 01 04 31 1B 00 01 4F 31;
30
};
31
32
volatile unsigned int REQUEST_BYTES[98];//Für Benutzen in ISR müssen als volatile deklariert werden
33
int i;
34
volatile unsigned int RX_COUNTER = 0;
35
volatile int ALL_RECEIVED_FLAG = 0;
36
int x ,y;
37
38
void send(const unsigned char *BYTE, int SIZE_OF_FRAME)
39
{
40
  P2OUT |= BIT0;            //Put SP3485 in Transmit Mode
41
  P1OUT |= BIT0;            //Rote LED ist an, wenn Senden aktiv ist
42
  while(SIZE_OF_FRAME--)
43
    {
44
      while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
45
      UCA0TXBUF = *BYTE++;    // Ein Byte verschicken und Pointer inkrementieren
46
    }
47
  while(UCA0STAT & UCBUSY);       // Wait until the last byte is completely sent
48
  P1OUT &= ~BIT0;            // Rote LED ist aus, wenn Senden inaktiv ist
49
  P2OUT &= ~BIT0;            // Put SP3485 in Receive Mode
50
}
51
52
void main(void)
53
    {
54
  WDTCTL = WDTPW + WDTHOLD;       // Stop the Watch dog
55
56
      //------------------- Configure the Clocks -------------------//
57
      if (CALBC1_1MHZ==0xFF)      // If calibration constant erased
58
         {
59
            while(1);                // do not load, trap CPU!!
60
         }
61
62
      DCOCTL  = 0;                   // Select lowest DCOx and MODx settings
63
      BCSCTL1 = CALBC1_1MHZ;         // Set range
64
      DCOCTL  = CALDCO_1MHZ;         // Set DCO step + modulation
65
66
      //---------------- Configuring the LED's ----------------------//
67
      P1DIR = BIT0 + BIT6;             // P1.0 and P1.6 output
68
      P1OUT &= ~BIT0;
69
      P1OUT &= ~BIT6;              // Alle P1 Ausgänge auf LOW
70
71
    //--------- Setting the UART function for P1.1 & P1.2 ---------//
72
    P1SEL = BIT1 + BIT2;        // P1.1 UCA0RXD Eingang
73
    P1SEL2 = BIT1 + BIT2;        // P1.2 UCA0TXD Ausgang
74
75
    //------------ Configuring SP3485 Control Line ---------------//
76
    P2DIR = 0xFF;            // P2.0 Ausgang fuer DE und ~RE
77
    P2OUT &= ~BIT0;            // Put SP3485 in Receive Mode
78
79
    //------------ Configuring the UART(USCI_A0) ----------------//
80
      UCA0CTL1 |= UCSSEL_2;        // USCI Clock = SMCLK
81
      UCA0BR0   = 0x08;                // 8 From datasheet table-
82
      UCA0BR1   = 0x00;                // -selects baudrate =115200,clk = SMCLK
83
      UCA0MCTL = UCBRS2 + UCBRS0;     // Modulation UCBRSx = 5
84
      UCA0CTL1 &= ~UCSWRST;           // **Initialize USCI state machine**
85
86
      //---------------- Enabling the interrupts ------------------//
87
      IE2 |= UCA0RXIE;                // Enable USCI_A0 RX interrupt
88
      IE2 |= UCA0TXIE;                // Enable USCI_A0 TX interrupt
89
      //UC0IE |= UCA0TXIE;         // Enable USCI_A0 TX interrupt
90
91
      __delay_cycles(2000000);
92
      //for(y=0 ; y < 6 ; y++)
93
      //{
94
        send(POLL_FRAMES[0], sizeof (POLL_FRAMES[0]));          // Send frame
95
        //__delay_cycles(3400);
96
      //}
97
98
      _BIS_SR(LPM0_bits + GIE);     // Going to LPM0
99
  }
100
101
//-----------------------------------------------------------------------//
102
//                Transmit and Receive interrupts                        //
103
//-----------------------------------------------------------------------//
104
#pragma vector = USCIAB0TX_VECTOR
105
__interrupt void USCI0TX_ISR(void)
106
{
107
  //__bic_status_register_on_exit(LPM0_bits);
108
}
109
110
#pragma vector = USCIAB0RX_VECTOR    //UART RX USCI Interrupt. This triggers when the USCI receives a char
111
__interrupt void USCI0RX_ISR(void)
112
{
113
  //P1OUT |= BIT6;          //Gruene LED ist an, wenn Empfangen aktiv ist
114
  REQUEST_BYTES[RX_COUNTER++] = UCA0RXBUF;        //Beim Auslesen wird das Flag UCA0RXIFG gelöscht, aber nicht der UCA0RXBUF geleert
115
  RX_COUNTER++;             //Nach jedem empfangenen Byte wird der Counter inkrementiert
116
117
  if (RX_COUNTER>13)
118
    {
119
    P1OUT |= BIT6;          //Gruene LED ist an, wenn Empfangen aktiv ist;
120
    }
121
  //P1OUT &= ~BIT6;          //Gruene LED ist aus, wenn Empfangen inaktiv ist
122
  //IFG2 &= ~UCA0RXIFG;         // Clear Interrupt RX flag
123
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Vadim D. schrieb:
> void send(const unsigned char *BYTE, int SIZE_OF_FRAME)

Das solltest Du Dir abgewöhnen.

Variablennamen sollte man nie in Versalien schreiben.

Die verbreitete Konvention ist, das nur mit Macros (#define) zu machen.

von Vadim D. (vendetta)


Lesenswert?

Rufus Τ. F. schrieb:
> Vadim D. schrieb:
>> void send(const unsigned char *BYTE, int SIZE_OF_FRAME)
>
> Das solltest Du Dir abgewöhnen.
>
> Variablennamen sollte man nie in Versalien schreiben.
>
> Die verbreitete Konvention ist, das nur mit Macros (#define) zu machen.

Kannst Du mir bitte irgendein Link posten, wo ich dies nachschauen 
könnte?

Verstehe nicht ganz, wie es dann aussehen sollte...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Vadim D. schrieb:
> Kannst Du mir bitte irgendein Link posten, wo ich dies nachschauen
> könnte?

Hast Du schon mal von anderen Leuten geschriebenen C-Code gesehen?

Vielleicht hast Du auch nur nicht verstanden, was Versalien sind? So 
nennt man es, wenn ein Wort KOMPLETT in Großbuchstaben geschrieben ist.

Statt
1
void send(const unsigned char *BYTE, int SIZE_OF_FRAME)

wäre
1
void send(const unsigned char *byte, int size_of_frame)

besser.

Der Parameter "byte" (oder "BYTE") ist allerdings auch problematisch; 
einerseits ist das bei manchen Compilern/SDKs ein Datentyp, andererseits 
ist das nichtssagend und falsch, denn es soll schließlich ein Pointer 
auf Dein "Frame" sein.

Also wäre "frame" oder "framepointer" ein passenderer Name:
1
void send(const unsigned char *frame, int size_of_frame)


Wird's verständlicher?

von Vadim D. (vendetta)


Lesenswert?

Auf jeden Fall!

Danke Dir, hab den Code schon entsprechend geändert :)

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.