Dudas con el compilador XC8

cosmefulanito04 dijo:
Cuando definiste la función, ¿qué tipo de variables devolvía?

Otras cosas:

- No tiene mucho sentido usar una variable global para luego obtener su valor mediante la devolución de una función. Sería bueno que esa variable sea local.

- Te recomiendo usar el comando switch, para no tener que hacer poner tantos if, a la larga el código se entiende mucho más.

Cuando definí la función hice que devolviese un entero, la variable key es de tipo entero y la variable que recoge el valor que devuelve la función es también de tipo entero. Probare como se ha dicho de cambiarlo a unsigned int.
Tienes razón, es un poco tontería eso que he hecho de poner la variable global si sólo la quiero para esa función, la pasare a local.
Respecto al comando switch lo suelo utilizar, simplemente he hecho esto para probar que le pasaba a la variable, pero es temporal ya que quiero que lo haga la LCD directamente.

Esta noche en llegar me pongo con el programa y os cuento que tal va saliendo la cosa.

Muchas gracias.
Un saludo!.
 
Por lo que decís, pareciera que hiciste todo bien.

Resumiendo hiciste algo como esto:

Código:
...

int mi_funcion();

void main()
{
   int variable;
   ...// Inicialización
   while(1)
    {      
      variable=mi_funcion();
      ...//El resto del código
    }
}

int mi_funcion()
{
  int var_ret;
  //... Código
  return var_ret;
}
 
Por lo que decís, pareciera que hiciste todo bien.

Resumiendo hiciste algo como esto:

Código:
...

int mi_funcion();

void main()
{
   int variable;
   ...// Inicialización
   while(1)
    {      
      variable=mi_funcion();
      ...//El resto del código
    }
}

int mi_funcion()
{
  int var_ret;
  //... Código
  return var_ret;
}

Exacto, eso es lo que tenía.
El tema es que lo acabo de modificar todo a unsigned int y me sigue dando problemas, realmente lo que está pasando es lo siguiente:

Desde la librería de Keypad, antes de enviarme el key por return, segun el boton del keypad recibo una key distinta, tal que asi:

0 4 8
1 5 9
2 6 10
3 7 11

Lo cual es lo que quiero, ya que tengo una key distinta para cada botón y desde un array podría tener una letra/numero en funcion de la posicion.

Pero sin embargo, cuando recibo la key en la llamada a la funcion, recibo estas keys cuando pulso los botones respectivos:

0 0 0
1 1 1
2 2 2
3 3 3

La verdad que no tiene sentido que la key tenga un valor antes del return y uno distinto después.
¿Alguna idea de qué podría estar pasando?

Un saludo!.
 
Para mí el problema no lo tenés en ese retorno, sino en el uso de esa librería en conjunto con tu hard.

De ser así, ¿qué provocaría que la variable key adopte distintos valores?



Pongo aquí el método que se encarga de decirme que tecla es la que está pulsada para asegurarnos que no esté ahí el fallo.
Código:
int Keypad_Check(void)
{
    uint8_t columna;
    int key = 0;


    const unsigned char keypad_array[] =
        {'1','2','3','A',
         '4','5','6','B',
         '7','8','9','C',
         '*','0','#','D','-'};


    if(NUMBER_COLUMNS == 4)
    {
        for (columna = 0b10000000; columna > 0b00000100; columna >>= 1)
    {
        PORTB = ~columna;
        if (PORTBbits.KEYPAD_ROW1 == 0) break; key++;
        if (PORTBbits.KEYPAD_ROW2 == 0) break; key++;
        if (PORTBbits.KEYPAD_ROW3 == 0) break; key++;
        if (PORTBbits.KEYPAD_ROW4 == 0) break; key++;
    }
    }

   if(NUMBER_COLUMNS == 3)
   {

    for (columna = 0b01000000; columna > 0b00001000; columna >>= 1)
    {
        PORTB = ~columna;

        if (PORTBbits.KEYPAD_ROW1 == 0){
            break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW2 == 0){
            break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW3 == 0){
            break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW4 == 0){
            break;
        }
        key++;
        
    }


   }


    //PORTB = 0xFF;
    
    if(key == 11)
    {
        LED = 1;
    }
    else if(key == 1)
    {
        LED = 0;
    }


    return key;

}
Lo curioso es que el led se enciende solo cuando pulso la ultima tecla ya que es la tecla 11, pero para apagarlo, debido al fallo que he comentado antes, me sirven las teclas de las posiciones 1, 5 y 9, ya que por alguna extraña razon, si yo digo tecla 5 sería solo la posición 5, pero si digo 1, son las 3.

