Aqui el programa que mencione anteriormente
#include <./lcd.h>
#include <./timers.h>
#include <avr/io.h>
extern unsigned int bf;//busy flag
/****************************************************
Rutina de encendido/apagado de la linea de control E
****************************************************/
void toggle(void){
sbi(PORTB,PB7);
//delay(2);no requerido
cbi(PORTB,PB7);
}
/****************************************************
Rutina de inicializacion del LCD
****************************************************/
void LCDini(void){
delay(30);
PORTD=0x30;
toggle();
delay(10);
PORTD=0x30;
toggle();
delay(10);
PORTD=0x20;//bus 4 bits
toggle();//***** 1 ****
delay(10);
PORTD=0x20;//bus 4bits
toggle();//***** 2 ****
//delay(10);
PORTD=0x80;// 2 LINEAS, 5X7 PUNTOS
toggle();
LCDbusy();//delay(10);
PORTD=0x00;//display on, cursor off
toggle();//***** 3 ****
//delay(10);
PORTD=0xC0;//blink off 0x0E
toggle();
LCDbusy();//delay(10);
PORTD=0x00;
toggle();//***** 4 ****
//delay(10);
PORTD=0x10;// display clear
toggle();
LCDbusy();//delay(10);
PORTD=0x00;
toggle();//***** 5 *****
//delay(10);
PORTD=0x60;// display entry
toggle();//funciona co LCDhome()
LCDbusy();//delay(10);//y no con LCDclear()
}
/****************************************************
Escribe un caracter en el display
****************************************************/
void LCDwrite(unsigned char dato){//escribe un caracter al lcd
volatile unsigned char tmp2;
tmp2=dato;
tmp2=tmp2&0xF0;//nibble alto
dato=(dato&0x0F)<<4;//nibble bajo
sbi(PORTB,PB6);
PORTD=tmp2;
toggle();
PORTD=dato;
toggle();
bf=LCDbusy();//delay(

;
cbi(PORTB,PB6);
}
/****************************************************
Escribe una cadena de tamaño size con retardo de
milisegundos entre la escritura de cada caracter
****************************************************/
void LCDputs(unsigned const char *msg, unsigned char size,unsigned int ms){
volatile unsigned char i;
for(i=0;i<size;i++){
LCDwrite(*(msg+i));
delay(ms);
}
}
/****************************************************
Fija la direccion de escritura en el display
****************************************************/
void LCDaddr(unsigned char addr){
volatile unsigned char tmp2;
tmp2=addr;
tmp2=tmp2&0xF0;//nibble alto
addr=(addr&0x0F)<<4;//nibble bajo
PORTD=tmp2|0x80;
toggle();
//delay(

;
PORTD=addr;
toggle();
LCDbusy();//delay(

;
}
/****************************************************
Limpieza del display, y regresa a la posicion cero de
memoria, de manera manual encender el cursor y el
display mediante LCDcontrol();
****************************************************/
void LCDclear(void){
PORTD=0x00;
toggle();
//delay(

;
PORTD=0x10;
toggle();
LCDbusy();//delay(

;
}
/****************************************************
Cursor en posicion home
****************************************************/
void LCDhome(void){
//manda cursor a home, la ram no se afecta,
//endender el display, cursor manualmente
PORTD=0x00;
toggle();
//delay(

;
PORTD=0x20;
toggle();
LCDbusy();//delay(

;
}
/****************************************************
lee busy flag, regresa el valor de la direccion RAM
del display
****************************************************/
unsigned char LCDbusy(void){
unsigned char busy,tmp;
sbi(PORTB,PB0); //enciende R/W
cbi(PORTB,PB6); //apaga RS
DDRD = 0x0F;//cambia las salidas por entradas
do{
cbi(PORTB,PB7);
delay(2);
sbi(PORTB,PB7);
busy = PIND;//lee puerto
delay(2);
cbi(PORTB,PB7);
busy = busy&0xF0;//parte alta
sbi(PORTB,PB7);
delay(2);
tmp = PIND;//lee puerto
cbi(PORTB,PB7);
tmp = (tmp&0xF0)>>4;//parte baja
busy=busy||tmp;//byte completo
tmp=busy&0x80;//enmascara BF
}while((tmp&0x80)==0x80);
bf=busy&0x7F;//limpia bf de direccion
cbi(PORTB,PB0); //apaga R/W
DDRD = 0xF0; //cambia las entradas por salidas
return(busy);