PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Port als Variable in Klasse verwenden (C++ Atmel Studio 6.2)?



Jawaiica
20.05.2015, 18:31
Schönen guten Abend,

ich habe ein kleines Problem beim erstellen einer Bibliothek für meine AVR Projekte und zwar hatte ich vor mir in C++ eine Bibliothek zu schreiben mit allen wichtigen Funktionen die ich wieder verwenden werde. Anfangen wollte ich, da es sich grade gut angeboten hat, mit einer Testfunktion um ein Schieberegister (74HC595) anzusteuern. Hierfür habe ich erst einmal eine Klasse und zwei Funktionen erstellt (eine zum initialisieren und eben eine zum übertragen von 8bit). Die Init-Funktion erhält als Parameter 4 Pins (ser, sck, scl und rck) und eine Port-Variable (volatile uint8_t *), die Write-Funktion bekommt dann nur die 8bit Daten die übertragen werden sollen. An sich macht die Init-Funktion so keine Probleme allerdings muss ich die Port-Variable irgendwie speichern können damit meine Write-Funktion diesen ebenfalls benutzen kann. Die Klassenvariable (in der die Port-Variable gespeichert werden soll) ist ebenfalls vom Typ volatile uint8_t *, dennoch wird diese nicht übernommen. Hier mal ein Beispiel:

Das funktioniert:




void SR_Init(volatile uint8_t *sr_ddr, volatile uint8_t *sr_port, uint8_t sr_ser, uint8_t sr_sck, uint8_t sr_scl, uint8_t sr_rck) {

*sr_ddr |= ((1<<sr_ser)|(1<<sr_sck)|(1<<sr_rck)|(1<<sr_scl));

*sr_port &= ~(1<<sr_ser);
*sr_port &= ~(1<<sr_sck);
*sr_port &= ~(1<<sr_rck);
*sr_port &= ~(1<<sr_scl);

*sr_port |= (1<<sr_scl);
}



Das hier schon nicht mehr:



void SR_Init(volatile uint8_t *sr_ddr, volatile uint8_t *sr_port, uint8_t sr_ser, uint8_t sr_sck, uint8_t sr_scl, uint8_t sr_rck) {
*SR_DDRk = *sr_ddr;
*SR_PORTk = *sr_port;

*SR_DDRk |= ((1<<sr_ser)|(1<<sr_sck)|(1<<sr_rck)|(1<<sr_scl));

*SR_PORTk &= ~(1<<sr_ser);
*SR_PORTk &= ~(1<<sr_sck);
*SR_PORTk &= ~(1<<sr_rck);
*SR_PORTk &= ~(1<<sr_scl);

*SR_PORTk |= (1<<sr_scl);
}

Aufgerufen wird die Funktion dann über:



SR_Init(&DDRD, &PORTD, PD0, PD1, PD2, PD3);

Hat zufällig jemand eine Lösung für mich, falls es dafür eine Lösung gibt? Ich könnte natürlich auch der Write-Funktion noch die Port-Variable als Parameter hinzufügen aber besser wäre es wenn es so gehen würde dass die nur einmal gesetzt werden muss (über die Init-Funktion).

MfG Jawaiica

Mxt
20.05.2015, 20:42
Hallo,

auch wenn ich nicht mit AVR-Studio arbeite, vielleicht schon mal ein paar Hinweise.

Wenn Du schon mit einer Klasse arbeitest, kannst Du Dinge wie den Port als Membervariable der Klasse anlegen und diese im Konstruktor initialisieren. Die Init-Funktion kann dann eigentlich entfallen, diese Arbeit kann der Konstruktor übernehmen. Eine Write Funktion wäre dann eine Memberfunktion der Klasse und braucht gar nicht mehr so viele Parameter.

Bevor ich mir irgendwelche Beispiele aus den Fingern sauge, hier einfach Verweise auf ähnlichen Code für andere Controller:

Eine Klasse als Verpackung einer SPI-Schnittstelle
https://developer.mbed.org/handbook/SPI

Etwas effizienter sind Template-Parameter, wie hier bei einer Klasse für IOs
https://developer.mbed.org/users/Sissors/code/FastIO/file/f0a48027b2b3/FastIO.h

- - - Aktualisiert - - -

Hier als Ergänzung das Grundprinzip als Visual Studio Program



#include "stdafx.h"

class A
{
private:

volatile uint8_t* m_Port;

public:

A(uint8_t* p) : m_Port(p)
{}

void Write(uint8_t v)
{
*m_Port = v;
}
};

template<typename T, volatile T* port>
class B
{
public:

void Write(T v)
{
*port = v;
}
};

uint8_t x;

int _tmain(int argc, _TCHAR* argv[])
{
A a(&x);

B<uint8_t, &x> b;

a.Write(1);
b.Write(2);

return 0;
}

Jawaiica
24.05.2015, 09:55
Schönen guten Morgen,

vielen Dank für die Antwort, so werde ich aber mehrere Klassen erstellen müssen (Außer ich mache eine Klasse und x Konstruktoren für unterschiedliche Sachen was aber nicht so toll wäre). Sollte es keine andere Lösung dazu geben werde ich das dann so machen. Danke für die Hilfe Mxt.

MfG Jawaiica