GCC in WinAVR nutzen:
Integration von C und C++
Bsp: mit gemsichten C und Cpp mit main.cpp
ein Implemntaionsfehler für Strings etc im Flashspiecher erfordert eine Neudefinmtion des PROGMEM und PSTR
(einzufügen in main.cpp Kopf)
// CPP ANPASSUNG VON http://avr.2057.n7.nabble.com/C-with-P_STR-td7435.html
#ifdef __cplusplus
#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))
#undef P_STR
#define P_STR(s) (__extension__({static prog_char __c[] PROGMEM = (s);&__c[0];}))
#else
#define P_STR(s) P_STR(s)
#endif
Ab jetzt wird P_STR() verwendet., anstatt PSTR(); siehe
"C:/WinAVR-20100110/doc/avr-libc/avr-libc-user-manual/group__avr__pgmspace.html"
Alle nicht CPP müssen mit extern "C" {.. *.h} eingebunden werden
....................................................................................................................
1 Variante !
Dekaration der Funktionsköpfe in Headerfilese von ANSI-C Headers:
#ifdef __cplusplus
extern "C" {
......entdwer jetzt schon #endif oder
int myOtherCfunc(int arg1, int arg2); /* a C function */
........ weitere Fuktionsköpfe im ANSI-Header
#endif
#ifdef __cplusplus
}
#endif
....................................................................................................................
2. Variante ! ( besser)
im main.cpp
extern "C" {
#include "main.h"
#include "uart.h"
#include "Befehle.h"
#include "debug.h"
}
// hier alle cpp header
#include "CRC16.h"
#include "ComSlip.h"
#include "WiMODLRHCI.h"
#include "WiMODLRHCI_IDs.h"
STRINGS oder ZEICHEN im FLASH ablegen --> Programm Memory
( MCA steht für "Memroy Character Array" )
( meist bei mehrmaliger Verwendung )
So legt man einen Stgring im Progamm Speicher ab. Damit ist dieser Teil des Programmes:
HIER IST PROGMEM ZU VERWENEN;
Dann mit den zusätlicehn Sttring befehlen mit _P wieder aus dem Flash lesen,
Usache ist die HARVARD Architektur
const char MCA_BOTSCHAFT[] PROGMEM = " Dies ist ein Text im Flash
"; //CONST
ARRAY
const char MCA_LCD16_CLEAR[] PROGMEM= "
"; //löschen mit Space
const char MCA_DELIMITER[] PROGMEM = ",";
const char MCA_FULLSTEPS[] PROGMEM = {0x3A,0x39,0x35,0x36}; //einzelne Zeichen
const char MCA_HALFSTEPS[] PROGMEM = {0x3A,0x28,0x39,0x11,0x35,0x24,0x36,0x12};
const char MCA_STARTREK[] PROGMEM = {0x81,0x42,0x24,0x18,0x24,0x42};
Anwendung;
also gemeint sind z.B. strcpy_P( gcaStr, MCA_BOTSCHAFT);
Wie holt man nun den String wieder aus dem Programmmeory raus.?
Mit Sonderfunkltionen ! Program Space Utilities
Program Space Utilities spiegeln praktische alle Stgringfunktione von C, nur mit einem "_P" an den Funktionsnamen angehängt
char * strncpy_P (char *, PGM_P, size_t)
....................................................................................................................
const char PROGMEM MC_AUTOR[] = "*Christof Ermer*"; So legt man eine Stgring im Progamm Speicher ab.
strncpy_P (gcaStr, MC_AUTOR); // jetzt steht im globalen Char Array STR der Text, der im Progmem unter MCA_AUTOR abgelegt ist..
....................................................................................................................
dazu gibt es noch verschiedene besondere Funktionen und Poniterdefintionen:
Direktes Ablegen von Strings bei einmaliger Verwendeung mit:
#define PSTR(s) ((const PROGMEM char *)(s))
dies liefert einen Pointer auf den Programmmeory
Anwendungen:
if( !strcmp_P( gcaStr , PSTR( "Vergleiche") ) {....};
if( !strcasecmp_P(gcaStr, PSTR("PING")) ) {...};
Merke und C** muss PSTR neu defineirt werdens. Siehe weiter oben
....................................................................................................................
#define PGM_P const prog_char *
Anwendung: legt Pointer auf Progmem ab. Sowas kan man als prima PARSER für Zeichen verwenden
Beispiel:
const char MCA_FULLSTEPS[] PROGMEM = {0x3A,0x39,0x35,0x36}; //einzelne Zeichen
static PGM_P gppmPattern; // Lese globaler Pointer auf programm memory
gppmPattern = MCA_FULLSTEPS;
//jetzt haben wir einen Pointer auf die vier Bitmuster namens
MCA_FULLSTEPS
strcpy_P( gcaStr, gppmPattern );
............................................ WICHTIG .............................................................
in "C" gibt es neben die Array Zugriffs-Schreibweise caFeld[ nummer ] --> oder caFeld[0] oder caFeld[1]
auch noch die Pointerarythmetik Schreibweise (MERKE: ein Array-Name ist der Pointer auf das Array )
*( caFeld + nummer )
Beipiel:
char caAutor[]= "Christof Ermer";
char cEinzelzeichen;
cEinzelzeichen = caAutor[2]; ---> cEinzelzeichen = 'r' (aber kein String weil Strings \0 terminiert sind)
cEinzelzeichen = *(caAutor + 2); ---> cEinzelzeichen = 'r' (ebenfalls richtgdereferenziert, dies ist sogar effektiver vom Compilerergebniss)
* Ponter auf (caAutor + Abstand )
....................................................................................................................
Wie lese ich byteweise aus dem Programmspeicher ?
esrt ein paar Vorgaben:
unsigned char u8Parser;
const char MCA_HALFSTEPS[] PROGMEM = {0x3A,0x28,0x39,0x11,0x35,0x24,0x36,0x12};
static PGM_P gppmPattern; // Lese globaler Pointer auf programm memory
das geht so NICHT !!! denn der Pointer ist ein Pointer auf "Progam Memory".
Das muß erst übersetztz werden ,--> mit pgm_read_byte_near() .!!
// FALSCH !!!
PORTC =
*( gppmPattern + ( u8Parser % 8 ) );
//so nicht !, erzeugt bei jedem
Aufruf das darauffolgende Bitmuster aus der Tabelle MCA_FULLSTEPS
u8Parser++;
SO GEHT ES !!
pgm_read_byte_near ist die Lösung.
#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
( siehe Dokumentation in WINAVR Ordner "C:/WinAVR-20100110/doc/avr-libc/avr-libc-user-manual/group__avr__pgmspace.html"
Das ist schon etwas schwer zu verstehen:
machen wir es einfach:
Beispiel:
1.Schritt
unsigned char u8Parser;
const char MCA_HALFSTEPS[] PROGMEM = {0x3A,0x28,0x39,0x11,0x35,0x24,0x36,0x12};
static PGM_P gppmPattern; // Lese globaler Pointer auf programm memory
gppmPattern = MCA_HALFSTEPS;
//jetzt haben wir einen Pointer auf die vier Bitmuster namens
MCA_FULLSTEPS
2.Schritt
while(1)
{ ( etwas unsauber, da Port C komplett geschrieben wird.. )
PORTC = pgm_read_byte_near( (gppmPattern + ( u8Parser
% 8 )) ) ; //(PGM_P). Dies erzeugt bei jedem Aufruf das
darauffolgende Bitmuster aus der Tabelle MCA_FULLSTEPS
u8Parser++;
};
Verwendung von Interrupt Variablen > 1 Byte
Es ist notwendig alle in Interrupts benutzten Variablen vor der
Benutzung oder logischen Verarbeitung besonders zu behandeln.
/Mainloops=649504 Tick=1054164
//Mainloops=101677 Tick=1054208
/*
Mainloops=680634 Tick=490
Mainloops=47143 Tick=512
Mainloops=681380 Tick=757
Mainloops=680632 Tick=1002
Mainloops=44977 Tick=1024
immer ärge rbei TICK =
2560 = bin 10100000000
16640 0x0b1000010000000
40960 10100000000000000
*/
//---------------------------------------------------------
ISR(TIMER2_OVF_vect)
{
gu32_Ticks++; // F_CPU/256/256 ->~244/sec
};
//---------------------------------------------------------
//---------------------------------------------------------
cli(); // Lösung
32Zwischen = (gu32_Ticks - u32Now); // Verriegelt Interrupt Fehler
//sonst stottert es ganz fürchterlich, Timingproblem
// Grund: mehr als ein Byte im Interrrupt wird zu unterschiedlichen Zeiten behandelt
sei();
//---------------------------------------------------------
//---------------------------------------------------------
if( u32Zwischen > TICK_1000MS ) //TICK_1000MS=244
{
...
};
//---------------------------------------------------------