# Reloj con PIC18F4550 y LCD grafica



## lmg_03 (Ene 19, 2010)

Hola gente del foro! como mencioné en el titulo de este tema, estoy haciendo un proyecto en el cual se tiene que mostrar la hora en un LCD grafico, para esto queria utilizar el TIMER1 del PIC para ahorrar espacio y no colocar un RTC, ya que ademas tengo que tomar muestras del ADC del pic cada 1 mseg. aproximadamente, por lo que queria aprovechar esta posibilidad.
La cuestión es que, la interrupcion por desbordamiento del TIMER1 funciona correctamente hasta cuando le incluyo las rutinas de escritura de la LCD grafica. Para la programacion estoy utilizando PICC CCS y cuando compilo el programa me establese como que las interrupciones son desabilitadas durante algunas de las funciones de la LCD.
Leyendo el timer este se incrementa secuencialmente, pero no genera la interrupcion por desbordamiento.
Como prodria solucionar este problema? porque intente hacerlo con la interrupcion externa RB0 y pasa lo mismo.

Desde ya muchas gracias por cualquier sugerencia


----------



## jjfonsecaz (Ene 21, 2010)

hola compañero.

Pues por lo que comentas, es normal que durante la ejecucion de las rutinas del LCD, especialmente las de inicializacion y las de escritura; se tengan que deshabilitar las interrupciones, de otra forma incurriria en errores y no controlarias adecuadamente la pantalla.

Yo revisaria en las rutinas del LCD que se habilitaran las interrupciones una vez que se han terminado de ejecutar. Puede ser el caso que no las esten habilitando y por ello no te funciona la interrupcion.

Un saludo


----------



## cabrera (May 12, 2010)

hola Img_03.

Tengo una pequeña dudilla enla q talvez me puedas ayudar...

Veo q haz trabajando con el Pic18f4550 en conjunto con la LCD. El asunto esq yo justamente acabo de terminar un proyecto en el que comunico un sensor de temperatura ds18b20 y una rtc ds1307 con un pic16f877a y desplego en una LCD un menu interactivo con el usuario en el cual este puede elegir entre visualizar la temperatura la fecha o la hora.

Mi duda viene a continuacion: yo quiero usar el pic18f4550 en vez del 16f877a para este mismo proyecto porq quiero agregarle comunicacion usb con la PC, pero la verdad he trabajado muy poco o casi nada con este pic18.

habra algun problema al cambiar de pic en mi programa? talvez algun problema con la LCD?

Yo estoy programando en ccs y uso la libreria LCD.c q viene incluida en dicho ccs, pero me han comentado q exixten ciertos inconvenientes al usar esta libreria con el pic18f4550.

Espero q puedas ayudarme aunq sea 1poco, o q alguien mas q lo lea y sepa del asunto me ayude .

Gracias por adelantado.

Dejare mi codigo y circuito por si los requieres para ayudarme con esta duda o por si a alguien le interesa mi proyecto .

A parte de la libreria LCD.c que viene incluida en el ccs use tambian estas 2 librerias que descargue de internet para el uso del sensor ds18b20.

1RA LIBRERIA
onewire.c :

```
/*-------1-wire definitions-------*/ 
#define ONE_WIRE_PIN PIN_A0 

/*******************1-wire communication functions********************/ 

/************onewire_reset*************************************************/ 
/*This function initiates the 1wire bus */ 
/* */ 
/*PARAMETERS: */ 
/*RETURNS: */ 
/*********************************************************************/ 

void onewire_reset()  // OK if just using a single permanently connected device 
{ 
 output_low(ONE_WIRE_PIN); 
 delay_us( 500 ); // pull 1-wire low for reset pulse 
 output_float(ONE_WIRE_PIN); // float 1-wire high 
 delay_us( 500 ); // wait-out remaining initialisation window. 
 output_float(ONE_WIRE_PIN); 
} 

/*********************** onewire_write() ********************************/ 
/*This function writes a byte to the sensor.*/ 
/* */ 
/*Parameters: byte - the byte to be written to the 1-wire */ 
/*Returns: */ 
/*********************************************************************/ 

void onewire_write(int data) 
{ 
 int count; 

 for (count=0; count<8; ++count) 
 { 
  output_low(ONE_WIRE_PIN); 
  delay_us( 2 ); // pull 1-wire low to initiate write time-slot. 
  output_bit(ONE_WIRE_PIN, shift_right(&data,1,0)); // set output bit on 1-wire 
  delay_us( 60 ); // wait until end of write slot. 
  output_float(ONE_WIRE_PIN); // set 1-wire high again, 
  delay_us( 2 ); // for more than 1us minimum. 
 } 
} 

/*********************** read1wire() *********************************/ 
/*This function reads the 8 -bit data via the 1-wire sensor. */ 
/* */ 
/*Parameters: */ 
/*Returns: 8-bit (1-byte) data from sensor */ 
/*********************************************************************/ 

int onewire_read() 
{ 
 int count, data; 

 for (count=0; count<8; ++count) 
 { 
  output_low(ONE_WIRE_PIN); 
  delay_us( 2 ); // pull 1-wire low to initiate read time-slot. 
  output_float(ONE_WIRE_PIN); // now let 1-wire float high, 
  delay_us( 8 ); // let device state stabilise, 
  shift_right(&data,1,input(ONE_WIRE_PIN)); // and load result. 
  delay_us( 120 ); // wait until end of read slot. 
 } 

 return( data ); 
}
```

