Zurück (C) Christof Ermer, Regensburg
Gästebuch (public. sonst besser Email)

Gratis Counter 04.12.2015

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
        {
...
        };
//---------------------------------------------------------