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

understanding port and peripherals

I am a newbie, and I am banging my head on the wall to get my system to work. I am lacking tools (scope mainly) but I am really keen to understand how to use the 8051 mcu. I hope more experienced programmers will take some time to help me out , I would really apreciate. What I know is working might help. I have an external EEPROM and RAM, and access to those peripheral is OK. A 4by4 keyboard, connected to P1 works fine, the same for LCD connected to P1, with program running from internal RAM of MCU or external RAM.

My problems are :
I am using a 2by16 LCD, and I have tested my routines for the LCD by using P1 for the data bus (LCD_BUS), and P3.2, P3.3 and P3.4 as the control lines RS, RW, EN. I do not have any problem at all with the data bus being P1. I also use a matrix keyboard (4 by 4), which I also tested on P1. I wrote the software to be able to change the bus definition by changing the port name, ie #define LCD_BUS P1 for the LCD and #define KEYBOARD P1. I want to use the keyboard on P1, and the LCD on P0. Because I have already a data bus on P0 (I use P0&P2 to access an external program in EEPROM and save data to NVRAM) it saves me one port, but I still use the same control lines (P3.2,P.3,P.4). Now my problem is the LCD does not work at all (probably not configured since I can see the top line with 5*7 black square, ..)
I did the following to test the hardware : I tested with the soft running from mcu (/EA = VCC) and remove peripheral from bus (RAM and ROM), still the same. Since P0 is an open drain port, I added 3.3K resistors for the data lines, still the same, and I did change the define statement to use P0. I tried to connect the keyboard to P0, with pull up resistors (3.3K) and the keyboard does not work, and on P2 I have got the same problem ... (I did change the ort definition for the keyboard as well...) So I can have a displayon P1 running fine, the keyboard on P1 as well and that's all folks...

I also tried to memory map the LCD, RS being connected to A0, RW to A1, LCD address is 0x8000 anda GAL 16V8A used as the decoder for the chip select

/* Inputs: */

Pin 2 = PSEN; /* active low */
Pin 3 = RD; /* active low */
Pin 4 = WR; /* active low */
Pin 5 = A15; /* active high */

/* Outputs: */

Pin 16 = NOE_RAM;
Pin 17 = CS_LCD;
Pin 18 = CS_RAM;
Pin 19 = OE_RAM;

/* Logic: EQUATIONS */

OE_RAM = RD & PSEN;
CS_LCD = RD & A15 # WR & A15;
CS_RAM = !A15;

(I use WinCUPL to program the GAL)

in the C program I define the CS_ LCD as ADR_LCD :

unsigned xdata ADR_LCD _at_ 0x8000; /* chip select for LCD */
#define DATA_BUS P0

to create the enable signal I use

CS_LCD = 1;
CS_LCD=0;

to write a character to display

void Data_Write(unsigned char character)
{

XBYTE[ADR_LCD+1] = character; // RS = 1, R/W = 0
CS_LCD = 1;
CS_LCD=0;
DATA_BUS = 0xFF; /* Data bus in read mode (HiZ) */

}

to read a character to display

unsigned char Read_Data(void)
{
unsigned char Read_bus;

DATA_BUS = 0xFF; /* Data bus in read mode (HiZ) */
XBYTE[ADR_LCD+3]; /* RS = 1, R/W = 1 */
CS_LCD = 1;
Read_bus = DATA_BUS; /* Read Data */
CS_LCD = 0; /* EN pulse */
return (Read_bus);

}

I also tried to use a NVRAM (DS1230) to be use to store code and data bu anding /PSEN and /RD as the /OE, /RD connected to /CE and /WR to /WE (equation with the GAL above), and program the NVRAM with a simple routine (loop forever that toggles P1.0 rougthly every second ) and I am sure you have guessed the result ? Does not work. Now I do not have an osilloscope (I know, need the budget...would help a lot).

Last problem, I have tried to write low level routines to use with the I2C bus, such as a 24LC16B serial EEPROM and a DS1844 digital potentiometer. I do not think they are not working, but I have roblem with the high level routines and how to use the ack, no_ack signal... Could some point me to some web site with example ?

Could someone tell me if I am miles away from the truth, should it be a bad wire connection that could give me so much trouble ?
Thanks for any help

  • Check the timing on your LCD. The RD and WR lines probably toggle too fast for it. Most of the LCD's I've used required that all the signal lines are on I/O ports and are toggled slowly (from software).

    There is some assembly source code (it is not too long) at http://www.boerde.de/~matthias/m8051/ that may be helpful. Look for charlcd.zip LCD-driver for Hitachi HD44100/HD44780.

    Jon

  • OK - LCD & keypad will work on P1, but neither LCD or keypad will work on P0.

    I see a few potential problems here. I would try to use P0 the same way you used P1. That is, skip using the XBYTE macro and manipulate P0 directly for the LCD. As long as make sure P2.7 (A15) remains high, your RAM & ROM should stay off the bus (assuming your chip select logic only enables RAM or ROM below 0x8000)

    Then write your code like this:
    //if P0, RD, WR, A15 are not yet defined
    // define them here
    #define P0 0x80
    #define RD 0xB7
    #define WR 0xB6
    #define A15 0xA7
    void Data_Write(unsigned char character)
    {
    A15 = 1;//this turns off RAM & ROM
    CS_LCD = 1;//if active hi or 0 if active low
    //assert anything else that the LCD
    //needs asserted here
    WR = 0; //assert write signal
    P0 = character; //put data on bus
    WR = 1; //deassert write signal
    CS_LCD = 0;//if active hi or 1 if active low
    //deassert everything asserted above here
    P0 = 0xFF; //maybe not needed - but doesn't hurt
    }
    unsigned char Read_Data(void)
    {
    unsigned char Read_bus;
    A15 = 1;//turns off RAM & ROM
    CS_LCD = 1;//if active hi or 0 if active low
    //assert anything else that the LCD
    //needs asserted here
    P0 = 0xFF;//prime data bus
    RD = 0;//assert read signal
    Read_bus = P0; //data is on bus, get it
    RD = 1;//deassert read signal
    CS_LCD = 0;//if active hi or 1 if active low
    //deassert anything asserted above here
    return (Read_bus);
    }

    With no scope or logic analyzer, you can debug your signals with a multimeter by inserting an endless loop in your code immediately after the instruction that you are interested in.

    Use

    while(1)
    ;

    for your endless loop.

    Essentially, your setup is "frozen" in the state it was in right before it went into the endless loop. You can then use a regular old multi-meter to see what signals are high and what signals are low.
    This works, but can be tedious since you have to constantly reprogram the code when you want to move the loop or take it out completely.

    You can use XBYTE if you want to. But, understand that the read or write takes place entirely "within" that instruction. In other words, you need to make sure that you assert everything that must be asserted and then do the XBYTE then deassert the LCD stuff.
    Or, if using the GAL to generate your chip selects - fix your CS_LCD equation.

    CS_LCD = !A15#(RD&WR);//CS_LCD active low
    CS_LCD = A15&(!RD#!WR);//CS_LCD active hi

    By the way, getting both the LCD and keypad working on P1 is pretty sophisticated for a Newbie. You are getting close!

    Good luck.