??? 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 } |