Programación PIC: obtenga el valor de varios botones en un puerto

Estoy aprendiendo PIC (pic18f4550) y soy bastante nuevo en la programación de microcontroladores. Estoy tratando de obtener el valor de tres botones en PORTA y enviarlo a una matriz LED de 8x8 como coordenadas X a través de un 74LS595 . El problema es que el valor que va a la matriz LED no cambia cuando presiono los botones para crear un valor diferente. Estoy simulando en Proteus, así que supongo que no necesito la función de rebote. Aquí está mi código y esquema:

#include<p18f4550.h>

#define SCK LATBbits.LATB0
#define DATA PORTBbits.RB1
#define SCL PORTBbits.RB2

void Data_in(unsigned char k){
    DATA=k;
    SCK=0;
    SCK=1;
}

void LatchData(){
    SCL=0;
    SCL=1;
}

void Send1byte(unsigned char data)
{
    unsigned char i,temp;
    for(i=0;i<8;i++)
    {
        temp = data & (1<<i);
        if(temp)
        {
            DATA = 1;
        }
        else
        {
            DATA = 0;
        }

        SCK = 0;
        SCK = 1;
    }

SCL = 0;
SCL = 1;
}

unsigned char getMatrixX(unsigned char in_X)
{

    switch(in_X)
    {
        case 0:      // the value stuck here
        return 0b01111111;
    case 1:
        return 0b10111111;
    case 2:
        return 0b11011111;
    case 3:
        return 0b11101111;
    case 4:
        return 0b11110111;
    case 5:
        return 0b11111011;
    case 6:
        return 0b11111101;
    case 7:
        return 0b11111110;
    default:
        return 0b11111111;
    }
}

void main()
{

    TRISA = 1;
    TRISC = 1;

    TRISB = 0;
    TRISD = 0;

    PORTD = 0x80;

    while(1){
        Send1byte(getMatrixX(LATA));
    }
}

Este es el enlace a mi esquema: mi Esquema

Realmente aprecio cualquier solución y consejo. Perdón por mi mal ingles.

Por un lado, en la instrucción switch(), necesita un descanso; al final de cada caso.
gracias por el consejo, pero aún no funciona, además, debido a la instrucción de devolución, no creo que sea necesario un descanso
Tienes razón, el descanso es innecesario aquí.
que tipo de botones tienes? De acuerdo con el esquema, las entradas al procesador se reducirán ~BAJO~ cuando el botón esté cerrado (¿presionado?).
Adam, es solo un botón pulsador normal, Proteus me permite mantenerlo presionado o sin presionar durante la simulación, así que sí, es bajo cuando se presiona y alto cuando no se presiona, uso esos estados para crear valor, para leer

Respuestas (2)

Hay una serie de cosas que deben corregirse en su código antes de que podamos comenzar a ayudarlo con los problemas funcionales. He enumerado algunos a continuación.

Uso de TRIS

Consulte la respuesta de Handoko, que se ocupa de esto.

Uso de registros LAT vs. PORT

Llamas a tu función así: Send1byte(getMatrixX(LATA)). Supongo que su intención es obtener el estado actual de los botones de entrada y enviarlos a esta función.

Esto no funcionará, debe leer del registro PORTA en su lugar. El código correcto sería Send1byte(getMatrixX(PORTA)).

¿Por qué es esto? Hay una breve explicación en la hoja de datos:

Leer el registro PORTA lee el estado de los pines; escribir en él escribirá en el pestillo del puerto.

Y una imagen útil:

Figura 10-1 PUERTO frente a LAT

La línea de datos interna que se usa cuando lee el bit PORT (abajo a la izquierda, desde el bloque verde) está conectada al búfer de entrada, que proviene directamente del pin de E/S. En contraste, la línea de datos utilizada cuando lee el bit LAT (arriba a la izquierda, conectado al bloque rojo) solo lee el estado del latch de datos. No está conectado a la entrada.

Tenga en cuenta que las definiciones de SCK/DATA/SCL deberían funcionar (escribir en el bit PORT establecerá el LAtch) pero normalmente mantengo todas las escrituras en el LAtch excepto cuando es imposible (por ejemplo, buses bidireccionales).

