3
\$\begingroup\$

i'm having a bit of a problem with this code. The code is intended to create an LCD MAP, with LCD routines to interface a 7 segment based LCD with the PIC24FJ128GA310 MCU with internal LCD driver.

the arrays DIGIT1 to DIGIT6 contain the LCD mapping for each 7segment DIGIT on the LCD, and they are all saved in code memory.

the array DIGITS[] is meant to contain the address of all the segment arrays so that a numerical index can be used with DIGIT[] to access each digit on the LCD for display.

enum COMS{COM0=0,COM1=0x40,COM2=0x80,COM3=0xC0};
enum SEGS
{//COM 0
    SEG_1A      = COM0 |0 , SEG_1B = COM0 |53, SEG_2A = COM0 |33, SEG_K1 = COM0 |44,
    SEG_K2      = COM0 |22, SEG_K8 = COM0 |21, SEG_4A = COM0 |62, SEG_4B = COM0 |61,
    SEG_5A      = COM0 |60, SEG_5B = COM0 |59, SEG_6A = COM0 |58, SEG_6B = COM0 |50,
    SEG_7A      = COM0 |61, SEG_7B = COM0 |48 ,SEG_8A = COM0 |59, SEG_8B = COM0 |26,
    SEG_9A      = COM0 |25, SEG_9B = COM0 |24, SEG_10A= COM0 |23, SEG_10B= COM0 |45,
    SEG_2B      = COM0 |52, SEG_3A = COM0 |32, SEG_3B = COM0 |51, SEG_S3 = COM0 |24,
//... LCD MAPS for COM1 - COM3 are ommited here for space
};

const BYTE DIGIT1[] = {SEG_1A,SEG_1B,SEG_1C,SEG_1D,SEG_1E,SEG_1F,SEG_1G};
const BYTE DIGIT2[] = {SEG_2A,SEG_2B,SEG_2C,SEG_2D,SEG_2E,SEG_2F,SEG_2G};
const BYTE DIGIT3[] = {SEG_3A,SEG_3B,SEG_3C,SEG_3D,SEG_3E,SEG_3F,SEG_3G};
const BYTE DIGIT4[] = {SEG_4A,SEG_4B,SEG_4C,SEG_4D,SEG_4E,SEG_4F,SEG_4G};
const BYTE DIGIT5[] = {SEG_5A,SEG_5B,SEG_5C,SEG_5D,SEG_5E,SEG_5F,SEG_5G};
const BYTE DIGIT6[] = {SEG_6A,SEG_6B,SEG_6C,SEG_6D,SEG_6E,SEG_6F,SEG_6G};
//...
const BYTE * Digits[] = {DIGIT1,DIGIT2,DIGI3,DIGIT4,DIGIT5,DIGIT6};

enum DIGITS {DIG1,DIG2,DIG3,DIG4,DIG5,DIG6,DIG7,DIG8,DIG9,DIG10};

enum MASK {
        ZERO = 0x3F, ONE = 0x06, TWO   = 0x5B, THREE = 0x4F, FOUR = 0x66,
        FIVE = 0x6D, SIX = 0x7C, SEVEN = 0x07, EIGHT = 0x7F, NINE = 0x67,
        BLANK= 0x00, MINUS = 0x40, OVERFLOW = 0x49,};

void DisplayDigit2(BYTE idx,BYTE Mask)
{
    const BYTE * digit;
    digit = Digits[idx];
    //BYTE vals;
    //vals = *digit;
    for(i=0; i<8;i++){
        DisplaySeg(digit,(Mask&1));
        digit++;//incrememt pointer
        Mask >>=1;
    }
}

The function DisplayDigit2() is called like this:

DisplayDigit2(DIG1,ONE);//Display 1 on the first digit of the LCD

The code compiles without problems, but when i try to step through the code, it compiler stopped on the first line

digit = Digits[idx];

with the message "User program stopped"

I then observe that in the watch window that the address of DIGIT1 in code memory is 0x48A, while that of DIGIT2 is 0x491.

But on checking their address in the array DIGITS, i see the values 0X848A, and 0x8491 for DIGIT1 and DIGIT2 respectively.

I'm not sure where exactly i got it wrong. enter image description here

\$\endgroup\$
5
\$\begingroup\$

Digits[] is supposed to be constant and contain pointers to constant pointers, right? Perhaps the precedence of * here could be a problem and maybe

const BYTE * Digits[] = {DIGIT1,DIGIT2,DIGI3,DIGIT4,DIGIT5,DIGIT6};

should be

const BYTE (*Digits)[] const = {DIGIT1,DIGIT2,DIGI3,DIGIT4,DIGIT5,DIGIT6};

http://en.wikipedia.org/wiki/Const-correctness