Un saludo!.
 
Última edición por un moderador:
Lo que no veo en esa rutina es el antirrebote.

Después habría que analizar si el resto está bien, por ej. el "keypad_array" no lo usas nunca.


Respecto al antirrebote de acuerdo, añadire un pequeño delay cada vez que sepamos que se ha pulsado para evitar posibles problemas.

Respecto a keypad_array es porque iba en un principio a pasar el valor como keypad_array[key], pero no he añadido aun a la libreria lcd la funcion de escribir un solo char, por eso aun no le he dado uso, pero lo he puesto ya para no olvidarlo.
 
Sabes que pasa, es difícil analizar ese código porque no explicás su procedimiento, como tampoco subiste la conexión del hard, en si lo importante es el teclado.

Yo cuando usé teclado matricial lo encaré de otra forma, para que te des una idea:

  1. Antirrebote: para encarar un buen antirrebote lo ideal es una interrupción de timer.
  2. Hard: verificar que el hard esté bien hecho, si los pull-ups están bien, que tenga las protecciones correctas en caso de pulsar dos pulsadores (diodos), que estén conectados al puerto correctamente.
  3. Rutina: una de las mejores formas de encararlo es mediante el uso máquinas de estado en conjunto con el timer.
 
Sabes que pasa, es difícil analizar ese código porque no explicás su procedimiento, como tampoco subiste la conexión del hard, en si lo importante es el teclado.

Yo cuando usé teclado matricial lo encaré de otra forma, para que te des una idea:

  1. Antirrebote: para encarar un buen antirrebote lo ideal es una interrupción de timer.
  2. Hard: verificar que el hard esté bien hecho, si los pull-ups están bien, que tenga las protecciones correctas en caso de pulsar dos pulsadores (diodos), que estén conectados al puerto correctamente.
  3. Rutina: una de las mejores formas de encararlo es mediante el uso máquinas de estado en conjunto con el timer.

Tienes razón, voy a explicarlo mejor y más detenido.

Voy a subir primero el código del archivo encargado de manejar las funciones del keypad:

Código:
#include <xc.h>
#include <stdint.h>
#include <stdio.h>

#include "Keypad.h"


#define KEYPAD_ROWS_PORT     PORT(PORT_ROWS)
#define KEYPAD_ROWS_TRIS     TRIS(PORT_ROWS)

#define KEYPAD_COLUMNS_PORT  PORT(PORT_COLUMNS)
#define KEYPAD_COLUMNS_TRIS  TRIS(PORT_COLUMNS)

#define KEYPAD_ROW1          PORTBIT(PORT_ROWS,KEYPAD_ROW1_POS)
#define KEYPAD_ROW1_TRIS     TRISBIT(PORT_ROWS,KEYPAD_ROW1_POS)

#define KEYPAD_ROW2          PORTBIT(PORT_ROWS,KEYPAD_ROW2_POS)
#define KEYPAD_ROW2_TRIS     TRISBIT(PORT_ROWS,KEYPAD_ROW2_POS)

#define KEYPAD_ROW3          PORTBIT(PORT_ROWS,KEYPAD_ROW3_POS)
#define KEYPAD_ROW3_TRIS     TRISBIT(PORT_ROWS,KEYPAD_ROW3_POS)

#define KEYPAD_ROW4          PORTBIT(PORT_ROWS,KEYPAD_ROW4_POS)
#define KEYPAD_ROW4_TRIS     TRISBIT(PORT_ROWS,KEYPAD_ROW4_POS)

#define KEYPAD_COLUMN1       PORTBIT(PORT_COLUMNS,KEYPAD_COLUMN1_POS)
#define KEYPAD_COLUMN1_TRIS  TRISBIT(PORT_COLUMNS,KEYPAD_COLUMN1_POS)

