Jump to content

johnc

Members
  • Content Count

    1
  • Joined

  • Last visited

    Never

Community Reputation

0 Neutral

About johnc

  • Rank
    Newbrie
  1. Can't get the cursor to position to locations 3,19 or 35 on the LCD for some reason. Code works ok on a real LCD Here's a test program to show the issue ... move the DD RAM address back one location at from position 39 one location at a time and write an "X" in the location. The character that is written to 3 is written to 5, to 19 is written to 21, to 35 is written to 37. All other locations are just fine. //////////////////////////////////////////////////////////////////////////// // LCD with HD44780 drive chip //////////////////////////////////////////////////////////////////////////// // Author(s): David Hobday // Date 4 September 2003 // // Designed and test for 16F84A // // Interface : // RS = RA01 // WR = RA02 // E = RA00 // // DB7 = RB07 // DB6 = RB06 // DB5 = RB05 // DB4 = RB04 // // Using 4 Bit interface // ///////////////////////////////////////////////////////////////////////////// // Program to test LCD plugin - with 4 bit interface // Designed and test for 16F84A // // **** Beware MPLABS assembler fails to report when program exceeds memory // upto 4 words - this can then cause the program to fail! // This program nearly totally fills the processor! // 20MHz - frequency needs setting high for busy test, // It write characters faster than they can be handled by the display and // so get missed. If clock frequency set lower this may not happen // Remeber also that the simualtor must also be told the clock rate so the plugins // can convert clock ticks to actual time. #pragma CLOCK_FREQ 20000000 // comment out when running on actual hardware - different delays used //#define RUN_UNDER_SIM #include <system.h> void LCD_Setup(void); void LCD_FunctionMode(void); void LCD_DataMode(void); void LCD_RawWriteNibble(char); void LCD_Write(char); void LCD_RawWrite(char); char LCD_Read(); void lprintf( const char *lcdptr ); //write string void LCD_Clear(); void LCD_WaitForNotBusy(); char writeDelayType; //////////////////////////////////////////////////////////////////////////// // Control signal bit definitions //////////////////////////////////////////////////////////////////////////// #define LCD_E 0 #define LCD_RW 2 #define LCD_RS 1 //////////////////////////////////////////////////////////////////////////// // LCD Commands ( Refer to LCD Data Sheet ) //////////////////////////////////////////////////////////////////////////// #define clear_lcd 0x01 // Clear Display #define return_home 0x02 // Cursor to Home position #define entry_mode 0x06 // Normal entry mode #define entry_mode_rev 0x04 // Normal entry mode -reverse direction #define entry_mode_scroll 0x07 // - with shift #define entry_mode_scroll_rev 0x05 // reverse direction #define system_set_8_bit 0x38 //8 bit data mode 2 line ( 5x7 font ) #define system_set_4_bit 0x28 // 4 bit data mode 2 line ( 5x7 font ) #define system_set_reset 0x30 // Reset code #define display_on 0x0C // Display ON - 2 line mode #define display_off 0x08 // Display off #define set_dd_line1 0x80 // Line 1 position 1 #define set_dd_line2 0xC0 // Line 2 position 1 #define set_dd_ram 0x80 // Line 1 position 1 #define write_data 0x00 // With RS = 1 #define cursor_on 0x0E // Switch Cursor ON #define cursor_off 0x0C // Switch Cursor OFF #define cursor_blink_on 0x0F // Cursor plus blink #define cursor_shift_right 0x14 // Move cursor right #define cursor_shift_left 0x10 // Move cursor left #define display_shift_right 0x1C // Scroll display right #define display_shift_left 0x18 // Scroll display left #define WriteNoDelay 1 #define WriteDelayTime 0 #define WriteUseBusy 2 void TestDelay() { #ifdef RUN_UNDER_SIM delay_ms( 2 ); #else delay_ms( 2 ); #endif } void TestDelayShort() { #ifdef RUN_UNDER_SIM delay_ms( 1 ); #else delay_ms( 100 ); #endif } void main() { #ifdef RUN_UNDER_SIM #else delay_s( 1 ); // power up delay #endif trisa = 0x00; // port a output while( 1 ) { LCD_Setup(); char i = 0; ////////////////////////////////////////////////// // Cursor Positioning ////////////////////////////////////////////////// LCD_FunctionMode(); LCD_Clear(); LCD_FunctionMode(); LCD_Write( set_dd_ram + 0x06 ); // start text top line, col 7 LCD_DataMode(); lprintf( "TEST" ); // make sure everything is working ok for( i = 39; i !=0; i-- ) { LCD_FunctionMode(); LCD_Write( set_dd_ram | i ); // start the cusror at the end LCD_DataMode(); // of the line and work our way LCD_Write('X'); // back to 0 TestDelay(); } } } void LCD_Clear() { LCD_FunctionMode(); LCD_Write( clear_lcd ); // clear display LCD_Write( return_home ); delay_ms( 2 ); LCD_DataMode(); } void LCD_Setup(void) { writeDelayType = WriteNoDelay; // no delays in data writes delay_ms(16); // Power up delay LCD_FunctionMode(); // Reset sequence as described in data sheets LCD_RawWriteNibble( system_set_reset >> 4 ); delay_ms(5); // min delay here of 4.1 ms LCD_RawWriteNibble( system_set_reset >> 4 ); delay_us(100); // min delay here of 100us LCD_RawWriteNibble( system_set_reset >> 4 ); // busy flag is valid from this point onwards LCD_WaitForNotBusy(); LCD_RawWriteNibble( system_set_4_bit >> 4 ); writeDelayType = WriteUseBusy; // use busy LCD_Write( system_set_4_bit ); LCD_Write( display_off ); LCD_Write( entry_mode ); LCD_Write( display_on ); LCD_Write( set_dd_ram ); LCD_DataMode(); } void LCD_FunctionMode(void) { output_low_port_a( LCD_RS ); } void LCD_DataMode(void) { output_high_port_a( LCD_RS ); } void LCD_Write(char d ) { if ( writeDelayType == WriteUseBusy ) LCD_WaitForNotBusy(); LCD_RawWrite( d ); if ( writeDelayType == WriteDelayTime ) delay_us( 50 ); // enough time for normal command execution - clear and home need longer!! } void LCD_RawWrite( char d ) { output_low_port_a( LCD_RW ); // set writing mode // set port b lower bits to output trisb &= 0x0F; // output upper nibble LCD_RawWriteNibble( d >> 4 ); // output lower nibble LCD_RawWriteNibble( d ); } void LCD_RawWriteNibble(char d ) { output_low_port_a( LCD_RW ); // set writing mode // port b upper nibble output trisb &= 0x0F; portb &= 0x0F; portb |= d << 4; // Clock data asm NOP // setup time asm NOP // setup time asm NOP // setup time output_high_port_a( LCD_E ); output_low_port_a( LCD_E ); asm NOP ;// holdup time } char LCD_Read() { char d; // portb upper nibble input trisb |= 0xF0; output_high_port_a( LCD_RW ); // set reading mode // data valid while EN high - // first high nibble output_high_port_a( LCD_E ); asm NOP // setup time asm NOP // setup time asm NOP // setup time d = portb & 0xF0 ; output_low_port_a( LCD_E ); // then low nibble output_high_port_a( LCD_E ); asm NOP // setup time asm NOP // setup time asm NOP // setup time d |= portb >> 4; output_low_port_a( LCD_E ); return d; } void LCD_WaitForNotBusy() { char old_RS; // save RS current state old_RS = porta & ( 1 << LCD_RS ); output_low_port_a( LCD_RS ); while( LCD_Read() & 0x80 ); // wait while busy set if ( old_RS ) // restore RS if necessary output_high_port_a( LCD_RS ); } void lprintf( const char *lcdptr ) { char pi; char c; pi = 0; while( 1 ) { c = lcdptr[pi++]; if ( c + 1 == 1 ) // funny code here as c == 0 fails with compiler V5.1 break; if ( c == '\n' ) { LCD_FunctionMode(); LCD_Write( set_dd_ram + 0x40 ); LCD_DataMode(); } else LCD_Write( c );// Display on LCD } }
×
×
  • Create New...