This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problem while using external RAM

Hi,

I am stuck up a peculiar problem while using 8051 external RAM.

I am declaring a variable:
unsigned int xdata x _at_ 0xA004;

then I equate:
x=6;

and i display this value on the hyperterminal (RS232) window using the function:

serial_num(x+0x30);

every thing goes fine and the value 6 is diaplayed on the hyper terminal window.

PROBLEM:

when i equate the value x to another variable *p and try to display the value *p i am unable to get the value on the hyper terminal window.

unsigned int xdata *p _at_ 0xA008;

x=6;
p=&x;
serial_num(*p+0x30);

when I try to display this on the hyper terminal (RS232) window I get garbage values displayed on the screen.

Here is the code that was developed.

#pragma LARGE
#include<reg52.h>
#include<string.h>
#include<absacc.h>
#include<intrins.h>
#include<ctype.h>

sbit RXD_pin=P3^0;
sbit TXD_pin=P3^1;
sbit INT0_pin=P3^2;
sbit INT1_pin=P3^3;
sbit WRITE_pin=P3^6;
sbit READ_pin=P3^7;

unsigned int xdata read_byte _at_ 0xA001, write_byte _at_ 0xA003;
unsigned int xdata count _at_ 0xA005, *p _at_ 0xA007 , x _at_ 0xA009;
unsigned int idata i;
unsigned char xdata CS5_enable _at_ 0XA000;
//CS5_enable is the variable declared to chip select the external RAM. Static RAM used is HY6264. 8K RAM
unsigned char xdata CS2_enable _at_ 0x4000;

void read_ram(void);
void write_ram(void);
void serial_init(void);
void serial_num(unsigned char);
void delay(void);

void main(void)
{ serial_init();
while(1)
{ write_ram();
x=6;
p=&x;
write_ram();
write_byte=*p;//write value to external ram location
read_ram();
read_byte=write_byte;//read value from external ram location
serial_num(read_byte+0x30); //display on hyper terminal window screen
} }

void read_ram(void)
{ CS5_enable=1;
WRITE_pin=1;
READ_pin=1;
}

void write_ram(void)
{ CS5_enable=0;
WRITE_pin=0;
}

void serial_num(unsigned char s)
{ SBUF=s;
while(TI==0);
TI=0;
}