#define KEYPAD_COLUMN2       PORTBIT(PORT_COLUMNS,KEYPAD_COLUMN2_POS)
#define KEYPAD_COLUMN2_TRIS  TRISBIT(PORT_COLUMNS,KEYPAD_COLUMN2_POS)

#define KEYPAD_COLUMN3       PORTBIT(PORT_COLUMNS,KEYPAD_COLUMN3_POS)
#define KEYPAD_COLUMN3_TRIS  TRISBIT(PORT_COLUMNS,KEYPAD_COLUMN3_POS)

#define KEYPAD_COLUMN4       PORTBIT(PORT_COLUMNS,KEYPAD_COLUMN4_POS)
#define KEYPAD_COLUMN4_TRIS  TRISBIT(PORT_COLUMNS,KEYPAD_COLUMN4_POS)

#define LED    PORTCbits.RC1



void Keypad_Init(void){

    TRISCbits.TRISC1 = 0;
    LED = 0;

    KEYPAD_ROWS_TRIS &=(~(0x0F<<KEYPAD_ROW1_POS)); // Output for the 4 rows
    KEYPAD_ROWS_PORT =(~(0xFF<<KEYPAD_ROW1_POS)); //Cleaning ports

    KEYPAD_COLUMN1_TRIS = 0;


    if (NUMBER_COLUMNS == 4)
    {
        KEYPAD_COLUMN1_TRIS = 0;
        KEYPAD_COLUMN2_TRIS = 0;
        KEYPAD_COLUMN3_TRIS = 0;
        KEYPAD_COLUMN4_TRIS = 0;
    }
    else if (NUMBER_COLUMNS == 3)
    {
        KEYPAD_COLUMN1_TRIS = 0;
        KEYPAD_COLUMN2_TRIS = 0;
        KEYPAD_COLUMN3_TRIS = 0;
    }

}

unsigned int Keypad_Check(void)
{
    uint8_t columna;
    int key = 0;


    const unsigned int keypad_array[] =
        {0,1,2,3,
         4,5,6,7,
         8,9,10,11};


    if(NUMBER_COLUMNS == 4)
    {
        for (columna = 0b10000000; columna > 0b00000100; columna >>= 1)
    {
        PORTB = ~columna;
        if (PORTBbits.KEYPAD_ROW1 == 0) break; key++;
        if (PORTBbits.KEYPAD_ROW2 == 0) break; key++;
        if (PORTBbits.KEYPAD_ROW3 == 0) break; key++;
        if (PORTBbits.KEYPAD_ROW4 == 0) break; key++;
    }
    }

   if(NUMBER_COLUMNS == 3)
   {
       key = 0;

    for (columna = 0b01000000; columna > 0b00001000; columna >>= 1)
    {
        PORTB = ~columna;

        if (PORTBbits.KEYPAD_ROW1 == 0){
            break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW2 == 0){
            break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW3 == 0){
            break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW4 == 0){
            break;
        }
        key++;
        
    }

   }


    PORTB = 0xFF;
    
    if(key == 11)
    {
        LED = 1;
    }
    else if(key == 1)
    {
        LED = 0;
    }


    return keypad_array[key];

}
Ahora la función main, la cual llama a la funcion encargada de chequear el keypad:
Código:
#include <xc.h>
#include <stddef.h>

#include "Keypad.h"
#include "lcd_hd44780.h"

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON         // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)



void main(void) {

  OPTION_REGbits.nRBPU = 0b0;

      
unsigned int variable;

  Keypad_Init();
  LCDInit(LS_NONE);
  LCDClear();



  while(1){


   variable = Keypad_Check();

   LCDGotoXY(0,0);
   LCDWriteInt(variable,2);

  }
 

}
En cuanto a los rebotes con el timer0 no se como afrontarlo, no estaría bien si utilizo un pequeño delay o hago que el programa espere hasta que el usuario suelte la tecla?

En cuanto a las maquinas de estado de acuerdo, procuraré programar de una forma limpia y más estructurada para poder entender mejor el código.

Un saludo!.
 
Última edición por un moderador:
Sigue faltando el hard, más que nada la conexión del teclado, así medio que estoy adivinando :rolleyes:.

