C programming for uC

Yeti

Joined Jul 26, 2005
35
I have a question about the coding for something in C for use with a microcontroller:

one of the examples in the text book is for interfacing a 4x4 key pad. my problem is that the text boook splits up the columns and rows from the key pad on two ports. I would like to split the rows and columns on one port( im using a P89LPC925 micro its a 8051).

heres the part of the code I would like to change

code from text:

#define COL P2
#define ROW P1

I think that in assembly there is some sort of DPL and DPH for using the high byte adn low byte. I would like to use Port 0 for the whole keypad.

So is there a way to say something like

#define COL DPH P2 // to get COL to be the high byte
#define ROW DPL P2 // ROW to be the low byte

Thanks
Yeti

If it helps any this is the whole code:

#include <reg51.h>
#include <stdio.h>

sfr p0m1 = 0x84; // this is no tin the text, but is used to make the ports
sfr p0m2 = 0x85; // bidirectional
//sfr p1m1 = 0x91; //
//sfr p1m2 = 0x92; //

#define COL P0
#define ROW P0
//#define TX P1

void MSDelay(unsigned int value);
void SerTX(unsigned char);

unsigned char keypad[4][4] = {'1', '2', '3', '+',
'4', '5', '6', '-',
'8', '9', '+', '*',
'.', '0', '=', '/'};

void main()
{
unsigned char colloc, rowloc;

PCON &= 0x7F; //
TMOD = 0x20; //
TH1 = 0xF4; // these values are different than the test b/c of the uC
TL1 = 0xF4; // i am using.
SCON = 0x50; //
TR1 = 1; //
COL = 0xF0; //to set the COL high and ROW low
ROW = 0xF0;
//TX = 0x7F; // the TX pin is P1.0, so setting it low for ouputting

while(1)
{
do
{
colloc = COL>>4;
colloc&= 0x0F;
}while(colloc != 0x0F);

do
{
do
{
MSDelay(20);
colloc = COL>>4;
colloc &= 0x0F;
}while(colloc == 0x0F);

MSDelay(20);
colloc = COL>>4;
colloc &= 0x0F;
}while(colloc == 0x0F);

while(1)
{
ROW = 0xFE;
colloc = COL>>4;
colloc &= 0x0F;
if(colloc != 0x0F)
{
rowloc = 0;
break;
}
ROW = 0xFD;
colloc = COL>>4;
colloc &= 0x0F;
if(colloc != 0x0F)
{
rowloc = 1;
break;
}
ROW = 0xFB;
colloc = COL>>4;
colloc &= 0x0F;
if(colloc != 0x0F)
{
rowloc = 2;
break;
}
ROW = 0xF7;
colloc = COL>>4;
colloc &= 0x0F;
if(colloc != 0x0F)
{
rowloc = 3;
break;
}
}
if(colloc == 0x0E)
else if(colloc == 0x0D)
else if(colloc == 0x0B)
else
}
}

void SerTX(unsigned char x)
{
SBUF = x;
while(TI == 0);
TI = 0;
}

void MSDelay(unsigned int value)
{
unsigned int x, y;
for(x=0; x<1275; x++)
for(y=0; y<value; y++);
}

Papabravo

Joined Feb 24, 2006
16,810
Greetings Mr. Snowman

That is a quaint but incorrect notion. DPL and DPH are hardware registers in the 8051 architecture. They are used in conjunction with PORT 0 and PORT 2 to access external memory. PORT 0 contains the low order 8 bits of the external memory address and the 8-bit data at different times of course. PORT 2 contains the high order 8 bits of the external address. The values which show up on PORT 0 and PORT 2 come from DPL and DPH respectivly when the processor executes the instructions "MOVX A,@DPTR" or "MOVX @DPTR,A". DPTR is the name for the two 8-bit registers DPH and DPL concatenated together to form a 16-bit address register.

You can define ROW and COL to be the same thing! What matters is the values that you write to ROW and COL and what you do with the values that you read back from them. You also need to read the data sheet very carefully to understand the meaning of "quasi-bi-directional I/O port". All 8051 ports work this way. In simple terms just write ones to any bits that you want to be inputs. Consider the following code fragment to see if it works for you.

Rich (BB code):
#define ROW P2
#define COL P2

#define ROW0 0xFE
#define ROW1 0xFD
#define ROW2 0xFB
#define ROW3 0xF7
.
.
.
unsigned char key;

ROW = ROW0;   //Enable ROW0 by taking bit 0 low
key = COL >> 4; //Read column values in bits [7..4]
ROW = 0xFF;   //Disable all rows
.
.
.

Yeti

Joined Jul 26, 2005
35
Thanks for your reply I was in process of posting the full code while you replied. I'll try to integrate your thoughts into the code. We are to make a simple calculator, and this code was refered by the prof, but I was not able to get the keypad to work yet with the hyperterm. I'll keep goin at it though

Thanks
Yeti

Papabravo

Joined Feb 24, 2006
16,810
Originally posted by Yeti@May 7 2006, 12:57 AM
Thanks for your reply   I was in process of posting the full code while you replied.  I'll try to integrate your thoughts into the code.  We are to make a simple calculator, and this code was refered by the prof, but I was not able to get the keypad to work yet with the hyperterm.  I'll keep goin at it though

Thanks
Yeti
[post=16864]Quoted post[/post]​
Snowman,

Hold the phone son, you do know that PORT 0 has "open-collector" outputs and that you need pullup resistors for those bits on port 0 that are supposed to be outputs. Of course you know that.

Also the serial port TX and RX are on PORT 3, bits 0 and 1, but you knew that too right?

Good Luck

Yeti

Joined Jul 26, 2005
35
Hrm are you looking at the right micro data sheet? I have the TX pin as port 1.0, and port 3 on this one is CLKOUT/XTAL2. it is a Phillips P89LPC925 20 pin DIP

Ill have to look more on the port 0. I can however get something on teh hyperterm using this program, but there is no keypad, It just lets me know that it is possible to get something. It just sends a letter "A" every two seconds or so.

#include <reg51.h>
#include <stdio.h>
sfr p1m1 = 0x91;
sfr p1m2 = 0x92;

void Delay(unsigned int);

void main(void)
{
unsigned char myChar = 'A';

p1m1 = 0x00;
p1m2 = 0x00;

PCON &= 0x7F;
TMOD = 0x20;
TH1 = 0xF4;
TL1 = 0xF4;
SCON = 0x50;
TR1 = 1;

while(1)
{
Delay(250);
SBUF = myChar;
while(TI==0);
TI=0;
Delay(250);
}
}

void Delay(unsigned int mytime)
{
unsigned int i, j;
for(i=0; i<1275; i++)
for(j=0; j<mytime; j++);
}

Papabravo

Joined Feb 24, 2006
16,810
You're right I thought it was the traditional pinout with four 8-bit ports. I was led astray by the discussion of DPH, DPL, and the data pointer. I assumed, incorrectly, that an external bus was possible and therefore your part had four ports instead of two.