Hallo,
ich habe gerade ein grundlegendes Verständnisproblem bei der Definition einer Structure und zwar möchte ich für ein Projekt eine RS485 "Klasse" erstellen.
Dabei habe ich gerade das Problem, dass ich nicht genau weiß, an welcher Stelle im Code bzw in welcher Datei, ich die Structure platzieren soll.
Ein Tutorial zu den Structures habe ich hier gefunden:zuvor wurde bei einem Multi-Datei-Projekt folgende Programmstruktur vorgestellt:
Wie ist jetzt das richtige Vorgehen?
Variante A:
Header
SourceCode:// RS485.h #ifndef RS485_H #define RS485_H #include <xc.h> #ifdef __cplusplus extern "C" { #endif #define bufferlen 46 #define TXDIR TRISBbits.TRISB5 #define TXDP PORTBbits.RB5 typedef struct RS485_STRUCT { uchar use_interrupt; uchar loopback; uchar ownAddress; volatile uint16 txcounter; volatile uint16 txLength; volatile uint16 rxcounter; volatile uint16 readcounter; volatile uchar RxBuffer[bufferlen]; volatile uchar TxBuffer[bufferlen]; } RS485_STRUCT; extern RS485_STRUCT RS485; void RS485_RC_INT(void); void RS485_TX_INT(void); void RS485_open(uchar sirq); void RS485_close(void); uchar RS485_read(void); void RS485_writeBytes(const uchar *bytes, uint16 len); #ifdef __cplusplus } #endif #endif /* RS485_H */
Code:// RS485.c #include "RS485.h" RS485_STRUCT RS485; // ??? // oder volatile RS485_STRUCT RS485; // ??? // ... CODE ...
oder Variante B:
Header
SourceCode:// RS485.h #ifndef RS485_H #define RS485_H #include <xc.h> #ifdef __cplusplus extern "C" { #endif #define bufferlen 46 struct { uchar use_interrupt; uchar loopback; uchar ownAddress; volatile uint16 txcounter; volatile uint16 txLength; volatile uint16 rxcounter; volatile uint16 readcounter; volatile uchar RxBuffer[bufferlen]; volatile uchar TxBuffer[bufferlen]; } RS485; void RS485_open(uchar sirq); void RS485_close(void); uchar RS485_read(void); void RS485_writeBytes(const uchar *bytes, uint16 len); void RS485_RC_INT(void); void RS485_TX_INT(void); #ifdef __cplusplus } #endif #endif /* RS485_H */
Variante B wurde bereits verwendet allerdings ohne die volatile deklarationen innerhalb des Struct.Code:// RS485.cpp #include "RS485.h" // Ohne Lokale Deklaration // RS485_STRUCT RS485;
Dies hat auch irgendwiefunktioniert allerdings bin ich mir bei dieser Version nicht sicher ob durch complier optimierung oder der Verwendung mehrerer Interrupts daten verfälscht werden.
Damit der Controller genügend Zeit für die weiteren Aufgaben bekommt findet die Kommunikation ebenfalls über Interrupts statt. Der Tx-Interrupt sendet die Daten im TxBuffer solange bis der TxCounter = txLength ist.
Bei einem Rx-Interrupt werden die Daten solange am RxBuffer angehängt, bis dieser Voll ist... ab einem RxCounter-Wert von 8 schaut das Hauptprogramm den RxBuffer an und beginnt diesen Abzuarbeiten.
Falls jemand grobe Fehler an der Struktur erkennt oder Verbesserungsvorschläge hat nehme ich diese gerne entgegen.Code://----------------------------------------------------------------------- void RS485_TX_INT(void) // Interrupt Methode Senden { if (TRMT) { RS485.txcounter++; TXREG = RS485.TxBuffer[RS485.txcounter]; //TXIF is cleared by loading TXREG RS485.TxBuffer[RS485.txcounter] = 0x00; ClrWdt(); if (RS485.txcounter >= RS485.txLength-1) { RS485.txLength = 0; RS485.txcounter = 0; TXEN = 0; TXIE = 0; TXDP = 0; // Dataenable am MAX 491 Baustein } } } //----------------------------------------------------------------------- void RS485_RC_INT(void) // Interrupt Methode Empfangen { uchar input = RCREG; if (RS485.rxcounter >= bufferlen-1) { //RS485.rxcounter = 0x00; RS485_writeBytes("RS485.RxBuffer: Overrun!",24); } if (RS485.rxcounter < bufferlen-1) { RS485.RxBuffer[RS485.rxcounter] = input; //RCREG; RS485.rxcounter++; } } //----------------------------------------------------------------------- void RS485_writeBytes(const uchar *bytes, uint16 len) { if (len < bufferlen) { RS485.txcounter = 0; RS485.txLength = 0; for (uint16 i = 0; i <= len; i++) { RS485.TxBuffer[RS485.txLength] = bytes[i]; RS485.txLength++; ClrWdt(); } PIE1bits.TXIE = 1; TXDP = 1; TXREG = RS485.TxBuffer[RS485.txcounter]; //TXIF is cleared by loading TXREG TXSTAbits.TXEN = 1; // Wenn TX eingeschaltet wird ist TXIF == 1 // Darum springt uC gleich in Interrupt routine. } } //-----------------------------------------------------------------------
Wichtig wäre mir vor allem eine saubere und stabile Programmierung. Vor allem bei der Definition der Struktur.
Viele Grüße
Lesezeichen