| ??? 10/26/05 23:21 Read: times Msg Score: +1 +1 Good Answer/Helpful |
#103000 - Here it is Responding to: ???'s previous message |
Charles Bannister said:
Maybe they will contribute something positive to the thread. Here it is. Positive contributions include: 1: Obviously, added comments! 2: I have renamed a number of variables where the previous names were misleading; eg, 3: The decimal display routine now displays the supplied integer (in the mathematical sense) as an integer - rather than scaling it to X.YZ. The parameter has also been reduced to a char - as the routine only copes with 3 digits anyway. 4.: I have compiled it with Keil C51 v7.50 & tested the conversion routines in the Keil simulator. 5.: And, of course, the fundamental problem of the delay loop has been highlighted #include <REG52.H>
// EXAMPLE Port & Pin definitions to match the 8052.com Tutorial
sbit LCD_EN = P3^7;
sbit LCD_RS = P3^6;
sbit LCD_RW = P3^5;
#define LCD_PORT P0
// Funtion prototype
void lcd_data(unsigned char dat);
/*
* this routine displays the supplied 8-bit unsigned number
* in hexadecimal notation.
*
* The hexadecimal display is achieved by sending two ASCII-coded
* characters to the LCD; eg the number 0xA4 is displayed by sending
* a '4' character followed by an 'A' character.
*/
void hex2lcd( unsigned char number )
{
unsigned char MSD; // used to extract the Most-Significant (MS) Hex Digit of the number
unsigned char LSD; // used to extract the Least-Significant (LS) Hex Digit of the number
MSD = (number&0xf0) >>4; // extract the MS Hex Digit; ie the top 4 bits
LSD = (number&0x0f); // extract the LS Hex Digit; ie the bottom 4 bits
// First, obtain the character to represent the MS Hex digit
// Note that the conversion differs slightly depending on whether the value is 0x0-0x9 or 0xA-0xF
if( MSD < 0xA )
{
// The MS Digit is less than 0xA; ie it is in the range 0x0-0x9
// Convert it to the corresponding ASCII character code '0' to '9'.
// This conversion is easy, as we just have to add the value of the digit, 0x0-0x9,
// to the value of the ASCII code for a '0' character
MSD += '0';
}
else
{
// The MS Digit is not less than 0xA; ie it is in the range 0xA-0xF
// Convert it to the corresponding ASCII character code 'A' to 'F'
// This conversion is slightly more complicated, as the values we are converting
// are in the range 0xA-0xF; so we cannot simply add the value to be converted
// to the ASCII code for an 'A' character - hence the subtraction of 0xA
// (note that a decent compiler will do the subtraction at compile-time, and
// will not generate code to work it out every time this line is executed!)
MSD += ('A' - 0xA);
}
// Now obtain the character to represent the LS Hex digit
// The process is exactly the same as for the MS digit
// Note that, since we have the MS and LS Digits in separate variables, it doesn't
// matter in which order we convert the digits.
if( LSD < 0xA )
{
LSD += '0';
}
else
{
LSD += ('A' - 0xA);
}
// Now send the two characters forming the hex representation to the display
// Note that it is now important that we send them in the correct order!
lcd_data( MSD );
lcd_data( LSD );
}
/*
* this routine displays the supplied 8-bit unsigned number
* in decimal notation, with leading zeros; ie "000" to "255"
*
* The decimal display is achieved by sending three ASCII-coded
* characters to the LCD; eg the number 0x78 (123 decimal) is displayed by
* sending a '1' character followed by a '2' character followed by a '3' character.
*/
void dec2lcd(unsigned char number)
{
unsigned char h=0; // used to extract the "hundreds" Digit of the number in decimal notation
unsigned char t=0; // used to extract the "tens" Digit of the number in decimal notation
// First, determine the number of "hundreds" in the number.
// We do this by repeatedly subtracting 100 until the number falls below 100,
// and counting how many times we subtracted 100
while( number >= 100 )
{
number -= 100;
h++; // Count another "hundred"
}
// The number now has no "hundreds" - either it had none to start with, or
// they have all just been subtracted.
// Next, determine the number of "tens" in the number.
// Again, we do this by repeatedly subtracting 10 until the number falls below 10,
// and counting how many times we subtracted 10
while(number>=10)
{
number -= 10;
t++;
}
// The number now has no "hundreds" and no "tens" - either it had none to start with, or
// they have all just been subtracted.
// All that is now left is the units!
// Now send the 3 digits - "hundreds", "tens", and "units" - to the display as ASCII-Coded
// Characters.
// Because each digit must be in the range 0-9, the corresponding ASCII code is found by
// adding the digit value to the value of the ASCII code for a '0' character
lcd_data( h + '0' ); // hundreds
lcd_data( t + '0' ); // tens
lcd_data( number + '0' ); // units (remember: number was left containing just units)
}
/*
* This Routine sends the supplied byte to the LCD
*
* Note that you must supply appropriate definitions for the port pins
* used by the LCD, and these must be bit-addressable
*
* Note also that the LCD must be properly initialised, and the control lines
* in their proper states, before calling this function.
*
* Note also that a software delay loop is used to set the length of the
* Enable pulse - YOU WILL ALMOST CERTAINLY NEED TO MODIFY THIS TO MATCH
* YOUR PARTICULAR CLOCK FREQUENCY, CHIP INSTRUCTION TIMINGS, COMPILER
* SETTINGS, etc. (in fact, it would be better to write a separate assembler
* delay routine).
*
*/
void lcd_data( unsigned char dat)
{
unsigned char a; // Loop counter for the delay loop - YOU MAY NEED TO MODIFY THIS!
LCD_RS=1; // Set the Register Select line high indicating data for display
LCD_RW=0; // Set the Read/Write line low indicating a Write to the display
LCD_PORT=( dat ); // Write the supplied byte to the LCD port
// Now pulse the Enable line so that the LCD will see the data
LCD_EN=1; // Set the EN line high
for( a=0; a<0xf; a++ ); // Pause a while - YOU WILL NEED TO MODIFY THIS!
LCD_EN=0; // Set the EN line low
} |