Configuración de funciones analógicas

Debe deshabilitar las funciones analógicas que están multiplexadas en los pines PORTA. Vea esta nota de la hoja de datos:

En un reinicio de encendido, RA5 y RA3:RA0 se configuran como entradas analógicas y se leen como '0'. (sección 10, página 113)

Además, la función de comparación también debe desactivarse. Para configurar todos los pines PORTA en entradas digitales, consulte el Registro 21-2 (ADCON1) en la hoja de datos. Podrías intentar:

ADCON1 = 0x0F; // All digital inputs
CMCON = 0x07;  // Comparators off (note this is the POR default)

Si no hace esto, nunca obtendrá los datos de entrada de sus interruptores, a menos que el simulador Proteus haga cosas inusuales.

Simplificando getMatrixX()

Puede simplificar su función getMatrixX() de varias maneras, dependiendo de si le importa el código o el espacio de datos. Aquí hay uno que usa una tabla de búsqueda (no probado):

unsigned char data[8] = { 0b01111111, 0b10111111, 0b11011111, 0b11101111, 0b11110111, 0b11111011, 0b11111101, 0b01111110 };

unsigned char getMatrixX(unsigned char in_X) {
  if (in_X > 7) {
    return 0xFF;
  }

  return data[in_X];
}

Sería simple hacer lo mismo con un turno y algo de lógica, evitando la tabla de búsqueda:

unsigned char getMatrixX(unsigned char in_X) {
  if (in_X > 7) {
    return 0xFF;
  }

  return 0xFF ^ (0x80 >> in_X);
}
Súper respuesta David, funcionó, ¡realmente funcionó! La función analógica es el problema, su tabla de búsqueda y explicación LAT también me ayuda mucho, no lo entendí hasta ahora. Me acabas de salvar el día, te daré un voto cuando tenga suficiente reputación.
Me alegro de que haya ayudado. Consulte siempre la sección de la hoja de datos titulada "RESUMEN DE REGISTROS ASOCIADOS CON PORTA", por ejemplo, la Tabla 10-2 para el PIC 18F4550. Esto puede ser muy útil para rastrear otras funciones que deben desactivarse.

En primer lugar, debe configurar su entrada y salida correctamente.

Usaste TRISA = 1;lo que significa que solo RA0 es una ENTRADA. Cambie esto a TRISA = 0b00000111;o TRISA = 0x07;para configurar los 3 botones como ENTRADA.

Lo mismo cuenta para TRISB. Cambie este valor a 0x00000111 o 0x07.

Como ha mencionado Peter, cambie todos sus casos en el interruptor a:

case1:
 // TODO
 return;
case2:
 // TODO
 return;

Además, ni siquiera veo dónde escribiste lo que tiene que hacer la MCU cuando se presiona un botón.

+1 para el problema del patrón de bits. Dicho esto, edite su respuesta - descanso; es redundante cuando regresa; está presente en el caso: enunciado.
gracias por responder, probé TRISA = 0xFF y 0x07 ya, no funciona, además como comento, ya tuve return, me devolvió un valor y me salió de la función, así que no creo que necesite descansos . Acerca de los botones, quise obtener solo el valor de ellos, así que puse LATA en la función getMatrixX como puede ver (proteus me permite mantener el botón presionado o sin presionar)
En los PIC mejorados, debe leer desde un PUERTO, escribir en un LAtch.
@David Ese es precisamente el punto que iba a hacer. No estoy familiarizado con los PIC, pero se supone que LATCH se emite, ¿verdad? ¿Puedes siquiera leer de eso?
Puede leer desde el registro LATx, pero solo obtendrá el valor que se ha establecido para el latch de salida. Si un pin está configurado para ingresar en el registro TRISx, entonces el valor en PORTx es lo correcto para leer para las entradas.
gracias por sugerir a David, acabo de intentarlo y todavía no hay señales de funcionar :(, observé el osciloscopio, imageshack.com/a/img837/7949/ci8a.png , la señal de Q0 de 74HC595 (cuarta línea) parece nunca cambiar cuando cambio los estados de los botones