void serial_init(void)
{ TMOD=0x20;
SCON=0x50;
TH1=0xcc;
TR1=1;
}

  • x=6;
    p=&x;
    serial_num(*p+0x30);
    


    Take a careful look at the expression (*p+0x30) Ask yourself: what is the 1st operand of the '+' operator here? ie, are you adding 0x30 to the pointer, or to the pointed-to value? In fact, (*p+0x30) is equivalent to p[0x30] - which is, presumably, not what you want. Presumably, what you want is (*p)+0x30 ? See: c-faq.com/.../unopprec2.html BTW: using 0x30 as a Magic Number is poor style, since what you actually mean is "the ASCII code for the character '0'". Therefore, it would be clearer to write (*p)+'0' - and still put an explanatory comment.

  • how about,

    unsigned int r = *p;
    serial_num(r+0x30);

  • Hi thanks for your reply. actually the pointer is not the question over here. even if i try to use any other variable other than pointers and try to display the values i am getting garbage values on the screen.

  • "actually the pointer is not the question over here."

    But do you understand why your example with the pointer was incorrect, and could not possibly have worked?

  • Remember that x+0x30 will only yield an ASCII digit code (ie, '0' to '9') if the value of x is between 0 and 9.

    If x has any other values, you will see garbage!

    How are you checking that you have valid values in the range 0..9?

    The code you posted is illegible because you didn't follow the instructions for posting code. :-(
    Please read them, and re-post your code accordingly:
    http://www.keil.com/forum/tips.asp

  • Sorry - forum messed that up again - see:
    http://www.keil.com/forum/docs/thread8601.asp

    It should be:

    Take a careful look at the expression (*p+0x30)

    Ask yourself: what is the 1st operand of the '+' operator here?
    ie, are you adding 0x30 to the pointer, or to the pointed-to value?

    In fact, (*p+0x30) is equivalent to p[0x30] - which is, presumably, not what you want.

    Presumably, what you want is (*p)+0x30 ? See: c-faq.com/.../unopprec2.html

    BTW: using 0x30 as a Magic Number is poor style, since what you actually mean is "the ASCII code for the character '0'". Therefore, it would be clearer to write (*p)+'0' - and still put an explanatory comment.

  • In fact, (*p+0x30) is equivalent to p[0x30] - which is, presumably, not what you want.

    According to my C operator precedence table, the dereference operator takes precedence over the addition.

    (*p + 0x30)
    

    is equivalent to

    ((*p) + 0x30)
    

    However, the increment operator ++ (which is not used here) takes precedence over a dereference.

  • Here you are:

    #pragma LARGE
    #include<reg52.h>
    #include<string.h>
    #include<absacc.h>
    #include<intrins.h>
    #include<ctype.h>
    
    sbit RXD_pin=P0^0;
    sbit TXD_pin=P0^1;
    sbit INT0_pin=P0^2;
    sbit INT1_pin=P0^3;
    sbit WRITE_pin=P0^6;
    sbit READ_pin=P0^7;
    
    unsigned int xdata read_byte _at_ 0xA001, write_byte _at_ 0xA003;// Addresses to write Byte
    unsigned int xdata count _at_ 0xA005, *p _at_ 0xA007 , x _at_ 0xA00A;
    unsigned int xdata count _at_ 0xA005, *pt _at_ 0xB007 , y _at_ 0xB00A;
    unsigned int idata i;
    unsigned char xdata CS5_enable _at_ 0XA000;
    //CS5_enable is the variable declared to chip select the external RAM.
    //Static RAM used is HY6264. 8K RAM
    unsigned char xdata CS2_enable _at_ 0x4000;
    
    void read_ram(void);
    void write_ram(void);
    void serial_init(void);
    void serial_num(unsigned char);
    void delay(void);
    
    void main(void){
            serial_init();                                  // Serial Port initialised
            while(1){
                    write_ram();                            // Write to RAM
                    x=7;
                    p=&x;                                               // Address of x in 'p'
                    write_ram();
    
            //      *pt = 3;
    
                    write_byte = *pt;                               //write value to external ram location
                    read_ram();
                    read_byte=write_byte;           //read value from external ram location
                    serial_num(read_byte+0x30); //display on hyper terminal window screen
                    // Adding 0x30 coz, (0x30 = 48), 48 is ASCII value for '0x00'  or '0'
            }
    }
    
    void read_ram(void){                    // Read from RAM
            CS5_enable=1;                           // Chip Select
            WRITE_pin=1;                            // Write Enable now set high
            READ_pin=1;                                     // Enable Read now set high
    }
    
    void write_ram(void){                   // Write function
            CS5_enable=0;                           // Enable Chip Select
            WRITE_pin=0;                            // Write operation Enabled
    }
    
    void serial_num(unsigned char s){
            SBUF=s;                                         // Transmission
            while(TI==0);
            TI=0;                                           // TI= Transmit Interrupt
    }
    
    void serial_init(void){
            TMOD=0x20;                                      // Timer 1, Mode 02, 8-bit Auto Reload
            SCON=0x50;                                      // smod=01, Receive Enable(REN) = 1
            TH1=0xcc;                                       // 0x0CC = 204;
            TR1=1;                                          // Start Timer
    }
    
    

  • I notice quite a few changes in the second version of code. This one is quite interesting:

    unsigned int xdata count _at_ 0xA005, *p _at_ 0xA007 , x _at_ 0xA009;

    changes to:

    unsigned int xdata count _at_ 0xA005, *p _at_ 0xA007 , x _at_ 0xA00A;

    however you no longer use 'p', instead you dereference an uninitialised pointer 'pt'.

    It also looks as though you have some sort of unusual xdata addressing scheme going on where it would appear (although I'm guessing) that you try to write to xdata while it is in 'read mode'. Would you care to elaborate a little on your RAM interface?

  • According to my C operator precedence table, the dereference operator takes precedence over the addition.

    No!

    (postfix ++) > (plus +) > (prefix ++) > (dereference *).

    So

    (*p+0x30)
    

    is rather equivalent to

    (*(p+0x30))
    

    !

  • What are you tring to do?
    Is there a reason you do not want the compiler to place the variables

    unsigned int xdata count _at_ 0xA005, *p _at_ 0xA007 , x _at_ 0xA00A;

    Are you sure everythig fits? how big is a pointer
    unsigned int xdata *p _at_ 0xA007
    put a generic pointer (3 bytes) in to Xdata at address 0xA007. It points to nothing.
    _at_ is usually used to get to memory mapped I/O

    A memory mapped pointer must be some interesting HW.

  • No!

    Yes. Citation please if you claim otherwise.

    Here's some of mine:

    publib.boulder.ibm.com/.../index.jsp
    www.cppreference.com/operator_precedence.html
    msdn2.microsoft.com/.../2bxt6kc4.aspx

    (postfix ++) > (plus +) > (prefix ++) > (dereference *).

    (postincrement ++) >> (preincrement ++ == dereference * )>> (binary addition.)

    preincrement and dereference actually have the same precedence.

    Maybe you're confusing the unary + with the binary +. They are treated differently as far as precedende goes.

  • "unsigned int xdata read_byte _at_ 0xA001, write_byte _at_ 0xA003;
    unsigned int xdata count _at_ 0xA005, *p _at_ 0xA007 , x _at_ 0xA009;
    unsigned int idata i;
    unsigned char xdata CS5_enable _at_ 0XA000;
    //CS5_enable is the variable declared to chip select the external RAM. Static RAM used is HY6264. 8K RAM
    unsigned char xdata CS2_enable _at_ 0x4000; "

    This was the code posted, and Raghu Ravi quoted the problem:
    "since when i equate the value x to another variable *p and try to display the value *p i am unable to get the value on the hyper terminal window."

    working to see what was the output ..

  • When we compile a program, does it give the desired output?
    Yes - wow, attempt right,
    no - debug, and find what problem,

    beginners as told put a printf and see what values are being to variables, any mistake in that, am afraid not,
    if so, pardon,
    no special intention, once we make up mind to start writing a program with an aim, is nt it run to completion,