AVR GCC: Globales/Statisches Array wird nicht richtig initialisiert

Ich habe ein Problem mit globalen Arrays in meinem C-Code. Was ich versuche, ist, einen Anzeigepuffer (Array von 8 uint8_t, wobei jedes uint8_t eine Zeile darstellt) zu verwenden, um die LEDs in einer 8x8-LED-Matrix mit Spaltenscannen zu beleuchten.

Der relevante Teil des Codes ist:

#include <avr/io.h> 
#include <util/delay.h> 
#include <stdlib.h> 
#include <avr/interrupt.h> 

uint8_t string_size=3;               //DISPLAY STRING SIZE 
uint8_t display_string[8][3];         //DISPLAY STRING 
uint8_t display_buffer[8];            //CURRENT DISPLAY BUFFER 

/***************************************** 
CHARACTER MAPS 
*****************************************/ 
uint8_t h[8]= { 
0b11111111, 
0b10000001, 
0b10100101, 
0b10100101, 
0b10111101, 
0b10100101, 
0b10000001, 
0b11111111 
}; 

uint8_t o[8]= { 
0b11111111, 
0b10000001, 
0b10111101, 
0b10100101, 
0b10100101, 
0b10111101, 
0b10000001, 
0b11111111 
}; 

uint8_t t[8]= { 
0b11111111, 
0b10000001, 
0b10111101, 
0b10011001, 
0b10011001, 
0b10011001, 
0b10000001, 
0b11111111 
}; 

/***************************************** 
FUNCTIONS 
*****************************************/ 
void addCharToString(uint8_t pos, uint8_t chr[]);   //ADD PASSSED CHAR TO SPECIFIED POS IN STRING 
void setupDisplayBuffer();                     //SETUP INITIAL DISPLAY BUFFER 
void writeDisplayBuffer();                     //DRAW CURRENT DISPLAY BUFFER 


int main() 
{ 

   addCharToString(0,h); 
   addCharToString(1,o); 
   addCharToString(2,t); 
   setupDisplayBuffer(); 

   for(;;) 
   { 
      writeDisplayBuffer(); 
   } 
} 

void addCharToString(uint8_t pos, uint8_t arr[]) 
{ 
   for(uint8_t i=0;i<8;i++) 
   { 
      //display_string[i][pos] = arr[i]; //PROBLEM HERE! 
      display_string[i][pos] = 0b10000001; 
   } 

} 
void setupDisplayBuffer()
{
    //COPY THE FIRST CHARACTER FROM DISPLAY STRING TO DISPLAY BUFFER
    for(uint8_t i=0;i<8;i++)
    {
        display_buffer[i] = display_string[i][0];
    }
}

void writeDisplayBuffer()
{
    for(uint8_t i=0;i<8;i++)
    {
        write595(display_buffer[i]);
        set2903Pin(i);
        _delay_loop_2(1986); // ACCURATE 1MS DELAY .. HIGHER THAN THIS = FLICKERING
    }
}

Wenn ich es ausführe, sehe ich, dass die gesamte Spalte aufleuchtet (der gesamte 8x8-Gitterdeckel beim Scannen) und es scheint, dass das Problem in der Zeile auftritt

display_string[i][pos] = arr[i];

in addCharToString(). Wenn ich diese Zeile auskommentiere und einen konstanten Wert (0b10000001) im obigen Code verwende, wird er perfekt angezeigt (erste und letzte Spalte leuchten)

Es scheint, dass die Arrays h, o und t nicht richtig initialisiert werden. Irgendwelche Ideen, was hier passieren könnte

Ich verwende ATMEGA8.

Aktualisieren:

Ich verwende -0s-Optimierung mit den folgenden gesetzten Flags

  • funsigned-chars
  • funsigned-bitfields
  • fpack-Struktur
  • fshort-enums
