Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

22/05/2014 #1


Problema en código de teclado + LCD en XC8
Hola,
Tengo un problema al montar mi circuito con Proteus ya que en una PIC SCHOOL si que me funciona.
El pic es pic16f886 y mediante un teclado matricial 4x4 quiero que salgan las teclas pulsadas.
El problema es que yo creo que lo tengo mal conectado.

Código:
#ifndef LCD_H

#define	LCD_H


#ifdef 	__cplusplus
extern "C" 
{

#endif

////////////// cuerpo del header///////////////////////


#define DispRS    RA3

#define DispRW    RA2

#define DispE     RA1
#define LCD_DAT_PORT PORTB

// Register selection
#define CMD_REG         0x00    // Command register
#define DATA_REG    0x01    // Data register
#define LCD_WRITE    0x00    // Writes to LCD
#define LCD_READ    0x01    // Reads from LCD


// LCD specific defines
#define LCD_CLR    0x01    // Clears display
#define LCD_HOME    0x02    // Returns home


// Entry mode set
#define LCD_DEC        0x04    // Decrements DDRAM address
#define LCD_SHIFT_R    0x05    // Shifts display to the right
#define LCD_INC        0x06    // Increments DDRAM address cursor from left to right?
#define LCD_SHIFT_L    0x07    // Shifts display to the left


// Display ON/OFF
#define LCD_DISPOFF    0x08    // Display off
#define LCD_DISPON    0x0C    // Display on
#define LCD_CRS_OFF    LCD_DISPON | 0x00    // Cursor does not display
#define LCD_CRS_ON    LCD_DISPON | 0x02    // Cursor displays
#define LCD_BL_OFF    LCD_DISPON | 0x00    // Cursor does not blink
#define LCD_BL_ON    LCD_CRS_ON | 0x01    // Cursor blinks



// Cursor and Display Shift
#define LCD_SH_C_L    0x10    // Shifts the cursor position to the left (Address Counter is decremented by 1)
#define LCD_SH_C_R    0x14    // Shifts the cursor position to the right (Address Counter is incremented by 1)
#define LCD_SH_D_L    0x18    // Shifts the entire display to the left. The cursor follows the display shift
#define LCD_SH_D_R    0x1C    // Shifts the entire display to the right. The cursor follows the display shift


// Function Set
#define LCD_FN_SET    0x28                // Function set. Data 4-bit
#define LCD_1L_5x8    LCD_FN_SET | 0x00    // Displays 1 line. Character font: 5x 8 dots
#define LCD_1L_5x10    LCD_FN_SET | 0x04    // Displays 1 line. Character font: 5x10 dots
#define LCD_2L_5x8    LCD_FN_SET | 0x08    // Displays 2 line. Character font: 5x 8 dots


// LCD defines for calling lcd_xy with line number, position and cursor status
#define LCD_LN1        0x80 //0x00    // DDRAM address of the 1st line
#define LCD_LN2        0xC0//0x40    // DDRAM address of the 2nd line


#define LCD_CG_SET    0x40    // Sets CG RAM address
#define LCD_DD_SET    0x80    // Sets DDRAM address
#define LCD_BUSY        0x80    // Busy flag


#define LCDNCHARS    16        // Define number of chars per line


// Function prototypes
void lcd_init(void);        // LCD initialization
void lcd_send_cmd(unsigned char data);    // Writes instruction to LCD
void lcd_send_dat(unsigned char data);    // Writes data to LCD



//////////////////////////////////////////////////////
#ifdef	__cplusplus
}
#endif

#endif	/* LCD_H */
Código:
//FICHERO AUTOGENERADO DE BITS DE CONFIGURACIÓN DEL MICROPROCESADOR
//#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF       // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF       // Brown Out Reset Selection bits (BOR enabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)

// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)
Os dejo los codigos que uso para esto.
La conexión la e realizado de la misma manera que la realizo en la protoboard y no me funciona.
No e utilizado nunca el Proteus y nose si me faltara algo
Muchas gracias
24/05/2014 #2


Problema codigo teclado+lcd
Hola,
Mi programa basicamente consiste en que cuando pulse una tecla, esta tecla aparezca en el LCD.
Como no quiero que este todo el rato testeando si a cambiado algun bit del puerto B, quiero hacerlo con interrupciones pero no me funciona.
Pongo aqui el código haber si podeis hechar una mano
Muchas gracias

Código:
#include <stdio.h> 
#include <stdlib.h>
#include <xc.h>
#include "lcd.h"
#include <pic16f886.h>


/* Dos definiciones para determinar un retardo */

#define _XTAL_FREQ 4000000 // necesario para macros __delay_ms()

#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
typedef unsigned char uint8_t;

unsigned char c;
char const KEYS[4][4] = {{'1','2','3','A'},
                         {'4','5','6','B'},
                         {'7','8','9','C'},
                         {'E','0','F','D'}};

void lcd_init()
{
    DispE = 0;
        DispRS = 0;
        __delay_ms(30);

        lcd_send_cmd(0x03);
        lcd_send_cmd(0x03);
        lcd_send_cmd(0x03);

        lcd_send_cmd(0x02);
        lcd_send_cmd(LCD_FN_SET);
        lcd_send_cmd(LCD_DISPOFF);
        lcd_send_cmd(LCD_CLR);
        lcd_send_cmd(LCD_DISPON);
}

void pulseEnable()
{
    DispE = 0;
    __delay_us(1);
    DispE = 1;
    __delay_us(1);
    DispE = 0;
    __delay_us(100);
}

void lcd_send_dat(unsigned char c)
{
        DispE = 0;
        DispRS = 1; //1 para mandar dato
        LCD_DAT_PORT = c >> 4; //ALTO

    pulseEnable();
        __delay_us(200); //5ms para comando, 200us para dato
            LCD_DAT_PORT = c;//( c & 0x0F ); //BAJO
    pulseEnable();
        __delay_us(200);
}

void lcd_send_cmd(unsigned char c)
{
        DispE = 0;
        DispRS = 0; //0 para mandar comando
        LCD_DAT_PORT = c >> 4; //ALTO
    pulseEnable();
        __delay_ms(5); //5ms para comando, 200us para dato
            LCD_DAT_PORT = c;//( c & 0x0F ); //BAJO
    pulseEnable();
        __delay_ms(5);
}

void writeString(const char *msg)
{
    while(*msg!='\0')
        lcd_send_dat(*msg++);
}

char teclado(void){
        unsigned char i,j;
	
	i=0;
	for(j=0;j<4;j++){
		if(PORTBbits.RB4==0){break;}
		i++;
		if(PORTBbits.RB5==0){break;}
		i++;
		if(PORTBbits.RB6==0){break;}
		i++;
		if(PORTBbits.RB7==0){break;}
		i++;
		PORTB<<=1;	//Trasladamos el 0 a siguiente Pin.
	}
	return(KEYS[i][j]);
            }

int main(int argc, char** argv) {
  
    ANSEL = 0X00 ;      //Deshabilitar ADC: Puertos digitales
    ANSELH = 0X00 ;     //Deshabilitar ADC: Puertos digitales
    TRISA = 0xf1;
    PORTA = 0x00;
    TRISB = 0xF0;
    PORTB = 0x00;

   INTCON = 0X88;

//Inicializar
        lcd_init();

    while(1)
    {
        
            lcd_send_cmd(LCD_LN1);      //1ª Línea
            lcd_send_cmd(LCD_HOME);     // Cursor a la posición 0
            lcd_send_cmd(LCD_CLR);      //Borra display
            

                if(INTCONbits.RBIF==1){
                c=teclado();
		lcd_send_dat(c);	// Visualizamos tecla pulsada.
		while(PORTBbits.RB4==0 || PORTBbits.RB5==0 || PORTBbits.RB6==0 || PORTBbits.RB7==0){} //Esperamos a que se suelte.-
		PORTB=0x00;
		INTCONbits.RBIF = 0; //Borramos bandera
	}


       
    }
    return (EXIT_SUCCESS);
}
24/05/2014 #3

Avatar de ByAxel

Hola.
No veo el bloque de interrupción... es necesario declarar cuando se activa interrupciones, de lo contrario al compilar el código, ocupa el espacio del vector de interrupción... va a suceder un bucle innecesario y también provoca que la pila se llene, perdiendo direcciones de retorno y/o datos en el proceso...

void interrupt isr(void)
{
...
// Aquí y fuera NO...
INTCONbits.RBIF = 0;
}

Tambíen, mientraz un flag esté activo, siempre va a saltar al vector de interrupción... y las líneas debajo de if(INTCONbits.RBIF==1){... dificilmente se van a ejecutar.

Ten en cuenta que la interrupción por cambio de estado en el puerto B es eso, cada vez que cambia de estado ya sea de 0 a 1 o de 1 a 0.

Es necesario rehacer la idea... modifica el código...
Saludos.
24/05/2014 #4


Gracias, pero lo que yo quiero es que no este muestreando siempre y eso se hace con la interrupcion. Pero claro nose que es lo que declarar a la interrupción para que no muestree, nose si me entiendes.
Llevo varios días con esto y probando varias cosas y me estoy volviendo un poco loco.
24/05/2014 #5

Avatar de ByAxel

por lo que entiendo... quieres leer el teclado solo cuando alguna tecla esté presionada y no siempre?
Eso se soluciona con interrupción, solo que de una u otra forma se tiene que verificar algo para saber si hay o no una tecla presionada... Por ejemplo, describo como funcionaría en el código:

Código:
#include <xc.h>

struct{
    unsigned char Key;
    unsigned IsPress:1;
    unsigned :7;
}STA = {0, 0};

void interrupt scanKey(void){
    if(INTCONbits.RBIF){
        //-- Lee el teclado
        //-- Recorre cada fila/columna para saber que tecla está presionada
        //-- Guarda en STA.Key
        //-- STA.IsPress = 1 -> Si hay una tecla activa

        PORTB = 0;  // Inhabilita el teclado
        INTCONbits.RBIF = 0;
    }
}

void main(void) {
    OPTION_REGbits.nRBPU = 0;   // PullUp Interno para 4 pines de entrada
    TRISB = 0x0F;               // 4 bits parte baja -> entradas
    INTCON = 0x88;              // Activa interrupciones

    //-- Importante:
    //-- Se mantiene inactivo al puerto del teclado
    PORTB = 0; // Con cero, los 4 bits de salida son cero
    //-- Con eso se asegura que cuando precione cualquier tecla, siempre se envíe
    //-- un cero a los pines de entrada, se cual sea...
    //-- y cuando se produzca la interrupción, recien ahí se escanea el teclado
    //-- esto se aprovecha por la lentitud de los cambios de estado al pulsar una tecla.

    while(1){
        if(STA.IsPress){    // Cuando hay una tecla
           STA.IsPress = 0;
           // Lee STA.Key -> Para saber la tecla presionada

           //--> Posible lugar para el antidebounce, ya que no se recomienda
           // poner en la interrupción
        }

        // Resto del código....
        // ....
    }
}
Es una idea... falta poner en práctica y asegurar un par de cosas...
Saludos
24/05/2014 #6


El problema sigue estando en que continuamente muestrea las filas, así que el problema es ese, en proteus esos pines no hacen otra cosa que cambiar de bajo a alto.
Y solo e conseguido que durante el tiempo que pulso una tecla en la primera columna de la izquierda salga el número 4 en todas las teclas.
Yo tengo el puerto B configurado de esta manera
TRISB = 0xF0;
Si le configuro de la otra forma no me funciona
26/05/2014 #7


Hola,
Ahora mismo el problema que tengo es que me escribe solo en el LCD y siempre un 1 o un 4 al accionar la tecla 7.
Dejo el código sin las interrupciones haber si alguien me puede echar una mano, gracias

Código:
#include <stdio.h> 
#include <stdlib.h>
#include <xc.h>
#include "lcd.h"
#include <pic16f886.h>


/* Dos definiciones para determinar un retardo */

#define _XTAL_FREQ 4000000 // necesario para macros __delay_ms()

#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0)))
typedef unsigned char uint8_t;

unsigned char tecla;
char const KEYS[4][4] = {{'1','2','3','A'},
                         {'4','5','6','B'},
                         {'7','8','9','C'},
                         {'E','0','F','D'}};

void lcd_init()
{
    DispE = 0;
        DispRS = 0;
        __delay_ms(30);

        lcd_send_cmd(0x03);
        lcd_send_cmd(0x03);
        lcd_send_cmd(0x03);

        lcd_send_cmd(0x02);
        lcd_send_cmd(LCD_FN_SET);
        lcd_send_cmd(LCD_DISPOFF);
        lcd_send_cmd(LCD_CLR);
        lcd_send_cmd(LCD_DISPON);
}

void pulseEnable()
{
    DispE = 0;
    __delay_us(1);
    DispE = 1;
    __delay_us(1);
    DispE = 0;
    __delay_us(100);
}

void lcd_send_dat(unsigned char c)
{
        DispE = 0;
        DispRS = 1; //1 para mandar dato
        LCD_DAT_PORT = c >> 4; //ALTO

    pulseEnable();
        __delay_us(200); //5ms para comando, 200us para dato
            LCD_DAT_PORT = c;//( c & 0x0F ); //BAJO
    pulseEnable();
        __delay_us(200);
}

void lcd_send_cmd(unsigned char c)
{
        DispE = 0;
        DispRS = 0; //0 para mandar comando
        LCD_DAT_PORT = c >> 4; //ALTO
    pulseEnable();
        __delay_ms(5); //5ms para comando, 200us para dato
            LCD_DAT_PORT = c;//( c & 0x0F ); //BAJO
    pulseEnable();
        __delay_ms(5);
}

void writeString(const char *msg)
{
    while(*msg!='\0')
        lcd_send_dat(*msg++);
}

char teclado(void){
        unsigned char i,j;
	
	i=0;
	for(j=0;j<4;j++){
		if(PORTBbits.RB4==0){
                __delay_ms(20);
                break;}
		i++;
		if(PORTBbits.RB5==0){
                __delay_ms(20);
                break;}
		i++;
		if(PORTBbits.RB6==0){
                __delay_ms(20);
                break;}
		i++;
		if(PORTBbits.RB7==0){
                __delay_ms(20);
                break;}
		i++;
		PORTB<<=1;	//Trasladamos el 0 a siguiente Pin.
	}
	return(KEYS[i][j]);
            }

int main(int argc, char** argv) {
  
    ANSEL = 0X00 ;      //Deshabilitar ADC: Puertos digitales
    ANSELH = 0X00 ;     //Deshabilitar ADC: Puertos digitales
    TRISA = 0xf1;
    PORTA = 0x00;
    TRISB = 0xF0;
    PORTB = 0x00;

   INTCON = 0X00;

//Inicializar
        lcd_init();
        lcd_send_cmd(LCD_LN1);
    while(PORTBbits.RB4 ==0 && PORTBbits.RB0 ==0 )
    {
        
                 //1ª Línea
           
            
            writeString("X=");
            

               if(1 ){
                   
                
                
                tecla=teclado();
		lcd_send_dat(tecla);
                
                __delay_ms(20);
		
		
	}


       
    }
    return (EXIT_SUCCESS);
}
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.