2DA LIBRERIA.

```
float ds1820_read() 
{ 
 int8 busy=0, temp1, temp2; 
 signed int16 temp3; 
 float result; 

 onewire_reset(); 
 onewire_write(0xCC); 
 onewire_write(0x44); 

 while (busy == 0) 
  busy = onewire_read(); 

 onewire_reset(); 
 onewire_write(0xCC); 
 onewire_write(0xBE); 
 temp1 = onewire_read(); 
 temp2 = onewire_read(); 
 temp3 = make16(temp2, temp1); 
  
 //result = (float) temp3 / 2.0;   //Calculation for DS18S20 with 0.5 deg C resolution 
 result = (float) temp3 / 16.0;  //Calculation for DS18B20 with 0.1 deg C resolution 
  
 delay_ms(200); 
 return(result); 
}
```

Y por ultimo mi programa en ccs:


```
#include <16f877a.h>
#device *=16 
#device adc=8  
#fuses xt,nowdt,noput,nobrownout,nolvp,noprotect
#FUSES NOWDT, HS, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT 
#use delay(clock=20M) 

//#include "lcd.c"
#include<onewire.c> 
#include<lcdmio.c> 
#include<ds18b20.c>  
#use standard_io (D) 


#use fast_io (c)
#use fast_io (b)  

#use i2c(MASTER, SDA=PIN_c4, SCL=PIN_c3,slow) 

//Registros DS1307 
#define ds_seconds 0x00 
#define ds_minutes 0x01 
#define ds_hours 0x02 
#define ds_day 0x03 
#define ds_date 0x04 
#define ds_month 0x05 
#define ds_year 0x06 
#define ds_control 0x07 

#define RB0 PIN_B0
#define RA4 PIN_A4

//DS1307 
//Vbat a tierra 

//// Declarando variables////////

int16 retardo; //Cada cuando actualiza lectura en LCD 

//Dato en registro ds, a mandar o leer 
int seconds,minutes,hours,day,date,month,year,control;

void sethora()
{
//Establece fecha y hora 
i2c_start(); //Inicia I2C 
i2c_write(0xd0); //Direcciona DS1307 write 
i2c_write(ds_seconds); //Indica que empiece en registro ds_seconds 
//Aquí establece fecha y hora respecto a la puesta arriba 
i2c_write(seconds); 
i2c_write(minutes); 
i2c_write(hours); 
//i2c_write(day); 
//i2c_write(date); 
//i2c_write(month); 
//i2c_write(year); 
i2c_write(control); 
i2c_stop(); //Ya puso la hora y fecha 
//El RTC ya está marcando el tiempo y fecha 
}

void setfecha()
{
//Establece fecha y hora 
i2c_start(); //Inicia I2C 
i2c_write(0xd0); //Direcciona DS1307 write 
i2c_write(ds_date); //Indica que empiece en registro ds_seconds 
//Aquí establece fecha y hora respecto a la puesta arriba 
//i2c_write(seconds); 
//i2c_write(minutes); 
//i2c_write(hours); 
//i2c_write(day); 
i2c_write(date); 
i2c_write(month); 
i2c_write(year); 
i2c_write(control); 
i2c_stop(); //Ya puso la hora y fecha 
//El RTC ya está marcando el tiempo y fecha 
}

void cheqhr()
{									
	if(hours==0x0a)hours=0x10;
	if(hours==0x1a)hours=0x20;
	if(hours==0x24)hours=0x00;
}
void cheqmin()
{									
	if(minutes==0x0a)minutes=0x10;
	if(minutes==0x1a)minutes=0x20;
	if(minutes==0x2a)minutes=0x30;
	if(minutes==0x3a)minutes=0x40;
	if(minutes==0x4a)minutes=0x50;
	if(minutes==0x5a)minutes=0x00;
}
void cheqday()
{									
	if(date==0x0a)date=0x10;
	if(date==0x1a)date=0x20;
	if(date==0x2a)date=0x30;
	if(date==0x32)date=0x01;
}
void cheqmon()
{									
	if(month==0x0a)month=0x10;
	if(month==0x13)month=0x01;
}
void cheqyear()
{									
	if(year==0x1a)year=0x20;
	if(year==0x21)year=0x10;
}



void main(void) 
{ 

float temperature; 

setup_adc_ports(NO_ANALOGS); 
setup_adc(ADC_OFF); 
setup_psp(PSP_DISABLED); 
setup_spi(FALSE); 
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); 
setup_timer_1(T1_DISABLED); 
setup_timer_2(T2_DISABLED,0,1); 
setup_comparator(NC_NC_NC_NC); 
setup_vref(VREF_LOW|-2); 

set_tris_A(0b00010001);
set_tris_B(0b00000001);

////Inicializando valores/////

retardo=50; //ms a tardar entre lectura y lectura
//var1=0; 

/*
//Justo cuando prende circuito, la fecha que establece es la siguiente 
seconds= 0x00; 
minutes= 0x00; 
hours = 0x12; //modo 24 hrs 
day = 0x01; //1 es domingo 
date = 0x01; 
month = 0x01; 
year = 0x10; 
control= 0x00; //OUT=0 SQWE=0 RS0-1=0 no hay onda cuadrada 
*/

//Rutina LCD 
lcd_init(); //Inicia LCD


lcd_putc("\f"); //Limpia LCD 
lcd_putc("FACULTAD DE\n"); //rtc 
lcd_putc("INGENIERIA"); 
delay_ms(1000);
lcd_putc("\f"); //Limpia LCD 
lcd_putc("INGENIERIA\n"); //rtc 
lcd_putc("MECATRONICA"); 
delay_ms(1000);
lcd_putc("\f"); //Limpia LCD 
lcd_putc("INSTRUMENTACION\n"); //rtc 
lcd_putc("Y CONTROL"); 
delay_ms(1000);
lcd_putc("\f"); //Limpia LCD 
lcd_putc("PROYECTO\n"); //rtc 
lcd_putc("FINAL"); 
delay_ms(1000);
lcd_putc("\f"); //Limpia LCD 
lcd_putc("LUIS ENRIQUE\n"); //rtc 
lcd_putc("CABRERA"); 
delay_ms(1500);
lcd_putc("\f"); //Limpia LCD 
lcd_putc("JUAN JOSE\n"); //rtc 
lcd_putc("BAZ"); 
delay_ms(1500);
lcd_putc("\f"); //Limpia LCD 
lcd_putc("JUAN ELIAS\n"); //rtc 
lcd_putc("CUEVAS"); 
delay_ms(1500);


/////////////saludo
lcd_putc("\f"); //Limpia LCD 
lcd_putc("Bienvenido\n"); 
lcd_putc("pres-->RA4");
saludo: 
if (input(RA4)==0)
{
saludoI:
if (input(RA4)==1)goto textmenu1;
goto saludoI;
}
goto saludo;

textmenu1:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("1. Reloj\n");
lcd_putc("RBO->in RA4->sig");
menu1:
if (input(RB0)==0)
{
menu1I:
if (input(RB0)==1)goto texthora;
goto menu1I;
}
if (input(RA4)==0)
{
menu1I2:
if (input(RA4)==1)goto textmenu2;
goto menu1I2;
}
goto menu1;
 
textmenu2:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("2. Fecha\n");
lcd_putc("RBO->in RA4->sig");
menu2:
if (input(RB0)==0)
{
menu2I:
if (input(RB0)==1)goto textfecha;
goto menu2I;
}
if (input(RA4)==0)
{
menu2I2:
if (input(RA4)==1)goto textmenu3;
goto menu2I2;
}
goto menu2;

textmenu3:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("3. Temperatura\n");
lcd_putc("RBO->in RA4->sig");
menu3:
if (input(RB0)==0)
{
menu3I:
if (input(RB0)==1)goto texttemp;
goto menu3I;
}
if (input(RA4)==0)
{
menu3I2:
if (input(RA4)==1)goto textmenu1;
goto menu3I2;
}
goto menu3;


texthora:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("\n");
lcd_putc("RBO>out RA4>conf");
hora:
if (input(RB0)==0)
{
horaI:
if (input(RB0)==1)goto textmenu1;
goto horaI;
}
if (input(RA4)==0)
{
horaI2:
if (input(RA4)==1)goto textconfhr;
goto horaI2;
}
delay_ms(retardo); //Usuario lee 
//Obtiene datos de DS1307 
i2c_start(); //Inicia I2C 
i2c_write(0xd0); //Direcciona DS1307 write 
i2c_write(ds_seconds); //Indica que ponga registro en ds_seconds 
i2c_stop(); 
i2c_start(); 
i2c_write(0xd1); //Lee DS1307 
seconds = i2c_read(); 
minutes = i2c_read(); 
hours = i2c_read(); 
day = i2c_read(); 
date = i2c_read(); 
month = i2c_read(); 
year = i2c_read(0); //no ack 
i2c_stop(); 
//Representa datos en la LCD 
//printf(lcd_putc,"\f%2x-%2x-20%2x\n",date,month,year); //dd-mm-year
lcd_gotoxy(1,1); 
printf(lcd_putc,"%2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
goto hora;
 
textfecha:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("\n");
lcd_putc("RBO>out RA4>conf");
fecha:
if (input(RB0)==0)
{
fechaI:
if (input(RB0)==1)goto textmenu2;
goto fechaI;
}
if (input(RA4)==0)
{
fechaI2:
if (input(RA4)==1)goto textconfday;
goto fechaI2;
}
delay_ms(retardo); //Usuario lee 
//Obtiene datos de DS1307 
i2c_start(); //Inicia I2C 
i2c_write(0xd0); //Direcciona DS1307 write 
i2c_write(ds_seconds); //Indica que ponga registro en ds_seconds 
i2c_stop(); 
i2c_start(); 
i2c_write(0xd1); //Lee DS1307 
seconds = i2c_read(); 
minutes = i2c_read(); 
hours = i2c_read(); 
day = i2c_read(); 
date = i2c_read(); 
month = i2c_read(); 
year = i2c_read(0); //no ack 
i2c_stop(); 
//Representa datos en la LCD 
lcd_gotoxy(1,1);
printf(lcd_putc,"%2x-%2x-20%2x",date,month,year); //dd-mm-year 
//printf(lcd_putc,"%2x:%2x:%2x",hours,minutes,seconds); //23:59:59 
goto fecha;

texttemp:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("\n");
lcd_putc("RBO>out");
temp:
if (input(RB0)==0)
{
tempI:
if (input(RB0)==1)goto textmenu3;
goto tempI;
}
  temperature = ds1820_read(); 
  lcd_gotoxy(1,1); 
  printf(lcd_putc,"TEMP: %3.1f ", temperature); 
  lcd_putc(223); 
  lcd_putc("C    "); 
/*  lcd_gotoxy(1,2); 
  if(temperature >= 29.0) 
   printf(lcd_putc,"Hot!    "); 
  else if( temperature >= 20 && temperature < 29.0) 
   printf(lcd_putc,"Comfort!"); 
  else 
   printf(lcd_putc,"Cold!   "); */
goto temp;

/////////////////////////////////////////////////////////////////////////////7

textconfhr:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("\n");
lcd_putc("RBO>hrs+ RA4>sig");
confhr:
cheqhr();
lcd_gotoxy(1,1);
printf(lcd_putc,"%2x-%2x-%2x",hours,minutes,seconds);
if (input(RB0)==0)
{
confhrI:
if (input(RB0)==1)
{
hours++;
goto confhr;
}
goto confhrI;
}
if (input(RA4)==0)
{
confhrI2:
if (input(RA4)==1)goto textconfmin;
goto confhrI2;
}
goto confhr;

textconfmin:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("\n");
lcd_putc("RBO>min+ RA4>out");
confmin:
cheqmin();
lcd_gotoxy(1,1);
printf(lcd_putc,"%2x-%2x-%2x",hours,minutes,seconds);
if (input(RB0)==0)
{
confminI:
if (input(RB0)==1)
{
minutes++;
goto confmin;
}
goto confminI;
}
if (input(RA4)==0)
{
confminI2:
if (input(RA4)==1)
{
sethora();
goto texthora;
}
goto confminI2;
}
goto confmin;

textconfday:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("\n");
lcd_putc("RBO>day+ RA4>sig");
confday:
cheqday();
lcd_gotoxy(1,1);
printf(lcd_putc,"%2x-%2x-20%2x",date,month,year);
if (input(RB0)==0)
{
confdayI:
if (input(RB0)==1)
{
date++;
goto confday;
}
goto confdayI;
}
if (input(RA4)==0)
{
confdayI2:
if (input(RA4)==1)goto textconfmon;
goto confdayI2;
}
goto confday;

textconfmon:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("\n");
lcd_putc("RBO>mon+ RA4>sig");
confmon:
cheqmon();
lcd_gotoxy(1,1);
printf(lcd_putc,"%2x-%2x-20%2x",date,month,year);
if (input(RB0)==0)
{
confmonI:
if (input(RB0)==1)
{
month++;
goto confmon;
}
goto confmonI;
}
if (input(RA4)==0)
{
confmonI2:
if (input(RA4)==1)goto textconfyear;
goto confmonI2;
}
goto confmon;

textconfyear:
lcd_putc("\f"); //Limpia LCD 
lcd_putc("\n");
lcd_putc("RBO>año+ RA4>out");
confyear:
cheqyear();
lcd_gotoxy(1,1);
printf(lcd_putc,"%2x-%2x-20%2x",date,month,year);
if (input(RB0)==0)
{
confyearI:
if (input(RB0)==1)
{
year++;
goto confyear;
}
goto confyearI;
}
if (input(RA4)==0)
{
confyearI2:
if (input(RA4)==1)
{
setfecha();
goto textfecha;
}
goto confyearI2;
}
goto confyear;


}
```
-----------------------------------------------------
Perdon no puse que que mi segunda libreria se llama ds18b20.c

