Tengun problemilla y no se muy bien como resolverlo. Estoy utilizando un LCD de 20x4, con 4bits, y señales de E/RS/RW, tengo conectado al puertoA la linea de datos, y las lineas de control al puertoC, en el PA tengo tambien conectado un sensor digital (SHT-11), el problema es que hace una medición (correcta), y a continuación las demas son erroneas, este problema me lo da a veces, solo deja de darmelos cuando compilo el programa sin el uso del LCD (para saber que está funcionando como debe lo compruebo via RS232), deduzco que el problema está en la librería, esta es la que estoy usando...
Codigo:
////////////////////////////////////////////////////////////////////////////
//// LCD_MOD.C ////
//// Driver para módulos LCD microcontrolados ////
//// ////
//// Inspirado en librería CCS ////
//// Adaptado por Fernando Nuño García y Miguel Ángel José Prieto para ////
//// funcionamiento con el LCD integrado en la placa PICDEM-2-PLUS. ////
//// Adaptado por Jaime Fernández-Caro para usar LCD de 20x4 ////
//// ////
//// Funciones definidas ////
//// ////
//// lcd_init() Inicialización,llamar antes de cualquier otra función////
//// ////
//// lcd_putc(c) Muestra c en la posicion siguiente del LCD. ////
//// Caracteres de control: ////
//// f Borra display ////
////
Sitúa cursor al comienzo de la línea 2 ////
//// Retrocede el cursor una posición ////
//// Avanza el cursor una posición ////
//// Retrocede una posición la pantalla visible ////
//// v Avanza una posición la pantalla visible ////
//// ////
//// ////
//// lcd_gotoxy(x,y) Sitúa escritura en posición del LCD ////
//// (posición 1,1: arriba a la izquierda) ////
//// ////
//// lcd_getc(x,y) Devuelve carácter en posición x,y del LCD ////
//// ////
////////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,1997 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS C ////
//// compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, reproduction ////
//// or distribution is permitted without written permission. ////
//// Derivative programs created using this software in object code ////
//// form are not restricted in any way. ////
////////////////////////////////////////////////////////////////////////////
// Conexión a 7 pines del MCU: 3 de control / interface de datos de 4 bits:
//
// Líneas de control asignadas
// RC0 enable
// RC1 rw
// RC2 rs
//
// Líneas de Datos
// RA0 D4
// RA1 D5
// RA2 D6
// RA3 D7
//
//
struct lcd_pines_control { // Estructura que se define para facilitar acceso
boolean enable; // y asociarlos a los 3 bits más bajos del PORTC
boolean rw; // asignamos luego a esta estructura el PORTC
boolean rs; // rs (1º corresponde al menos significativo
boolean nada; // a los pines de control del LCD
int otros:4;
} lcd_control;
struct lcd_pines_datos { // Hacemos lo mismo con esta estructura para el PORTA
int datos:4; // los 4 bits más bajos son los de datos
int no_usados:4;
} lcd_datos;
#byte lcd_control = 0xF82 // Ponemos la estructura entera en el PORTC
#byte trisc = 0xF94 // Registro de dirección de datos
#byte lcd_datos = 0xF80 // Lo mismo para los datos, en el PORTA
#byte trisa = 0xF92 // Registro de dirección de datos
//Prototipos de las funciones posteriores
void lcd_init();
byte lcd_read_byte();
void lcd_send_nibble(byte n);
void lcd_send_byte(byte address, byte n);
void lcd_gotoxy(byte x, byte y);
void lcd_putc(char c);
char lcd_getc(byte x, byte y);
void lcd_clr_line(char fila);
///////////////////////////////////////////////////////////////////////////////////////////
/// Función que inicializa el LCD, se deberían cambiar bits para cambiar configuracion
///////////////////////////////////////////////////////////////////////////////////////////
void lcd_init() {
byte i;
trisc&=0b11111000; // Asignamos salidas en RC0, RC1 y RC2, resto puerto como estaba
trisa&=0b11110000; // Lo mismo para RA0 a RA3
lcd_control.rs = 0;
lcd_control.rw = 0;
lcd_control.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
lcd_send_byte(0,0b00101000); ///Se envía Function set 0 0 1 DL N F - -
lcd_send_byte(0,0b00001100); ///Se envía Display on/off 0 0 0 0 1 D C B
lcd_send_byte(0,0b00000001); //Se envía Clear Display
lcd_send_byte(0,0b00000110); //Se envía Entry Mode set 0 0 0 0 0 1 I/D S//
// DL: datos 4 bits(0); 8 bits (1) / N: 2 líneas (1); 1 línea (0) / F: 5x10 (1); 5x8 (0)
// D: display on (1); off (0) / C: cursor on (1); off (0) / B: parpadeo pos.cursor (1); no (0)
// I/D: incremento en R/W (1) o decremento (0) / S: acompaña desplaz.display (1); no (0)
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Lee el byte señalado por el puntero, 1º parte alta, 2º parte baja
// Si al llamar a esta función rs=0, devuelve busy flag (+signif.) y dirección actual
/////////////////////////////////////////////////////////////////////////////////////////////
byte lcd_read_byte()
{
byte low,high;
trisc&=0b11111000; //Las señales de control siguen siendo salidas, el resto lo que sean
trisa|=0b00001111; //Las de datos pasan a ser entradas, las demas igual
lcd_control.rw = 1;
delay_cycles(1);
lcd_control.enable = 1;
delay_cycles(1);
high = lcd_datos.datos;
lcd_control.enable = 0;
delay_cycles(1);
lcd_control.enable = 1;
delay_us(1);
low = lcd_datos.datos;
lcd_control.enable = 0;
trisa&=0b11110000; // Dejamos RD0 a RD3 como salidas
return( (high<<4) | low);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Envía medio byte, los 4 bits más bajos de n
// Necesario poner rs y rw de modo adecuado y entrar con enable=0
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_send_nibble( byte n )
{
lcd_datos.datos = n;
delay_cycles(1);
lcd_control.enable = 1;
delay_us(2);
lcd_control.enable = 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Envía un byte (n) al registro de instrucciones (si address=0) o reg. de datos (address=1)
// Utiliza lcd_send_nibble(n) enviando primero nibble alto del byte
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_send_byte( byte address, byte n )
{
lcd_control.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ; //Mientras esté ocupado el LCD, espera
lcd_control.rs = address;
delay_cycles(1);
lcd_control.rw = 0;
delay_cycles(1);
lcd_control.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0x0F);
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Sitúa el contador de direcciones en la DDRAM (para lectura o escritura posterior)
// x puede ir de 1 a 40, posición dentro de una línea (16 visibles)
// y puede ser 1 (línea 1) o 2 (línea 2)
/////////////////////////////////////////////////////////////////////////////////////////////
void lcd_gotoxy( byte x, byte y)
{
byte posicion;
switch(y)
{
case 1 : posicion=0x80;break;
case 2 : posicion=0xc0;break;
case 3 : posicion=0x94;break;
case 4 : posicion=0xd4;break;
}
posicion+=x-1;
lcd_send_byte(0,0x80|posicion); //Las direcciones de la DDRAM empiezan por 1xxxxxxx
}
////////////////////////////////////////////////////////////////////////////////////////////
// Envía un carácter c a la DDRAM del LCD, también algunos caracteres de control
////////////////////////////////////////////////////////////////////////////////////////////
void lcd_putc( char c)
{
switch (c)
{
case "f" : lcd_send_byte(0,1); //Limpia la pantalla
delay_ms(2);
break;
case "
" : lcd_gotoxy(1,2); //Coloca puntero en 1ª posicion de la 2ª línea
break;
case "" : lcd_send_byte(0,0x10); //Retrocede una posición el cursor
break;
case " " : lcd_send_byte(0,0x14); //Avanza una posición el cursor
break;
case "" : lcd_send_byte(0,0x18); //Retrocede una posición la pantalla visible
break;
case "v" : lcd_send_byte(0,0x1C); //Avanza una posición la pantalla visible
break;
default : lcd_send_byte(1,c); //Envía caracter a DDRAM,
break; //Si es una tira, los envía todos uno a uno
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Devuelve el carácter situado en la posición x,y de la DDRAM
///////////////////////////////////////////////////////////////////////////////////////////
char lcd_getc( byte x, byte y) {
char value;
lcd_gotoxy(x,y);
lcd_control.rs=1;
value = lcd_read_byte();
lcd_control.rs=0;
return(value);
}
////////////////////////////////////////////////////////////////////////////////////
// Limpia la linea correspondiente y se situa al principio de la misma //
////////////////////////////////////////////////////////////////////////////////////
void lcd_clr_line(char fila)
{
int j;
lcd_gotoxy(1,fila);
for (j=0;j<40;j++) lcd_putc(" ");
lcd_gotoxy(1,fila);
}
No se muy bien como afrontarlo, creo q es akí:
trisc&=0b11111000; // Asignamos salidas en RC0, RC1 y RC2, resto puerto como estaba
trisa&=0b11110000; // Lo mismo para RA0 a RA3
es decir, la forma que tiene de configurar el puerto, ya q el sensor tiene 2 lineas, una de datos (bidireccional), y la del reloj, y al configurar el LCD cuelga al sensor...
Lo que creo debo hacer es (esto no se si funcionará) desabilitar el LCD mientras se esté leyendo el sensor... esto no se como hacerlo.
Otra solución es poner el LCD el solo en el puerto A(solo dispongo de este completo, ya q el sensor puedo ponerlo en el lugar q ocupan actualmente las lineas de control), el problema esq estoy haciendo uso de 7 lineas, y el puerto A solo tiene 6, por lo que habia pensado en deshabilitar la linea RW, ya que en mi diseño no voy a hacer uso de esta linea, debería ponerla a GND, el problema esq la librería si hace uso de ella...y no se como readaptarlo
Otra opción pasa por readaptar la librería xlcd.c (del C18) para que funcione con el CCS, pero parece algo complejo.
Se os curre algo???, lo deseable sería la primera solución, e incluso la segunda :p
Gracias y Un Saludo
