Encender el LED cuando se presiona el botón PIC

1

Tengo una placa olimex con una PIC16LF76 (Esquema - El PIC ES una foto diferente):

Estoy intentando cambiar el LED cuando se presiona el botón, mi código C parece:

#include <xc.h>
#pragma config FOSC = HS        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF       // Power-up Timer Enable bit (PWRT enabled)
#pragma config CP = OFF         // FLASH Program Memory Code Protection bit (Code protection off)
#pragma config BOREN = OFF

int main() {
    TRISA = 0x20;
    ADCON0 = 0b111;
    while(1){
        if((PORTA & 0x20)==0) {
            PORTA |= 0x01;
        } else {
            PORTA &= ~0x01;
        }
    }
}

¿Qué va mal (algo similar funcionaría para Atmel AVR)? Mi compilador es XC8 y estoy usando MPLabX. Puedo confirmar que el interruptor funciona, y también lo hace el LED, ya que he probado estas partes de la placa olimex individualmente e independientemente sin el chip PIC en la placa.

EDITAR:

He intentado las respuestas proporcionadas todavía en vano. También el LED está encendido a pesar de no encenderlo.

    
pregunta Dean

2 respuestas

3

Su problema probablemente se deba al módulo analógico. De acuerdo con la página 84 de la hoja de datos que vinculó, el registro ADCON1 debe configurarse correctamente para habilitar las funciones digitales en PORTA.

Es probable que un valor de 0b111 haga que su código funcione (pero vea otras respuestas sobre el anuncio). Varias otras combinaciones de valores están disponibles en la tabla para REGISTRO 11-2:

Estetipodeconfiguraciónescomúnenlosdispositivosmáspequeños12Fy16F,quenotienenlacapacidaddeseleccionarindividualmenteanalógicoodigitalporpin.

ComoseñalaSpehroenloscomentarios,hayvariasformasdeencontrarquéregistrosestánasociadosconunpuerto.LamássencillaeslaTABLA4-2:RESUMENDELOSREGISTROSASOCIADOSCONPORTA,quetieneesteaspecto:

Esta tabla se vuelve aún más útil en dispositivos grandes que tienen muchas funciones, como funciones analógicas extendidas o captura y comparación. Muchos de estos deben deshabilitarse después del reinicio (por ejemplo, comparadores) y algunos pueden interferir involuntariamente si están mal configurados (por ejemplo, MSSP).

Tenga en cuenta que esta tabla también muestra que el 16LF76 no tiene registros LATx, por lo que otros comentarios anteriores pueden ignorarse de forma segura para este dispositivo.

    
respondido por el David
2

Esta respuesta será similar a mi respuesta aquí .

Primero, es probable que necesites cambiar el rebote. Es decir, desea establecer un retraso en el software o usar un condensador desde la entrada a tierra. Cuando se presiona el interruptor, el contacto se hará y se romperá muy rápidamente antes de finalmente cerrar y tirar el pin de entrada a tierra. Cada vez que se cierra va a encender su LED. Por lo tanto, desea filtrar (paso bajo) los cambios atenuando la frecuencia alta. Aquí hay una buena referencia de publicación de anuncios . Vea las páginas 12-14.

simular este circuito : esquema creado usando CircuitLab

A continuación, es posible que desee establecer una marca para que solo se active una vez que se haya soltado el botón. El bucle no se detendrá una vez que presione el botón. Mientras el interruptor esté cerrado, el bucle continuará ejecutándose y alternando el LED. Tal vez su configuración actual funciona a veces, pero no otros? Eso sería porque estás viendo dónde finalmente se detiene el bucle.

while(1)
{
    //Check to see whether the switch is pressed and flag is set.
    //Then, toggle the port and reset the flag.
    if ((PORTA & 0x20)==0 && flag==1)
    {
        PORTA ^= 0x01; //Notice the XOR (toggle) here. No if-statement needed.
        flag = 0;
    }
    //Now, wait until the switch is released until the pin can be toggled again.
    //This way, if you hold the button down, it will not keep toggling the port
    //repeatedly. It will only toggle it once, then wait for the button to be released.
    else if ((PORTA & 0x20)==1 && flag==0)
    {
        flag = 1;
    }
}

Otra forma sería utilizar una interrupción sobre cambio si está disponible. Entonces podría tener el disparador de interrupción en un flanco descendente y encender el LED allí.

    
respondido por el Justin Trzeciak

Lea otras preguntas en las etiquetas