y por ultimo mi circuito es este:







Ups, nose como insertar una imagen enel foro.

si alguien me explica por ahi como la insertare. Sorry


----------



## EINNER C (Jun 13, 2010)

hola..

en cuanto a migrar de un pic 16 a un 18, creo q no hay ningun inconveniente, yo tambn trabajaba anteriormente con los 16, pero hace un tiempo cambie por el mismo motivo, la comunicacion por usb, y la verdad que no me han surgido problemas con la lcd,...

si tienes alguna duda, o si te presenta problemas al migrar al pic 18, aqui estaremos paa qyudar

exitos


----------



## rugebiker (Jun 14, 2010)

que tal 
mira coincidentemente yo quiero hacer justo lo mismo que tu 
un reloj con el PIC18F4550 y que me muestre la hora en una pantalla LCD. Me gustaria poder ver tu circuito si me lo permitieras y tambien la programacion porque vilmente estoy bien noob en esto 
muchas gracias 
mi mail es:







Ruben


----------



## framm703 (Feb 11, 2011)

No existe alguna manera de generar un calendario dentro de un pic de 4mhz?... utilizando timers?


----------



## EINNER C (Feb 17, 2011)

pues la verdad si se propone con un pic puede hacerce miles de cosas, es cosa de imaginacion y bastante codigo, yo creo que si es posible, pero te recomendaria utilizar integrados destinados a tal fin, como por ejemplo el ds1302, que es un reloj en tiempo real, y te da la hora, minutos segundos y ademas la fecha en dias meses y a~os y puedes configurarlo como quieras, solo es necesario que trabajes comunicacion i2c y listo, culquier duda con gusto


----------



## framm703 (Feb 17, 2011)

Muchas gracias por responder  , El problema que tengo es que tengo que realizar un datalogger con un aceleremetro que detecta caidas conciderables de la produccion de frutas finas como proyecto final de tecnico en electronica,y necesito saber la fecha y la hora del impacto, ya tengo dentro de la fruta, un pic de 16 pines con AD y timer 0 y 1, un Acelerometro y una eeprom externa de 8 pines, ademas del cristal, estaba pensando en utilizar el Timer1 para generar un pulso de 500MS para un reloj de precision para generar una base de tiempos horaria, no de fechas, utilizando un cristal de baja frecuencia LP de 32.768 en el timer, pero mi duda es si consigo la precision necesaria para un reloj, por fabor alguien me podria decir si es conveniente para generar una base de tiempor precisa? , muchas graciasñ


----------



## Haks (May 14, 2011)

Hola me pudieran ayudar uso el codigo y la libreria del reloj pero en el lcd me aparecen -0.6 grados

Ya se por que, copie la libreria del termomtro ds1820 y yo nesecito la ds18b20 alguien la tendra


----------