Wenn es sich um LUTs handelt, versuchen Sie, sie als konstant zu deklarieren, was es dem Compiler ermöglichen würde, sie in das Programm-ROM zu verschieben. Wenn es sich um variable Arrays handelt, bin ich mir nicht sicher, wie sie initialisiert werden. (wenn ich AVR-gcc verwende, programmiere ich nicht in C, nur Ada)
@BrianDrummond Ich habe auch versucht, das Schlüsselwort PROGMEM zu verwenden, damit der Code wurde const uint8_t h[8] PROGMEM = { 0b11111111, 0b10000001, 0b10100101, 0b10100101, 0b10111101, 0b10100101, 0b10000001, 0b11111111 }; und void addCharToString(uint8_t pos, const uint8_t arr[]) { for(uint8_t i=0;i<8;i++) { display_string[i][pos] = pgm_read_byte(&arr[i]); //PROBLEM HERE! //display_string[i][pos] = 0b10000001; } } das Ergebnis dasselbe war
Eine weitere Diagnose, die einen Versuch wert sein könnte, ist display_string[i][pos] = i, nur um sicherzustellen, dass Ihre writeDisplayBuffer-Routine nicht alle Bits in jeder Zeile oder so ähnlich ODER-verknüpft.
@PeterJ Das ist komisch. Die Verwendung display_string[i][pos] = ierzeugt eine leere Anzeige
Vielleicht liegt Ihr Problem woanders, ich würde sie normalerweise konstant machen, wie Brian vorgeschlagen hat, aber nur, weil AVRs mehr FLASH als RAM haben, aber ich habe sicherlich initialisierte Arrays ohne Probleme in RAM gelegt, sie werden initialisiert, bevor main aufgerufen wird.
Teile und herrsche. display_string[i][pos] = temp;Wenn es funktioniert, temp = 0b10000001;dann versuchen Sie estemp = arr[i];
Es scheint, dass mit meiner displayStringBuffer() -Routine etwas nicht stimmt. lass mich prüfen und berichten
Es wurde mir bei avrfreaks.net post vorgeschlagen , dass mein Makefile keine .data zum letzten Hex hinzufügt. Ich verwende die Standardeinstellungen in AVR Studio 4. Wie kann ich sicherstellen, dass es auch den .data-Teil zu meinem endgültigen Hex hinzufügt?

Antworten (2)

Lösung gefunden. Wie von Mitgliedern von avrfreaks.net hier vorgeschlagen , bestand das Problem darin, dass durch die Verwendung des Standard-Makefiles der .data-Teil des Codes nicht in die endgültige Hex-Datei aufgenommen wurde. Als Ergebnis wurde der RAM mit dem Standardwert (0xFF) initialisiert, da er die Array-Werte (im .data-Teil) nicht finden konnte. Die Verwendung eines benutzerdefinierten Makefiles mit dem Flag -j .datain avr-objcopy löste das Problem.

Ihre Array-Initialisierung ist in Ordnung; siehe So initialisieren Sie ein Array in C oder K&R für Kapitel und Vers. Bis auf den Aufruf von writeDisplayBuffer ist alles gut. Vielleicht liegt das Problem in write595(), set2903Pin() oder irgendwo in Ihrer Schaltung.

Ich habe den Code für setupDisplayBuffer() und writeDisplayBuffer() zu meinem Beitrag hinzugefügt. Ich habe sie so oft durchgesehen, aber ich kann den Fehler nicht lokalisieren.
Sie scheinen in Ordnung zu sein - ich habe sie in einem Debugger gestartet und Ihr Code ruft erfolgreich kontinuierlich die Funktion write595 mit den Bitmaps für den ersten Buchstaben auf. Das Problem scheint tiefer zu liegen.
Ja, da ist definitiv was los! Wenn ich die Anweisung verwende, display_string[i][pos] = i;erhalte ich eine leere Anzeige. die Verwendung eines konstanten Werts wie display_string[i][pos] = 0b10000001;erzeugt das richtige Muster