El uso del delay no es la mejor solución, pero se puede implementar, el tema es que hay que hacerlo con cuidado para no bloquear el uC.

De ese código yo entendí esto:

  1. Definís los puertos para las filas y columnas.
  2. Las columnas funcionan como salida, como no uso PIC, no sé si su configuración es correcta.
  3. Las filas como entradas, nuevamente, como no uso PIC, no sé si su configuración es correcta.
  4. En la función "Keypad_Check" usando el for vas rotando el bit de las columnas en el puerto B (negás el valor y vas asignando 0b 0111 1111 -> 0b 1011 1111 -> 0b 1101 1111); pero hay un problema, las filas también son el puerto "B" y cuando asignas "PORTB = ~columna;", estás pisando momentáneamente el valor físico de las filas (no sé que efecto puede traerte esto en la familia PIC) por "1111".
  5. Con el bit de la columna en "0", preguntás por el estado de c/fila y cortás el for cuando detectás un "0" en una cierta fila.
  6. Es raro el uso del índice key, ya que por ej. si estamos en la columna 1 y en la fila 2 obtenemos el valor de índice 2, pero ese indice hace referencia al nº 2 y no al nº 4 (teclado típico telefónico).

Lo que te propongo corregir:

  • Es vital el uso de un antirrebote. Para facilitar la implementación te propongo algo muy burdo, cuando detectes una fila, en vez de hacer solamente un break, implementá un delay de 300mS (después empezá a bajar ese tiempo hasta sentirte cómodo). Es importante que solo se implemente ese delay cuando se detecta una pulsación.
  • El problema del punto 2 lo resolvés usando máscaras, es decir en vez de:

    Código:
    PORTB = ~columna;

    Usás esto:

    Código:
    PORTB &= ~columna;

    Esa línea te permite mantener el valor del resto del puerto B y solo pone en 0 el bit de rotación. Sin embargo las columnas anteriores no vuelven a 1, por lo tanto el código final debería ser así:

    Código:
    PORTB |= 0b11100000; //Forzas a "1" todas las columnas
    PORTB &= ~columna; //Forzas a "0" la columna que usas para medir el estado de las filas.
  • El problema del punto 6 se arregla reordenando el contenido del vector "keypad_array", nuevamente yo estoy pensando que el teclado es el típico telefónico.

Eso sería lo que probaría.
 
Primero de todo agradecerte la ayuda, ya que me está ayudando mucho a entender cómo programar los pics.
He realizado los cambios propuestos y sigue sin funcionar, subo una imagen de la conexión del pic con el keypad.
qdnr.jpg


Un saludo!.
 
Viendo el hard noto que las modificaciones que te puse en las columnas no se corresponden. El código debería quedar así:

Código:
PORTB |= 0b01110000; //Forzas a "1" todas las columnas
PORTB &= ~columna; //Forzas a "0" la columna que usas para medir el estado de las filas.

Antes faltaba forzar una columna a 1.

Otra cosa, ¿las filas la configurás como entradas con pull-up? y las columnas ¿cómo configurás la salida?

Yo lo configuraría:

- Fila como entrada con pull-up.
- Columnas, salida sin pull-up (si se puede).

Sobre el punto 6 que puse antes, me equivoqué, si se presiona el pulsador cuando estamos en la columna 1 y en la fila 2, el valor de la variable "key" será simplemente 1, como resultado la función devolverá el nº 1.

¿Los delay te quedaron bien? Así debería quedarte esa rutina:

Código:
for (columna = 0b01000000; columna > 0b00001000; columna >>= 1)
    {
        PORTB |= 0b01110000; //Forzas a "1" todas las columnas
        PORTB &= ~columna; //Forzas a "0" la columna que usas para medir el estado de las filas.

        if (PORTBbits.KEYPAD_ROW1 == 0){
           delay_ms(300); 
           break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW2 == 0){
            delay_ms(300); 
            break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW3 == 0){
            delay_ms(300); 
            break;
        }
        key++;

        if (PORTBbits.KEYPAD_ROW4 == 0){
            delay_ms(300); 
            break;
        }
        key++;
        
    }

Y si no me equivoco, el vector debería quedarte así:

Código:
const unsigned int keypad_array[] =
        {1,4,7,10,2,5,8,0,3,6,9,11};

