c-LCD与PIC16的4位通信



我使用PIC16F690与LCD进行通信。我从一个例子中得到了以下代码。问题是,我想将4个低位用于我自己的输出,但它总是被覆盖。问题是,我总是覆盖整个端口。我怎么能只写4个高位而不写前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
}

希望你们能帮助我:(

编辑:谢谢你的提示。找到了以下解决方案,效果很好,还是我错过了什么?

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();
}

不幸的是,您的PIC模型缺少LAT寄存器,这可以让您编写更干净、简化的代码。如果您有它们,您可以应用读-修改-写方法。PIC18和最新的PIC16型号具有LAT寄存器。

如果uC有LAT寄存器,你可以这样写:

#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();
}

这可能仍然适用于PORTC,但使用它有风险,而且可能不可靠。因为从PORT寄存器读取的是端口的当前状态,而不是输出锁存器。但我建议你自己试试看结果。如果在锁存器写入访问之间有足够的时间,则硬件引脚输出可能具有足够的时间来稳定并且可以工作。

最新更新