I also suggest adding that second "const". I don't think that is the problem, but if there is a bug that attempts to change Digits then that might help you find it. (BTW, it might be helpful to attempt to differentiate your variable names more -- the word "digit" is used in many forms and it would be easy for someone [especially an outsider like myself] to mistake one for another.)

BTW, I think you made a typo here (shouldn't it be ++ not **?)

digit**;//incrememt pointer

The way that I usually go about writing a 7-segment display interface is something like this:

// Human-readable bit values
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80

// Number of available positions on display
#define NUM_DIGITS 4

// Map symbols to segments
#define SYMBOL_0 (BIT0 | BIT1 | BIT2)
#define SYMBOL_1 (BIT0 | BIT5)
// (these are just examples -- not real mappings) 

// function prototypes
void display_number(int number);    // calls display_digit once per digit
void display_digit(unsigned char symbol, unsigned char position);    // writes symbol to one of the 7-segment positions
void display_refresh();    // Scans through each digit and illuminates segments again

const unsigned char digit_map[] = { SYMBOL_0, SYMBOL_1, ...}
unsigned char digits_being_displayed[NUM_DIGITS];


// (in main)
int x = 1234;
display_number(x);
// ...
// (in polling/timer loop)
display_refresh();


// (in display_number)
// Note: need to handle signs, convert number, etc. this is just for illustration
// ...
for (int pos=0; pos < NUM_DIGITS; pos++) {
    int i, temp = number;
    // get corresponding digit (depending on how you number your digits, this could be different)
    for (i=1; i<(pos+1); i++)
        temp /= 10;
    temp %= 10;
    switch (temp) {
        case 0:
            digit = SYMBOL_0;
            break;
        case 1:
            digit = SYMBOL_1;
            break;
        // ...
    }

    display_digit(digit_map[digit], pos); 
}

// ...

// (in display_digit)
digits_being_displayed[position] = value;  // this value can get written periodically to the display with display_refresh()

So I'm not quite familiar with the syntax / structures you are using (e.g. BYTE = {}) but I hope my comments are still helpful. If you like enum better than #define that is fine too, of course.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your input. my compiler, C30 v3.31 does not seem to accept the syntax: const BYTE (* Digits)[] const... I get an error on that line. I've also tried it this way: const BYTE * const Digits[], but still the same problem. And i've corrected the typo, and i appreciate all the other inputs thanks, but i would still like to know why the debugger stops on that first line of the DisplayDigit2() routine \$\endgroup\$ – TiOLUWA Aug 27 '12 at 17:44
  • \$\begingroup\$ I thought you were stepping or had a breakpoint set. Does your application work correctly (not counting the unexpected difference you saw in the watch window -- Jim Paris seems to have a good explanation for that -- and the stop)? \$\endgroup\$ – iX3 Aug 27 '12 at 19:08
  • \$\begingroup\$ Yes the code works correctly when i step through it, until it gets to the first line int he function. Jim Paris explains the watch window issues with the address, but that only goes to show me that what i see in the watch window is not the problem. Something still makes the debugger stop stepping through the code onces it executes the line of code in question. \$\endgroup\$ – TiOLUWA Aug 27 '12 at 21:17
  • \$\begingroup\$ Oh, I'm sorry. Nevermind my type suggestions then -- I thought the application wasn't working. Can you run it without the debugger attached? Or instead of stepping, can you set a breakpoint after it and run it to there? Sometimes I've seen stepping get messed-up by optimization. What version of MPLAB / C30 are you using and do you have optimization enabled? On another MCU I had a similar problem that was caused by a trap interrupt (I'd tried to write to a read-only area) that I didn't catch...if you change the left-side of that line to some dummy variable does it still stop? \$\endgroup\$ – iX3 Aug 27 '12 at 22:54
  • \$\begingroup\$ i'm usign C30 v3.31, with no optimization (i have actually tried it on various optimization levels with the same problem) I've also tried to set a break point to run until after that line, and i got the same issue. "user program stopped" with no reason or explanation. \$\endgroup\$ – TiOLUWA Aug 28 '12 at 14:53
3
\$\begingroup\$

I then observe that in the watch window that the address of DIGIT1 in code memory is 0x48A, while that of DIGIT2 is 0x491.

But on checking their address in the array DIGITS, i see the values 0X848A, and 0x8491 for DIGIT1 and DIGIT2 respectively.

This is normal. The PIC is not a flat memory space, so you need some way of marking the fact that address 0x12 in code memory is not the same as address 0x12 in SRAM, for example. The compiler uses extra high bits to denote this.

\$\endgroup\$
  • \$\begingroup\$ Further research reveals that the PIC24 hardware uses this upper bit to access program memory (flash or "const") via a paging register--usually PSVPAG. So it's real, and not just some compiler affectation. \$\endgroup\$ – gbarry Apr 17 '18 at 18:11

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.