Y en caso de no haber presionado nada, deberías descartar el dato sabiendo que key será igual a 12.
 
Última edición:
??? mm vale cosmefulanito, he ido a realizar las modificaciones en el codigo tal como me has comentado, y lo curioso es que antes no me iba, y al añadir los retardos, ha funcionado perfectamente, de que manera influyen los retardos en el valor? :/

Muchisimas gracias de nuevo por todo, no se si lo habria conseguido sin tu ayuda!
 
Como te dije, esos delay estan pensados para evitar rebotes que es el gran problema que tenés cuando empleas un pulsador.

Para que tengas una idea de lo que lee el uC cuando presionas un pulsador:

EliminadorRebote7.gif


Ese problema hacía que tu variable "key" vaya tomando valores distintos en c/rebote y aparecían datos incorrectos.

Pero como te dije, ese antirrebote es muuuuuy precario y estaría bueno que lo implementes con timers. Para que te des una idea de como se debería implementar un buen antirrebote por soft:

Cosmefulanito04 dijo:
Por lo tanto un método para saber si el pulsador realmente fue presionado y descartar rebotes y ruido es hacer esto:

1- Detectada la pulsación esperar 5mSeg.
2- Pasados 5mSeg, preguntar si el PIN se encuentra en el estado correcto (en este caso debe estar en estado bajo, por ser flanco descendente), para agregar mayor confiabilidad esperar otros 5mSeg.
3- Pasados otros 5mSeg, nuevamente preguntar el estado del PIN, si es el correcto dar como válido la pulsación, de lo contrario se trata de ruido/rebote.
4- (Opcional) Esperar un cierto tiempo (ej. 300mSeg o 1Seg) y verificar el estado del PIN, si sigue en el estado correcto, se toma como válida otra pulsación (esta condición habilita que el usuario aumente la cuenta manteniendo el botón pulsado).
5- (Opcional) Esperar a que el PIN vuelva al otro estado para repetir la secuencia desde 1, de lo contrario, se repite 4.
 
Primero de todo, perdón por tardar tanto en responder, no he podido acceder estos días y no sabía de tu respuesta.
Sí, sabía que los pulsadores funcionaban así, pero pensaba que al ser simulado en proteus sería en un funcionamiento ideal (sin rebotes), pero ya veo que no es así ^^.

Quería comentar que estoy trabajando en diseñar una librería para utilizar pantallas GLCD.

He conseguido que muestre cosas en pantalla aunque lo que muestra son caracteres que no tienen mucho sentido, adjunto el código e imagen de mi conexionado para ver si alguien puede ayudarme.

No hace falta decir que si puedo ayudar a alguien con las librerías que ya tengo no hay mas que pedírmelo!.

Código GLCD.h

Código:
/* 
 * File:   GLCD.h
 * Author: Manuel
 *
 * Created on 2 de junio de 2014, 22:39
 */

#ifndef GLCD_H
#define    GLCD_H

#include <xc.h>
#include <stdint.h>

#ifdef    __cplusplus
extern "C" {
#endif


    unsigned char __cgram[]=
{
    0x0C, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00, //Char0 degree symbol
    0x00, 0x04, 0x0E, 0x1F, 0x0E, 0x04, 0x00, 0x00, //Char1
    0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04, 0x00, //Char2
    0x0A, 0x15, 0x11, 0x0A, 0x04, 0x00, 0x00, 0x00, //Char3
    0x0A, 0x1F, 0x1F, 0x0E, 0x04, 0x00, 0x00, 0x00, //Char4
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Char5
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Char6
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //Char7
};





#define _CONCAT(a,b) a##b
#define _CONCAT2(port,pos)  TRIS##port##bits.TRIS##port##pos
#define _CONCAT3(port,pos)  R##port##pos
#define PORT(x) _CONCAT(PORT,x)
#define TRIS(x) _CONCAT(TRIS,x)
#define TRISBIT(__port,__pos) _CONCAT2(__port,__pos)
#define PORTBIT(__port,__pos) _CONCAT3(__port,__pos)


#define GLCD_DATA        D


//Register Select (RS)
#define GLCD_RS_PORT     C
#define GLCD_RS_POS      5

//Read/Write (RW)
#define GLCD_RW_PORT     C
#define GLCD_RW_POS      6

//Enable signal (E)
#define GLCD_E_PORT      C
#define GLCD_E_POS       7

#define LS_NONE     0B00000000


void GLCDInit(uint8_t style);
void GLCDGotoXY(uint8_t x,uint8_t y);
void GLCDWriteInt(int val,int8_t field_length);

void GLCDByte(uint8_t,uint8_t);

#define GLCDCmd(c) (GLCDByte(c,0))
#define GLCDData(d) (GLCDByte(d,1))


void GLCDBusyLoop();




#ifdef    __cplusplus
}
#endif

