- 12V Akku mit 280 Ah bauen         
Seite 3 von 3 ErsteErste 123
Ergebnis 21 bis 22 von 22

Thema: Hilfe! Programm zu groß trotz aktivierter Optimierung!

  1. #21
    Benutzer Stammmitglied
    Registriert seit
    12.06.2007
    Beiträge
    42
    Anzeige

    Praxistest und DIY Projekte
    Ich weiß, aber zumindest bei diesem Testprogramm ist das kein Problem. ISRs gibt es nicht, und ich kann mir per Taster den restlichen Speicher im SRAM anzeigen lassen (momentan noch 17 Bytes frei). Nächste Woche gehts an richtige Projekt, mal sehen wie gut ich da (plötzlich ohne Testboard...) voran komme.

    In jedem Fall schönen Dank, SprinterSB, und schönes Wochenende!

  2. #22
    Benutzer Stammmitglied
    Registriert seit
    12.06.2007
    Beiträge
    42
    So, hier nochmal der aktuelle Code. Die Delay-Funktionen habe ich entfernt und durch eine eigene Funktion zum Tastenentprellen ersetzt. Außerdem gibt es noch weitere kleine Verbesserungen (dank der Hilfe von SprinterSB).

    Perfekt ist es noch nicht, aber ich muss mich jetzt meiner produktiven Aufgabe widmen und kann leider nicht weiter am Testprogramm werkeln.

    Die funktion long_delay_ms() wird nicht mehr benutzt. Ich habe sie aber drinnengelassen, da ich finde, dass eine solche Funktion für Anfänger zum Testen doch sehr nützlich ist. Bitte nicht schlagen! Ich weiß ja, dass delays keinen guten Ruf haben, aber wir reden hier von den ersten Gehversuchen in der AVR-Welt...
    Code:
    /*  T E S T P R O G R A M M  (USART+EEPROM)
     *  ---------------------------------------
     *  
     *  Dieses Testprogramm (geschrieben für ATTiny2313) empfängt und sendet Zeichen über die
     *  RS232-Schnittstelle (UART/USART) und ermöglicht die folgenden Funktionen:
     *
     *  SW0 (Taster 0, bei mir an PIND2): empfangene Zeichen im EEPROM speichern
     *
     *  SW1 (Taster 1, bei mir an PIND3): gespeicherte Zeichen wieder auslesen und ans Terminal senden
     *
     *  SW2 (Taster 2, bei mir an PIND4): Anzahl aktuell eingelesener Zeichen ans Terminal senden
     *
     *  SW3 (Taster 3, bei mir an PIND5): freien Speicher (SRAM) ans Terminal senden
     *
     *  Zum Testen dieses Programm benötigt man ein Terminal-Programm (ich nutze HTerm), mit dem man
     *  Daten zum AVR schicken und von ihm empfangen kann.
     *
     *  Wenn das Terminal-Programm verbunden ist, sieht man, dass kontinuierlich ein Punkt ('.') gesendet
     *  wird. Dies ist als Lebenszeichen des AVR zu verstehen. Bricht der Datenstrom plötzlich ab, ist
     *  das Programm wahrscheinlich hängengeblieben (z.B. wegen Speicherüberlauf o.ä.).
     *
     *  Da das SRAM in seiner Größe sehr beschränkt ist (beim ATTiny2313 nur 128 Bytes), habe ich eine
     *  maximale Größe für den empfangenen String festgelegt. Sie kann über IUSART_INP_MAX geändert werden.
     *
     *  Das Beschreiben des EEPROM ist in der Hinsicht kritisch, als dass der Speicher nur
     *  ca. 100000 mal beschreibbar ist. Deshalb ist es nicht sinnvoll, jedesmal wieder ab
     *  Byte 0 zu schreiben. Deshalb habe ich die Funktionen eeprom_get_last_byte() und
     *  eeprom_get_first_written_byte() geschrieben. Mithilfe dieser Funktionen kann man so
     *  navigieren, dass das EEPROM kontinuierlich beschrieben wird, so dass alle Bytes
     *  gleichmäßig beansprucht werden und die Lebensdauer deutlich erhöht wird. Erreicht man
     *  das Ende des EEPROM (beim ATTiny2313 128 Bytes, änderbar über EEPROM_MAX_BYTE), so
     *  beginnt man wieder bei Byte 0, wobei ein String auch überlappen kann (z.B. ein
     *  5-Zeichen-String in den Bytes 126, 127, 0, 1 und 2).
     *
     *  Bei meinem Testboard (STK500) habe ich die Taster nicht nach Standardkonfiguration angeschlossen,
     *  wie oben an der Funktionsübersicht zu sehen ist (SW0 auf PIND2 statt PIND0 usw.). Wer ganz normal
     *  SW0 an PIND0 hat, muss lediglich diese wenigen Stellen im Code abändern.
     *
     *  Beispiel:
     *  ---------
     *    
     *  if( !(PIND & (1<<PIND3)) && iUSART_inp>0 && cBoolSaved) {    //SW1 gedrückt
     *                       -
     *  ändern in
     *
     *  if( !(PIND & (1<<PIND1)) && iUSART_inp>0 && cBoolSaved) {    //SW1 gedrückt
     *                       -
     *
     *  Tipp: Wer HTerm benutzt, sollte in der oberen Ansicht (vom AVR gesendete Zeichen) nur die ASCII-
     *        Ausgabe zulassen (also Häkchen weg bei Hex, Dec und Bin). So behält man den Überblick.
     *
     *
     *  Wer (wie ich gerade) in die AVR-Programmierung einsteigt und an der Kommunikation zwischen AVR
     *  und PC sowie am Beschreiben des EEPROM interessiert ist, wird vielleicht (hoffentlich) mithilfe
     *  dieses Programms weiterkommen.
     *
     *
     *  Matthias Marschhausen (2007-07-20)
     *
     */
    #ifndef F_CPU
    	#define F_CPU 4000000
    #endif
    #ifndef UART_BAUD_RATE
    	#define UART_BAUD_RATE 9600
    #endif
    //
    #define IUSART_INP_MAX 20   //maximale Anzahl an Zeichen, die vom AVR empfangen werden darf
    #define EEPROM_MAX_BYTE 127 //letztes Byte des EEPROM (beim ATTiny2313 128 Byte großer Speicher)
    //
    extern unsigned char __heap_start;
    //
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/eeprom.h>
    #include <util/delay.h>
    /*
    #include <avr/interrupt.h>
    #include <stdio.h>
    #include <stdint.h>
    */
    //
    typedef struct {
      unsigned char D2:1;
      unsigned char D3:1;
      unsigned char D4:1;
      unsigned char D5:1;
    }swBit;
    //
    //
    //FUNKTIONS-PROTOTYPEN
    //--------------------
       static void USART_init(unsigned int baud);
              void USART_transmit(unsigned char cData);
              void USART_transmit_str(char *cStr);
              void USART_clear(void);
              void clearArray(char cArray[],int iMax);
              void __attribute__ ((naked, section (".init8"))) __init8_mem (void);
    static uint8_t eeprom_get_next_byte(uint8_t iLastByte);
    static uint8_t eeprom_get_first_written_byte(uint8_t iLastByte,uint8_t iWrittenBytes);
              void myDebounce(swBit *bitfeld,uint8_t iPin);
              void long_delay_ms( unsigned long ms );
    //
    //
    //GLOBALE VARIABLEN
    //-----------------
    uint8_t i = 0;
    uint8_t iEEPROM_lastByte = 0;
    swBit swPressed;
    
    
    /***************/
    int main(void) {
    /***************/
             static char cUSART_inp[IUSART_INP_MAX];  //Array für das Zwischenspeichern von über USART empfangenen Zeichen
          unsigned short iUSART_inp = 0;  //Index für das Array cUSART_inp[], entspricht der Anzahl der empfangenen Zeichen
          unsigned short iDot = 0;  //zum ständigen Senden eines Punktes (als Lebenszeichen)
             static char cTmpZahl[4] = {0};  //Temp-Variable für Konvertierungen mit itoa()
           unsigned char cBoolSaved = 0;  //wurden die empfangenen Zeichen im EEPROM gespeichert?
           
    	//
    	DDRB = 0xff;	//Port B Pins als Ausgänge definieren
    	PORTB = 0xff;
    	//DDRD = 0x00;	//Port D Pins als Eingänge definieren. Wohl nicht notwendig, da die Bits standardmäßig sowieso 0 sind
    	//
    	USART_init(UART_BAUD_RATE);   //USART initialisieren
      //
      clearArray(cUSART_inp,IUSART_INP_MAX);
    	for(;;) {   //Endlosschleife (bei AVR-Programmierung gewollt/nötig)
        if( ++iDot % 1000 == 0 ) { //alle 1000 Durchläufe einen Punkt ans Terminal senden
          USART_transmit('.');  //Punkt senden
          iDot = 0;  //iTest natürlich zurücksetzen, um einen Überlauf zu verhindern
        }
        if( iUSART_inp > IUSART_INP_MAX ) {      //string wäre zu lang, also alles zurücksetzen
          USART_transmit_str("WARNUNG: >");                       //Warnung ans
          USART_transmit_str(itoa(IUSART_INP_MAX,cTmpZahl,10));   //Terminal senden
          USART_transmit_str(" Zeichen - RESET ");                //
          clearArray(cUSART_inp,IUSART_INP_MAX);  //Array zurücksetzen
          iUSART_inp = 0;   //Array-Index zurücksetzen
          USART_clear();
        }
        //
    		if( UCSRA & (1<<RXC) ) {	//Zeichen werden empfangen und im char-array gespeichert
          //USART_transmit(UDR);  //sendet jedes empfangene Zeichen direkt wieder and Terminal
                                  //(kann zum grundsätzlichen Testen der Kommunikation aktiviert werden)
          cUSART_inp[++iUSART_inp-1] = UDR; //empfangenes Zeichen im Array speichern
          cBoolSaved = 0;   //"gespeichert"-Status auf 0 (false) setzen
    		}
        //
        if( !(PIND & (1<<PIND2)) && iUSART_inp>0 && !swPressed.D2 && !cBoolSaved) {    //SW0 gedrückt
          for(i=0;i<iUSART_inp;i++) {
            //char-array (cUSART_inp) in EEPROM speichern
            eeprom_write_byte((uint8_t*)(unsigned int)eeprom_get_next_byte(iEEPROM_lastByte),cUSART_inp[i]);
          }
          //
          clearArray(cUSART_inp,IUSART_INP_MAX);  //Array zurücksetzen
          //
          USART_transmit_str(" SAVED ");  //damit man was sieht...
          cBoolSaved = 1;   //"gespeichert"-Status auf 1 (true) setzen
        }
        //
        myDebounce(&swPressed,PIND2);
        //
        if( !(PIND & (1<<PIND3)) && iUSART_inp>0 && !swPressed.D3 && cBoolSaved) {    //SW1 gedrückt
          //
          for(i=0;i<iUSART_inp;i++) {
            //Inhalt des EEPROM rurück in das char-array schreiben
    //        cUSART_inp[i] = eeprom_read_byte((uint8_t*)(unsigned int)eeprom_get_first_written_byte(iEEPROM_lastByte,iUSART_inp-1-i));
            cUSART_inp[i] = eeprom_read_byte((void*)eeprom_get_first_written_byte(iEEPROM_lastByte,iUSART_inp-1-i));
          }
          //
          USART_transmit_str(cUSART_inp);  //Array ans Terminal senden
          //
          iUSART_inp = 0; //Array-Index zurücksetzen
          cBoolSaved = 0; //"gespeichert"-Status auf 0 (false) setzen
        }
        //
        myDebounce(&swPressed,PIND3);
        //
        if( !(PIND & (1<<PIND4)) && !swPressed.D4 ) {  //SW2 gedrückt: iUSART_inp (Anzahl eingegebener Zeichen) ausgeben
          USART_transmit_str(" Anzahl Zeichen: ");                //ans Terminal
          USART_transmit_str(itoa(iUSART_inp,cTmpZahl,10));   //senden
          USART_transmit(32);                                 //
        }
        //
        myDebounce(&swPressed,PIND4);
        //
        if( !(PIND & (1<<PIND5)) && !swPressed.D5 ) {          //SW3 gedrückt: freien Speicher (SRAM) ermitteln
          USART_transmit_str(" FREE MEM: ");                //und ans Terminal senden
          USART_transmit_str(itoa(SP - (uint16_t) &__heap_start,cTmpZahl,10));
          USART_transmit_str(" Bytes ");
        }
        //
        myDebounce(&swPressed,PIND5);
        //
    	}
    	//
    	return(0);  //wird nie erreicht, da Endlosschleife...
    }
    
    
    /***************/
    static void USART_init(unsigned int baud) {    //nochmal genau ansehen und schöner formulieren!
    /***************/
    /*
    UBRRH = (unsigned char)(baud>>8);		//Baudrate setzen
    UBRRL = (unsigned char)baud;				//
    //
    UCSRB = (1<<RXEN)|(1<<TXEN);		//Receiver und Transmitter aktivieren
    //
    UCSRC = (1<<USBS)|(3<<UCSZ0);	//8 Datenbits, 2 Stopbits (?)
    */
    UCSRA=0x00;
    //UCSRB=0x08;
    UCSRC=0x86;
    UBRRH=0x00;
    UBRRL=0x17;
    //
    UCSRB = (1<<RXEN)|(1<<TXEN);		//Receiver und Transmitter aktivieren
    }
    
    /***************/
    void USART_transmit(unsigned char cData) {  //sendet ein Zeichen ans Terminal
    /***************/
    	while( !(UCSRA & (1<<UDRE)) ) {
    		;//warten, bis der transmit buffer leer ist, so dass wieder übertragen werden kann
    	}
    	UDR = cData;
    }
    
    /***************/
    void USART_transmit_str(char *cStr) {   //sendet einen String (char-Array) ans Terminal
    /***************/
      while(*cStr) {
        USART_transmit(*cStr++);
      }
    }
    
    /***************/           //Liest solange empfangene Zeichen ein (und verwirft sie), bis 
    void USART_clear(void) {    //keine mehr da sind.
    /***************/
      uint8_t cTmp;
      while( UCSRA & (1<<RXC) ) {
        cTmp = UDR;
      }
      while( UCSRA & (1<<RXC) ) {
        cTmp = UDR;
      }
      return;
    }
    /***************/
    void clearArray(char cArray[],int iMax) { //ersetzt alle Werte in einem Array durch binäre Nullen ('\0')
    /***************/
      for(i=0;i<iMax;i++) {
        cArray[i]='\0';
      }
    }
    
    /***************/
    static uint8_t eeprom_get_next_byte(uint8_t iLastByte) {
    /***************/
      uint8_t iNextByte = iLastByte + 1;
      //
      if(iNextByte > EEPROM_MAX_BYTE) {
        iNextByte = 0;
      }
      //
      iEEPROM_lastByte = iNextByte;
      return(iNextByte);
    }
    
    /***************/
    static uint8_t eeprom_get_first_written_byte(uint8_t iLastByte,uint8_t iWrittenBytes) {
    /***************/
      uint8_t iFirstByte;
      if( iLastByte - iWrittenBytes < 0 ) {
        iFirstByte = EEPROM_MAX_BYTE + iLastByte - iWrittenBytes;
      } else {
        iFirstByte = iLastByte - iWrittenBytes;
      }
      return(iFirstByte);
    }
    
    /***************/                                   //damit beim Tastendruck nur einmal der
    void myDebounce(swBit *bitfeld,uint8_t iPin) {      //entsprechende Programmteil ausgeführt wird.
    /***************/                                   //Die übergebene Struktur speichert, welche
      switch(iPin) {                                    //Tasten gerade gedrückt sind oder nicht
        case(2):                                        //(0=nicht gedrückt, 1=gedrückt).
          if( !(PIND & (1<<iPin)) && !(bitfeld->D2) ) { //Wird eine Taste gedrückt, wird ein weiteres
            bitfeld->D2 = 1;                            //Drücken bzw. Gedrückthalten solange ignoriert,
          }else {                                       //bis sie wieder losgelassen wurde.
            if( PIND & (1<<iPin) ) {
              bitfeld->D2 = 0;
            }
          }
          break;
        case(3):
          if( !(PIND & (1<<iPin)) && !(bitfeld->D3) ) {
            bitfeld->D3 = 1;
          }else {
            if( PIND & (1<<iPin) ) {
              bitfeld->D3 = 0;
            }
          }
          break;
        case(4):
          if( !(PIND & (1<<iPin)) && !(bitfeld->D4) ) {
            bitfeld->D4 = 1;
          }else {
            if( PIND & (1<<iPin) ) {
              bitfeld->D4 = 0;
            }
          }
          break;
        case(5):
          if( !(PIND & (1<<iPin)) && !(bitfeld->D5) ) {
            bitfeld->D5 = 1;
          }else {
            if( PIND & (1<<iPin) ) {
              bitfeld->D5 = 0;
            }
          }
          break;
        //
      }
    }
    
    
    /***************/                         //hält für ms Millisekunden die Programmausführung an
    void long_delay_ms( unsigned long ms ) {  //(nicht mehr im Programm verwendet)
    /***************/
      while( ms-- )
        _delay_ms( 1 );
    }
    Gruß Matze

Seite 3 von 3 ErsteErste 123

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test