TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: rferrero en 16 de Mayo de 2004, 06:25:00
-
Hola. Tengo la micro pic trainer y el libro del 16f84 (http://www.microcontroladores.com. Resulta que en el anexo 7 vienen programas escritos en C, a modo de ejemplo. Estoy tratando de sacar por pantalla 4 letras con uno de esos programas y no hay forma. Compila perfectamente, lo grabo en el PIC mediante IC-PROG, pero no saca nada por pantalla. El programa en cuestión es:
#include<16f84.h>
#use delay(clock=4000000,RESTART_WDT)
#include<lcd2.c>
#use fast_io(A)
#use fast_io(B)
main()
{
while(1)
{
lcd_init();
lcd_enviar(LCD_COMANDO,LCD_CURSOR_BLINK);
lcd_putc("H");
lcd_putc("o");
lcd_putc("l");
lcd_putc("a");
sleep();
}
}
Programas en ensamblador funcionan perfectamente, pero para c, no. Será problema del archivo lcd.c?? He probado con varios y no sé qué hacer. He visto 1000 programas de lcd en el foro, pero no consigo que me funcione.
Alguien me puede ayudar???????????
Muchas gracias. Un saludo.
-
Hola.
El ejemplo funciona perfectamente, revisa las conexiones, te envio una captura del ejemplo simulado en Proteus.
Una imagen vale mas que 1000 palabras.
El driver que tienes (lcd2.c creado por los de microsystems y distinto al del ccs) pone el bit enable del lcd en en pin RA2, el R/W e el pin RA1 y el RS en el pin RA0 y todo el puerto B para la
comunicación, así que lo primero es revisar las cnexiones.
Saludos.
-
Recuerda que en el fichero LCD.C tienes que quitar un comentario, para que este funcione sobre el puerto B..
// As defined in the following structure the pin connection is as follows:
// D0 enable
// D1 rs
// D2 rw
// D4 D4
// D5 D5
// D6 D6
// D7 D7
//
// LCD pins D0-D3 are not used and PIC D3 is not used.
// Un-comment the following define to use port B
// #define use_portb_lcd TRUE <--- ESTE COMENTARIO LO TIENES QUE QUITAR.
Las Conexiones son iguales a las de arriba sino que en el puerto b, y si no sale nada puedes mirar el potenciometro de contraste.. a veces puede ser eso.
Saludos
-
- Veo que no tienes los FUSES configurados en el programa, támpoco estan en los programas de Microsystems. Conviene que añadas en todos tus programas #FUSES XT,NOWDT, ... Cuando grabas con el ICPROG ¿desconectas el WDT? ... me parece que este será el problema que tienes.
- ¿Estas usando la Trainer o placas por separado? Si usas esta segunda opción ¿qué pines del PIC usas exactamente para conectar a la LCD?
Un saludo
-
Si lo conectas bien Funciona Perfecto
#include <16F84A.h>
#fuses XT,NOPROTECT,NOWDT
#use delay(clock=4000000)
#use fast_io(A)
#use fast_io(B)
#include<lcd2.c>
main()
{
while(1)
{
lcd_init();
lcd_enviar(LCD_COMANDO,LCD_CURSOR_BLINK);
lcd_putc("H");
lcd_putc("o");
lcd_putc("l");
lcd_putc("a");
sleep();
}
}
-
Antes de nada, muchas gracias a todos por vuestras sugerencias. Adjunto los archivos usados.
En ensamblador, el programa es ejem2_20.asm y el archivo incluido para el manejo de la lcd es lcd_cxx.inc.
En C, el programa es ejem2_20.c y el archivo incluido para el manejo del lcd es lcd2.c, que venía con la micro pic trainer.
Compilo el asm y pongo el 16f84 y funciona perfectamente. Compilo el C, y nada.
Gracias de todas formas!! 
Un saludo.
-
No me deja enviarlo. Dice que no hay espacio suficiente, así que, aunque engorroso (lo siento), lo transcribo aquí directamente.
lcd.asm
;Ejemplo para simulación y/o MicroPIC Trainer
;
;El manejo de la pantalla LCD
;
;Este ejemplo pretende introducirnos en el manejo de la pantalla LCD, para la visualización
;de diferentes mensajes (p.e. Hola).
;
;Debe recordarse que las líneas RA0-RA2 actúan ahora como salida de señales de control hacia
;el LCD. Al estar conectadas con sendos interruptores en la MicroPIC Trainer, estos deben
;estar a nivel lógico "1" permanentemente.
List p=16F84 ;Tipo de procesador
include "P16F84.INC" ;Definiciones de registros internos
Lcd_var equ 0x0c ;Variables (2) de las rutinas de manejo del LCD
org 0x00 ;Vector de Reset
goto Inicio
org 0x05 ;Salva vector de interrupción
include "LCD_Cxx.inc" ;Incluye las rutinas de manejo del LCD
Inicio clrf PORTB ;Borra los latch de salida
bsf STATUS,RP0 ;Selecciona banco 1
clrf TRISB ;Puerta B se configura como salida
movlw b"00011000"
movwf TRISA ;RA0-RA2 salidas, RA3-RA4 entradas
bcf STATUS,RP0 ;Selecciona banco 0
call LCD_INI ;Secuencia de inicio del LCD
movlw b"00001111"
call LCD_REG ;Envía instrucción: LCD ON, Cursor ON y blink ON
movlw "F"
call LCD_DATO ;Visualiza H
movlw "u"
call LCD_DATO ;Visualiza o
movlw "n"
call LCD_DATO ;Visualiza l
movlw "c"
call LCD_DATO ;Visualiza a
movlw "i"
call LCD_DATO ;Visualiza a
movlw "o"
call LCD_DATO ;Visualiza a
movlw "n"
call LCD_DATO ;Visualiza a
movlw "a"
call LCD_DATO ;Visualiza a
movlw " "
call LCD_DATO ;Visualiza blanco
Loop sleep ;Puesta en Standby
goto Loop ;Vuelta a standby
end ;Fin del programa fuente
LCD.c
// Ejemplo para simulación y/o MicroPIC Trainer
// El manejo de la pantalla LCD.
// Este ejemplo pretende introducirnos en el manejo de la pantalla LCD, para la
// visualización de diferentes mensajes (p. ej. Hola).
// Debe recordarse que las líneas RA0-RA2 actúan ahora como salida de señales de control
// hacia el LCD. Al estar conectadas con sendos interruptores en la MicroPIC Trainer,
// estos deben estar a nivel lógico "1" permanentemente.
#include <16f84.h>
#use delay(clock=4000000)
#include <lcd2.c>
#fuses XT,NOWDT,NOPUT
#use fast_io(A)
#use fast_io(B)
main() {
set_tris_a(0x18); // 00011000
set_tris_b(0x00);
lcd_init(); // Comandos de inicialización del LCD.
while(1)
{
lcd_enviar(LCD_COMANDO,LCD_CLEAR); // Envía comando al LCD
lcd_enviar(LCD_COMANDO, LCD_HOME);
lcd_gotoxy(1,1);
lcd_putc(" Prueba "
;
lcd_putc("H"); // Envía caracter al LCD.
lcd_putc("o");
lcd_putc("l");
lcd_putc("a");
lcd_putc(" ");
delay_ms(1000);
}
}
Ahora pongo los archivos de manejo del LCD.
Lcd_cxx.inc
;El conjunto de rutinas que se presentan a continuación permiten realizar las tareas básicas
;de control del módulo de visualización LCD. Este fichero se debe incluir en los futuros
;programas fuente mediante la directiva INCLUDE
;
;Permiten adaptarse a los nuevos tiempos de las nuevas pantallas LCD de Winteck
;
;Las rutinas están adaptadas a las velocidades más lentas de los nuevos módulo de winteck, en las
;cuales el tiempo de activación (Tc) de la señal ENABLE es de 40 uS.
#define ENABLE bsf PORTA,2 ;Activa señal E
#define DISABLE bcf PORTA,2 ;Desactiva señal E
#define LEER bsf PORTA,1 ;Pone LCD en Modo RD
#define ESCRIBIR bcf PORTA,1 ;Pone LCD en Modo WR
#define OFF_COMANDO bcf PORTA,0 ;Desactiva RS (modo comando)
#define ON_COMANDO bsf PORTA,0 ;Activa RS (modo dato
CBLOCK Lcd_var ;Inicio de las variables. Será la primera
Lcd_Temp_1 ;direccón libre disponible
Lcd_Temp_2
ENDC
;*************************************************************************
;UP_LCD: Configuración PIC para el LCD.
;
UP_LCD bsf STATUS,RP0 ;Banco 1
clrf PORTB ;RB <0-7> salidas digitales
movlw b"00011000"
movwf PORTA ;RA0-RA2 salidas, RA3-RA4 entradas
bcf STATUS,RP0 ;Banco 0
OFF_COMANDO ;RS=0
DISABLE ;E=0
return
;
;**************************************************************************
;LCD_BUSY: Lectura del Flag Busy y la dirección.
;
LCD_BUSY LEER ;Pone el LCD en Modo RD
bsf STATUS,RP0
movlw H"FF"
movwf PORTB ;Puerta B como entrada
bcf STATUS,RP0 ;Selecciona el banco 0
ENABLE ;Activa el LCD
nop
LCD_BUSY_1 btfsc PORTB,7 ;Chequea bit de Busy
goto LCD_BUSY_1 ;
DISABLE ;Desactiva LCD
bsf STATUS,RP0
clrf PORTB ;Puerta B salida
bcf STATUS,RP0
ESCRIBIR ;Pone LCD en modo WR
return
;**************************************************************************
;LCD_E: Pulso de Enable. En los nuevos LCD"s esta señal debe estar a "0" unos 40uS antes de
;volver a activarse a "1".
;
LCD_E ENABLE ;Activa E
nop
DISABLE ;Desactiva E
movlw .14
movwf Lcd_Temp_1
LCD_E_1 decfsz Lcd_Temp_1,F ;Pierde unos 40 uS para la constante de tiempo Tc
goto LCD_E_1 ;de los nuevos módulos LCD de winteck
return
;
;**************************************************************************
;LCD_DATO: Escritura de datos en DDRAM o CGRAM. Envía el dato presente en el W
;
LCD_DATO OFF_COMANDO ;Desactiva RS (modo comando)
movwf PORTB ;Valor ASCII a sacar por portb
call LCD_BUSY ;Espera a que se libere el LCD
ON_COMANDO ;Activa RS (modo dato).
goto LCD_E ;Genera pulso de E
;**************************************************************************
;LCD_REG: Escritura de comandos en el LCD. Envía el comando presente en el W
LCD_REG OFF_COMANDO ;Desactiva RS (modo comando)
movwf PORTB ;Código de comando.
call LCD_BUSY ;LCD libre?.
goto LCD_E ;SI.Genera pulso de E.
;***************************************************************************
;LCD_INI: inicialización del LCD enviando el comando "Function Set" 3 veces consecutivas
;con un intervalo de unos 5 mS. El LCD queda borrado y el cursor en la primera posición
LCD_INI movlw b"00111000"
call LCD_REG ;Código de instrucción
call LCD_DELAY ;Temporiza
movlw b"00111000"
call LCD_REG ;Código de instrucción
call LCD_DELAY ;Temporiza
movlw b"00111000"
call LCD_REG ;Código de instrucción
call LCD_DELAY ;Temporiza
movlw b"00000001" ;Borra LCD y Home.
call LCD_REG
return
;*****************************************************************************
;LCD_DELAY: Rutina de temporización de unos 5 mS. Se emplean las variables Lcd_Temp_1
;y LCD_Temp_2 en lugar del TMR0. Este queda libre para las aplicaciones del usuario
LCD_DELAY: clrwdt
movlw .10
movwf Lcd_Temp_1
clrf Lcd_Temp_2
LCD_DELAY_1: decfsz Lcd_Temp_2,F
goto LCD_DELAY_1
decfsz Lcd_Temp_1,F
goto LCD_DELAY_1
return
lcd C
// Funciones para la gestion del display LCD de la MicroPIC Trainer.
// lcd_init() Debe ser llamada antes que las otras funciones.
//
// lcd_putc(c) Visualiza c en la siguiente posición del display.
// Caracteres especiales de control:
// f Borrar display
//
Saltar a la segunda linea
// Retroceder una posición.
//
// lcd_gotoxy(x,y) Selecciona la nueva posicion de escritura en el display.
// (la esquina superior izquierda es 1,1)
//
// lcd_getc(x,y) Devuelve el caracter de la posicion x,y del display.
#bit lcd_enable = 5.2
#bit lcd_rw = 5.1
#bit lcd_rs = 5.0
#byte lcd_a = 5
#byte lcd_b = 6
#define LCD_LINEA2 0x40 // Direccion de memoria para la segunda linea
#define LCD_DATO 1
#define LCD_COMANDO 0
#define LCD_CLEAR 0x01
#define LCD_HOME 0x02
#define LCD_DISPLAY_OFF 0x08
#define LCD_DISPLAY_ON 0x0C
#define LCD_CURSOR_ON 0x0E
#define LCD_CURSOR_BLINK 0x0F
#define LCD_CURSOR_SHIFT_RIGHT 0x10
#define LCD_CURSOR_SHIFT_LEFT 0x14
#define LCD_DISPLAY_SHIFT_RIGHT 0x18
#define LCD_DISPLAY_SHIFT_LEFT 0x1C
int lcd_leer()
{
int valor;
set_tris_a(0x18);
set_tris_b(0xFF);
lcd_rw = 1;
delay_cycles(1);
lcd_enable = 1;
delay_cycles(1);
valor = lcd_b;
lcd_enable = 0;
delay_us(40);
set_tris_b(0x00);
return valor;
}
void lcd_enviar(int dir, int valor)
{
set_tris_a(0x00);
set_tris_b(0x00);
lcd_rs = 0;
while( bit_test(lcd_leer(),7) );
lcd_rs = dir;
delay_cycles(1);
lcd_rw = 0;
delay_cycles(1);
lcd_enable = 0;
lcd_b = valor;
delay_cycles(1);
lcd_enable = 1;
delay_us(2);
lcd_enable = 0;
delay_us(40);
}
void lcd_init()
{
int i;
set_tris_a(0x18);
set_tris_b(0x00);
lcd_enable = 0;
lcd_rw = 0;
lcd_rs = 0;
delay_ms(300);//15
for(i=0; i<3; i++)
{
lcd_enviar(LCD_COMANDO,0x38);
delay_ms(50);//5
}
lcd_enviar(LCD_COMANDO,LCD_DISPLAY_ON);
lcd_enviar(LCD_COMANDO,0x06);
lcd_enviar(LCD_COMANDO,LCD_CLEAR);
lcd_enviar(LCD_COMANDO,LCD_HOME);
}
void lcd_gotoxy( byte x, byte y) {
byte dir;
if(y!=1)
dir=LCD_LINEA2;
else
dir=0;
dir+=x-1;
lcd_enviar(LCD_COMANDO,0x80|dir);
}
void lcd_putc( char c) {
switch (c) {
case "f" : lcd_enviar(LCD_COMANDO,0x01);
delay_ms(2);
break;
case "
" : lcd_gotoxy(1,2); break;
case "" : lcd_enviar(LCD_COMANDO,0x10); break;
default : lcd_enviar(LCD_DATO,c); break;
}
}
char lcd_getc( int x, int y) {
char valor;
lcd_gotoxy(x,y);
lcd_rs = 1;
valor = lcd_leer();
lcd_rs = 0;
return valor;
}
-
Los programas en asm y C de Microsystems correspondientes a enviar al LCD el "mensaje" Hola, funcionan perfectamente (veo que has retocado el programa de C del Ejemplo 2-20)
Solo queda como te recordaba oshow al principio y yo mismo, que nos digas cuales son los pines del PIC que conectas a la LCD (el fichero lcd2.c es para 8 bits, el fichero lcd.c de CCS es para 4 bits, no te líes), aunque por otra parte si dices que el asm te funciona, en fin, raro, raro, raro .... el compilador te va bien con otros programas, no?
-
Cómo que qué pines conecto?? En teoría debería salir por el puerto B, habiendo 3 líneas del puerto A que se usan como control o algo así. Creo que lo pone en el encabezamiento del programa en asm.
Pues sí. Funciona perferctamente todo con otros programas. El caso es que hago lo mismo en C y nada. No es que, ni siquiera, se borre la pantalla, es que sale con cuadraditos negros, como si no recibiera órdenes ni nada de nada.
Gracias. Un saludo.