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.
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.
Consulte la respuesta de Handoko, que se ocupa de esto.
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:
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).
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.
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);
}
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.
pedro bennett
usuario3669754
Dzarda
Adán cabeza
usuario3669754