Magge2k
19.01.2016, 00:22
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. :confused:
Ein Tutorial zu den Structures habe ich hier gefunden: :cool:
http://microchip.wikidot.com/tls2101:structures
zuvor wurde bei einem Multi-Datei-Projekt folgende Programmstruktur vorgestellt: ;)
http://microchip.wikidot.com/tls2101:libraries-headers
Wie ist jetzt das richtige Vorgehen?
Variante A:
Header
// 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 */
Source
// RS485.c
#include "RS485.h"
RS485_STRUCT RS485; // ???
// oder
volatile RS485_STRUCT RS485; // ???
// ... CODE ...
oder Variante B:
Header
// 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 */
Source
// RS485.cpp
#include "RS485.h"
// Ohne Lokale Deklaration
// RS485_STRUCT RS485;
Variante B wurde bereits verwendet allerdings ohne die volatile deklarationen innerhalb des Struct.
Dies hat auch irgendwie :strom funktioniert 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.
//-----------------------------------------------------------------------
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.
}
}
//-----------------------------------------------------------------------
Falls jemand grobe Fehler an der Struktur erkennt oder Verbesserungsvorschläge hat nehme ich diese gerne entgegen.
Wichtig wäre mir vor allem eine saubere und stabile Programmierung. Vor allem bei der Definition der Struktur.
Viele Grüße
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. :confused:
Ein Tutorial zu den Structures habe ich hier gefunden: :cool:
http://microchip.wikidot.com/tls2101:structures
zuvor wurde bei einem Multi-Datei-Projekt folgende Programmstruktur vorgestellt: ;)
http://microchip.wikidot.com/tls2101:libraries-headers
Wie ist jetzt das richtige Vorgehen?
Variante A:
Header
// 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 */
Source
// RS485.c
#include "RS485.h"
RS485_STRUCT RS485; // ???
// oder
volatile RS485_STRUCT RS485; // ???
// ... CODE ...
oder Variante B:
Header
// 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 */
Source
// RS485.cpp
#include "RS485.h"
// Ohne Lokale Deklaration
// RS485_STRUCT RS485;
Variante B wurde bereits verwendet allerdings ohne die volatile deklarationen innerhalb des Struct.
Dies hat auch irgendwie :strom funktioniert 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.
//-----------------------------------------------------------------------
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.
}
}
//-----------------------------------------------------------------------
Falls jemand grobe Fehler an der Struktur erkennt oder Verbesserungsvorschläge hat nehme ich diese gerne entgegen.
Wichtig wäre mir vor allem eine saubere und stabile Programmierung. Vor allem bei der Definition der Struktur.
Viele Grüße