#endif    /* GLCD_H */
código GLCD.c

Código:
#include <xc.h>
#include <stdint.h>

#include "GLCD.h"

#define GLCD_DATA_PORT     PORT(GLCD_DATA)
#define GLCD_DATA_TRIS     TRIS(GLCD_DATA)

#define GLCD_E           PORTBIT(GLCD_E_PORT,GLCD_E_POS)
#define GLCD_E_TRIS      TRISBIT(GLCD_E_PORT,GLCD_E_POS)

#define GLCD_RS          PORTBIT(GLCD_RS_PORT,GLCD_RS_POS)
#define GLCD_RS_TRIS     TRISBIT(GLCD_RS_PORT,GLCD_RS_POS)

#define GLCD_RW          PORTBIT(GLCD_RW_PORT,GLCD_RW_POS)
#define GLCD_RW_TRIS     TRISBIT(GLCD_RW_PORT,GLCD_RW_POS)



#define SET_ENABLE() (GLCD_E=1)
#define SET_RS() (GLCD_RS=1)
#define SET_RW() (GLCD_RW=1)

#define CLEAR_ENABLE() (GLCD_E=0)
#define CLEAR_RS() (GLCD_RS=0)
#define CLEAR_RW() (GLCD_RW=0)



void GLCDInit(uint8_t style)
{
    /*****************************************************************

    This function Initializes the lcd module
    must be called before calling lcd related functions

    Arguments:
    style = LS_BLINK,LS_ULINE(can be "OR"ed for combination)
    LS_BLINK : The cursor is blinking type
    LS_ULINE : Cursor is "underline" type else "block" type
        LS_NONE : No visible cursor

    *****************************************************************/

    //After power on Wait for LCD to Initialize
    __delay_ms(30);

    //Set IO Ports
    GLCD_DATA_TRIS=~(0xFF); //Output

        GLCD_E_TRIS=0;   //Output
        GLCD_RS_TRIS=0;  //Output
        GLCD_RW_TRIS=0;  //Output

    GLCD_DATA_PORT= ~(0xFF);//Clear data port

        CLEAR_ENABLE();
    CLEAR_RW();
    CLEAR_RS();


    __delay_us(0.5);    //tAS

    SET_ENABLE();
    GLCD_DATA_PORT|=(0b00000010); //[B] To transfer 0b00100000 i was using LCD_DATA_PORT|=0b00100000

        __delay_us(1);

        CLEAR_ENABLE();

        __delay_us(1);

    //Wait for LCD to execute the Functionset Command
    GLCDBusyLoop();                                    //[B] Forgot this delay

    //Now the LCD is in 4-bit mode


    GLCDCmd(0b00101000);             //function set 4-bit,2 line 5x7 dot format
        GLCDCmd(0b00111111|style);    //Display On

        /* Custom Char */
        GLCDCmd(0b01000000);
        //GLCDCmd(0b00000010);

    uint8_t i;
    for(i=0;i<sizeof(__cgram);i++)
        GLCDData(__cgram[i]);



}




void GLCDGotoXY(uint8_t x,uint8_t y)
{

}





void GLCDByte(uint8_t c,uint8_t isdata)
{
//Sends a byte to the LCD in 4bit mode
//cmd=0 for data
//cmd=1 for command


if(isdata==0)
    CLEAR_RS();
else
    SET_RS();

__delay_us(0.5);        //tAS

SET_ENABLE();

//Send high nibble

GLCD_DATA_PORT = c;

__delay_us(1);            //tEH

//Now data lines are stable pull E low for transmission

CLEAR_ENABLE();


__delay_us(1);            //tEL

GLCDBusyLoop();
}


