简体   繁体   中英

LCD 4 bit communication with PIC16

I use a PIC16F690 for communication with my LCD. I got the following code from an example. The problem is that I want to use the 4 lower bits for my own outputs, but it always gets overwritten. The problem is, that I always overwrite the complete port. How can I only write the 4 upper bits without touching the first 4.

#define LCD_DATA PORTC

void lcd_write (unsigned char c)
{
    __delay_ms(1);
    LCD_DATA = ((c >>4) & 0x0F);
    LCD_STROBE();

    LCD_DATA = (c & 0x0F);
    LCD_STROBE();
}

void lcd_init()
{
    char init_value;

    ANSEL= 0; //Disable analog pins on PORTA

    init_value= 0x3;
    LCD_RS= 0;
    LCD_EN= 0;
__delay_ms(100);
    __delay_ms(15); //wait 15ms after power is applied
    LCD_DATA = init_value;
    LCD_STROBE();
    __delay_ms(10);
    LCD_STROBE();
    __delay_ms(10);
    LCD_DATA =2; //4-bit mode
    LCD_STROBE();

    lcd_write(0x28); //Set interface length
    lcd_write(0x0C); //Display On, Cursor On, Cursor Blink
    lcd_clear(); //Clear Screen
    lcd_write(0x6); //Set entry mode
}

Hope you guys can help me:)

Edit: Thank you for your hints. Found following solution and works perfectly or do i miss something?

void lcd_write (unsigned char c)
{
    __delay_ms(1);
    if(((c >>4) & 1))
    {
       RC0 = 1; 
    }else
    {
       RC0 = 0;
    }
    
    if(((c >>4) & 2))
    {
       RC1 = 1; 
    }else
    {
       RC1 = 0;
    }
    
    if(((c  >>4) & 4))
    {
       RC2 = 1; 
    }else
    {
       RC2 = 0;
    }
    
    if(((c >>4) & 8))
    {
       RC3 = 1; 
    }else
    {
       RC3 = 0;
    }
    
    
    //LCD_DATA = ((c >>4) & 0x0F);
    LCD_STROBE();

    //LCD_DATA = (c & 0x0F);
    
    if(c & 1)
    {
       RC0 = 1; 
    }else
    {
       RC0 = 0;
    }
    
    if(c & 2)
    {
       RC1 = 1; 
    }else
    {
       RC1 = 0;
    }
    
    if(c & 4)
    {
       RC2 = 1; 
    }else
    {
       RC2 = 0;
    }
    
    if(c & 8)
    {
       RC3 = 1; 
    }else
    {
       RC3 = 0;
    }
    
    LCD_STROBE();
}

Unfortunately, your PIC model lacks LAT registers, which could allow you to write a cleaner and simplified code. If you had them, you could apply read-modify-write method. PIC18 and the latest PIC16 models have LAT registers.

If the uC has LAT registers, you can write it like this:

#define LCD_DATA LATC // Instead of PORTC

void lcd_write (unsigned char c)
{
    __delay_ms(1);
    unsigned char oldValue = LCD_DATA & 0xF0;
    LCD_DATA = (oldValue | ((c >> 4) & 0x0F));
    LCD_STROBE();

    LCD_DATA = (oldValue | (c & 0x0F));
    LCD_STROBE();
}

This may still work with PORTC, but it's risky to use it and it may be unreliable. Because reading from PORT register reads the current status of the port, not the output latch. But I suggest you to try it yourself and see the result. If there is sufficient time between the latch write accesses, the hardware pin output may have enough time to stabilize and it may work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM