Autor Tema: Teclado por interrupción: codigo sencillísimo que no funciona  (Leído 2201 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado unoquepasa

  • PIC12
  • **
  • Mensajes: 65
Teclado por interrupción: codigo sencillísimo que no funciona
« en: 10 de Febrero de 2008, 19:29:30 »
         Hola, estoy usando un dspic30F4013 para manejar un teclado matricial de 4x4 y no consigo que entre en la rutina de interrupción cuando los pines configurados como entrada cambian.

           Os pongo las especificaciones:

Código: [Seleccionar]
11.5.2 CN Configuration and Operation
The CN pins are configured as follows:
1. Ensure that the CN pin is configured as a digital input by setting the associated bit in the
TRISx register.
 2. Enable interrupts for the selected CN pins by setting the appropriate bits in the CNEN1
and CNEN2 registers.
3. Turn on the weak pull-up devices (if desired) for the selected CN pins by setting the
appropriate bits in the CNPU1 and CNPU2 registers.
4. Clear the CNIF (IFS0<15>) interrupt flag.
5. Select the desired interrupt priority for CN interrupts using the CNIP<2:0> control bits
(IPC3<14:12>).
6. Enable CN interrupts using the CNIE (IEC0<15>) control bit.
When a CN interrupt occurs, the user should read the PORT register associated with the CN
pin(s). This will clear the mismatch condition and setup the CN logic to detect the next pin
change. The current PORT value can be compared to the PORT read value obtained at the last
CN interrupt to determine the pin that changed.
The CN pins have a minimum input pulse width specification. Refer to the “Electrical
Specifications” section of the device data sheet for further details.

        En mi caso las 4 input del teclado corresponden a RB0, RB1, RB2, RB3, con sus resistencias de pull.up internas. Y los 4 pines de salida, son RB4, RB5, RC13 y RC14.   Os pongo el código:

Código: [Seleccionar]
int main ( void )
{
copiab=0;
TRISC = 0x0000;              //Todo el puerto C como salida
TRISB=0x000F;                //RB0, RB1, RB2 y RB3 configurados como entrada y el resto como salida
CNEN1=0x003C;              // Estamos seleccionando, CN2, CN3,CN4 y CN5 que corresponden a los mismos pines que RB0-RB3
                                                                                           //para indicar que si cambian se produzca interrupción
CNPU1=0x003C;              //Aquí activamos las resistencias de Pull-Up de

IFS0bits.CNIF=0;             //Borro el posible flag de interrupción de cambio de RB0-RB4 que pueda haber
IPC3=0x3000;                 //Le proporciono a la interrupcion prioridad media, aunque no existen más interrupciones
        IEC0=0x8000;                //Activo la interrupción de cambio de RB0-RB4

PORTB=0x000F;             //Pongo los RB0-RB4 a 1. Cosa que pensaba que se pondría automáticamente al poner las resistencias de Pull-up pero no era así
                                    //el resto del puerto debe estar a 0 para crear la interrupción cuando se pulse una tecla, creando en RBx un 0 al pulsar
                                            //este efecto ha sido comprobado y ocurre, he puesto un led en RB0 y luce siempre y cuando no apriete las teclas de su fila       
                                            //correspondiente
        PORTC=0x0000;            //todo el puerto C a cero, ya que se usan los pines RC13 y RC14 para crear la interrupción al pulsar la tecla (poniendo RBx a cero)
LCD_Inicializa();            //Rutina de inicialización del display
LCD_Linea1();

while(1)
{  }
return 0;
}

void __attribute__((__interrupt__, __shadow__)) _CNInterrupt(void)     //Rutina de interrupción
{
                __delay32(US_25);              //que espera 25 us (antirebotes)

                //aunque ya lo habíamos definido, lo definimos por una nota sobre los glitches que vi que podían aparecer o algo así:
                TRISC = 0x0000;              //Todo el puerto C como salida
        TRISB=0x000F;                //RB0, RB1, RB2 y RB3 configurados como entrada y el resto como salida

copiab=PORTB;                   //esto simplemente lo hago porque así lo dicen las notas de aplicación
PORTF=~PORTF;                   //en el puerto F tengo un display que debería cambiar su estado (Encendido/apagado) al entrar en la interrupcion
LCD_Caracter('z');               //mando caracter al LCD
    IFS0=0x0000;                    //borro el flag
PORTB=0x000F;                 //los puertos a su configuración de "reposo" (ya que aquí la he quitado, pero en realidad aquí va la llamada a la rutina de
PORTC=0x0000;                                              /saber que tecla he pulsado
return;
}

              Bueno, como véis el código es muy muy sencillo, pero soy nuevo con los dspic (bueno y con los pics tb xD) y algo se me escapa, leer los comentarios que ahí está todo explicado, y si me podéis echar una mano os lo agradecería mucho. El caso es que no entra en la interrupción NUNCA. Ni el led del puerto F cambia su estado ni envia nada al LCD. El programa sin la interrupción funciona perfecto (vamos que enviar cosas al LCD sin problema en el programa main)

Un saludo y gracias por adelantado


Desconectado unoquepasa

  • PIC12
  • **
  • Mensajes: 65
Re: Teclado por interrupción: codigo sencillísimo que no funciona
« Respuesta #1 en: 11 de Febrero de 2008, 21:39:30 »

       La madre que *****! Resulta que había que añadir esta línea:
   ADPCFG=0xFFFF;

para que el puerto B que está compartido con el conversor adc funcione bien (aunque el adc esté desactivado) Al final he usado también todo el puerto b en vez de dos pines del puerto C porque no me funcionaban bien del todo.

Ale, por fin funciona el maldito teclado.

Un saludo!