void GLCDBusyLoop()
{
    
}


void GLCDWriteInt(int val,int8_t field_length)
{

    /***************************************************************
    This function writes a integer type value to LCD module

    Arguments:
    1)int val    : Value to print

    2)unsigned int field_length :total length of field in which the value is printed
    must be between 1-5 if it is -1 the field length is no of digits in the val

    ****************************************************************/

    char str[5]={0,0,0,0,0};
    int i=4,j=0;

        //Handle negative integers
        if(val<0)
        {
            GLCDData('-');   //Write Negative sign
            val=val*-1;     //convert to positive
        }

    while(val)
    {
            str[i]=val%10;
            val=val/10;
            i--;
    }
    if(field_length==-1)
        while(str[j]==0) j++;
    else
        j=5-field_length;


    for(i=j;i<5;i++)
    {
    GLCDData(48+str[i]);
    }
}
Main
Código:
#include <xc.h>

#include "GLCD.h"

void main(void) {
    GLCDInit(LS_NONE);
    GLCDWriteInt(10,1);

    while(1)
    {
        
    }

}
Mi duda es, la matriz __cgram que estoy utilizando es la que obtuve de una libreria para la lcd, para glcd es la misma?
Sea o no la misma, ¿cómo puedo yo saber que valores van en cada casilla para entender mejor el código y el funcionamiento de esa matriz?

Adjunto lo que muestra mi pantalla GLCD en la simulación en proteus.

7o06k.jpg



Muchas gracias.

Un saludo!.
 
Última edición por un moderador:
Si alguien que lea este mensaje me podria ayudar estaria muy agradecido, ultimamente es estado por mi propia cuenta tratando de aprende a programa con el compilador CX8 en MPLAB X, y ya entiendo algunas cosas, y ya compile el primer codigo que hice, el parpadear un LED conectado a un pin, cuando lo simulo en ISIS de proteus funciona, pero al gravarle a un pic en la protoboard este no realiza ninguna accion, y noce que puede estar mal, adjunto el archivo del proyecto por siacaso les sirve.

Pd: el programador que utilizo es el PicKit 2, y la version del compilador CX8 es v1.37
 

Adjuntos

  • app2.X.rar
    36.5 KB · Visitas: 0
Saludos.
Prueba el siguiente código con esta palabra de configuración.
Si te funciona, entonces podré corroborar a qué se debió el error.

PHP:
#include <xc.h>
#define _XTAL_FREQ 4000000

#pragma config FOSC = INTOSCCLK,WDTE = OFF,PWRTE = ON,MCLRE = OFF,LVP = OFF

void main (void)
{
    TRISBbits.TRISB0 = 0;   // RB0 como salida
    
    while(1)
    {
        RB0 =~ RB0;
        __delay_ms(500);
    }
}
 
Última edición:
Estaba revisando los dos códigos y vi algo interesante, los dos códigos si funcionan pero con una velocidad muy muy lenta, por eso pensaba que algo estaba mal, porque al inicio el led conectado estaba apagado por mucho tiempo, cuando escribo __delay_ms(100); no me da un retardo de 100 mili segundos sino de unos 10 o 15 segundos, dejo el código tal ves sirva, me ayudaría mucho saber el porque no me da el retardo que yo quiero de 100 mili segundo al usar esta linea de código "__delay_ms(100);"
 

Adjuntos

  • app2.X.rar
    1.9 MB · Visitas: 4
OK. Entonces se tiene que configurar el registro OSCCON para que el oscilador funcione a 4 MHz.
Ya que por defecto en el PIC16F819, el oscilador trabaja a una frecuencia de 31.25 KHz.

Agrega estas líneas en el main, que pueden ser de la siguiente forma:

Así:
OSCCON = 0b01100000;
O así:
OSCCONbits.IRCF2 = 1;
OSCCONbits.IRCF1 = 1;

Como el bit IRCF0 por defecto es 0, no tiene caso configurarlo.
Opcionalmente también puedes poner lo siguiente:
while(!OSCCONbits.IOFS);
Ésto es para esperar hasta que el oscilador interno se encuentre estable.

Suerte.
 
Atrás
Arriba