1
\$\begingroup\$

Im having problem with global arrays in my C code. What i am trying to do is to use a display buffer (array of 8 uint8_t with each uint8_t representing a row) to light up the leds in 8x8 led matrix using column scanning.

the relevant part of code is:

#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
    }
}

When I run it I see the whole column light up (whole 8x8 grid lid up with scanning) and it seems the problem is happening in the line

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

in addCharToString(). if i comment out this line and use a constant value (0b10000001) in the above code it gets displayed perfectly (first and the last column lighting up)

It seems that the array(s) h, o and t are not getting initialized properly. Any ideas what could be happening here

I am using ATMEGA8.

Update:

I am using -0s optimization with the following flags set

  • funsigned-chars
  • funsigned-bitfields
  • fpack-struct
  • fshort-enums
\$\endgroup\$
  • \$\begingroup\$ If they are LUTs, try declaring them const, which would allow the compiler to move them into program ROM. If they are variable arrays I'm not sure how they would be initialised. (when I use AVR-gcc I don't program in C, just Ada) \$\endgroup\$ – Brian Drummond Mar 7 '13 at 11:07
  • \$\begingroup\$ @BrianDrummond I did also try using the PROGMEM keyword so the code became const uint8_t h[8] PROGMEM = { 0b11111111, 0b10000001, 0b10100101, 0b10100101, 0b10111101, 0b10100101, 0b10000001, 0b11111111 }; and 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; } } but the result was the same \$\endgroup\$ – Ankit Mar 7 '13 at 11:20
  • \$\begingroup\$ A further diagnostic might be worth a try is display_string[i][pos] = i, just to make sure your writeDisplayBuffer routine isn't ORing all bits across each row or something like that. \$\endgroup\$ – PeterJ Mar 7 '13 at 11:26
  • \$\begingroup\$ @PeterJ This is weird. using display_string[i][pos] = i produces a blank display \$\endgroup\$ – Ankit Mar 7 '13 at 11:36
  • \$\begingroup\$ Maybe your problem is elsewhere, I'd normally make them const as Brian suggested but only because AVRs have more FLASH than RAM, but I've certainly put initialized arrays in RAM before without problems, they get initialized before main is called. \$\endgroup\$ – PeterJ Mar 7 '13 at 11:41
2
\$\begingroup\$

Found the solution. As suggested by members at avrfreaks.net here the problem was that by using the default makefile the .data part of code was not getting included in the final hex file. as a result the ram was getting initialized by default value (0xFF) since it could not find the array values (in the .data part). Using a custom makefile with the flag -j .data in avr-objcopy solved the problem.

\$\endgroup\$
0
\$\begingroup\$

You array initialisation is fine; see How to initialise an array in C, or K&R for chapter & verse. Up to the call to writeDisplayBuffer everything is good. Maybe the problem is within write595(), set2903Pin() or in your circuit somewhere.

\$\endgroup\$
  • \$\begingroup\$ i have added the code for setupDisplayBuffer() and writeDisplayBuffer() to my post. I've looked over them so many times but cant seem to pinpoint the mistake. \$\endgroup\$ – Ankit Mar 7 '13 at 13:58
  • \$\begingroup\$ They seem fine - Ive fired them up in a debugger and your code successfully continually calls the write595 function with the bitmaps for the first letter. Looks like the problem is deeper down. \$\endgroup\$ – Richard Padley Mar 7 '13 at 16:58
  • \$\begingroup\$ Yep something is definitely up! when i use the statement display_string[i][pos] = i; i get a blank display. using a constant value such as display_string[i][pos] = 0b10000001; produces the right pattern \$\endgroup\$ – Ankit Mar 7 '13 at 20:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.