PIC-Programmierung - Holen Sie sich den Wert mehrerer Tasten an einen Port

Ich lerne PIC (pic18f4550) und bin ziemlich neu in der Mikrocontroller-Programmierung. Ich versuche, den Wert von drei Tasten auf PORTA zu erhalten und ihn als X-Koordinaten über einen 74LS595 an eine 8x8-LED-Matrix zu senden . Das Problem ist, dass sich der Wert, der zur LED-Matrix geht, nicht ändert, wenn ich die Tasten drücke, um einen anderen Wert zu erzeugen. Ich simuliere auf Proteus, also brauche ich wohl keine Entprellfunktion. Hier ist mein Code und Schema:

#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));
    }
}

Dies ist ein Link zu meinem Schaltplan: mein Schaltplan

Bin wirklich dankbar für Lösungen und Ratschläge. Entschuldigung für mein schlechtes Englisch.

Zum einen brauchen Sie in der switch()-Anweisung eine Pause; jeweils am Ende.
danke für den rat, funktioniert aber immer noch nicht, außerdem halte ich aufgrund der rücksendeanweisung eine pause für nicht nötig
Du hast recht, Pause ist hier unnötig.
was hast du für Knöpfe? Gemäß dem Schema werden die Eingänge zum Prozessor ~ LOW ~ gezogen, wenn die Taste geschlossen (gedrückt?) wird.
Adam, es ist nur ein normaler Druckknopf, Proteus erlaubt mir, ihn während der Simulation gedrückt oder nicht gedrückt zu halten, also ja, er ist niedrig, wenn er gedrückt wird, und hoch, wenn er nicht gedrückt ist. Ich benutze diese Zustände, um Werte zu schaffen, um daraus zu lesen

Antworten (2)

Es gibt eine Reihe von Dingen, die in Ihrem Code behoben werden müssen, bevor wir mit der Unterstützung bei den Funktionsproblemen beginnen können. Ich habe unten ein paar aufgelistet.

Verwendung von TRIS

Bitte beachten Sie die Antwort von Handoko, die sich damit befasst.

Verwendung von LAT- vs. PORT-Registern

Sie rufen Ihre Funktion so auf: Send1byte(getMatrixX(LATA)). Ich nehme an, Sie möchten den aktuellen Status der Eingabetasten abrufen und an diese Funktion senden.

Dies funktioniert nicht, Sie müssen stattdessen aus dem PORTA-Register lesen. Der richtige Code würde lauten Send1byte(getMatrixX(PORTA)).

Warum ist das? Im Datenblatt gibt es eine kurze Erklärung:

Das Lesen des PORTA-Registers liest den Status der Stifte; Wenn Sie darauf schreiben, wird in den Port-Latch geschrieben.

Und ein hilfreiches Bild:

Abbildung 10-1 PORT vs. LAT

Die interne Datenleitung, die beim Lesen des PORT-Bits (unten links, vom grünen Block) verwendet wird, ist mit dem Eingangspuffer verbunden, der direkt vom I/O-Pin kommt. Im Gegensatz dazu liest die Datenleitung, die beim Lesen des LAT-Bits verwendet wird (oben links, verbunden mit dem roten Block), nur den Status des Datenlatchs. Es ist nicht mit dem Eingang verbunden.

Beachten Sie, dass die SCK/DATA/SCL-Definitionen funktionieren sollten (das Schreiben in das PORT-Bit setzt den LATch), aber ich behalte normalerweise alle Schreibvorgänge im LATch, außer wo dies unmöglich ist (z. B. bidirektionale Busse).

Konfiguration analoger Funktionen

Sie müssen die analogen Funktionen deaktivieren, die auf PORTA-Pins gemultiplext werden. Siehe diesen Hinweis aus dem Datenblatt:

Bei einem Power-On-Reset werden RA5 und RA3:RA0 als analoge Eingänge konfiguriert und als „0“ gelesen. (Abschnitt 10, Seite 113)

Außerdem muss die Komparatorfunktion deaktiviert werden. Um alle PORTA-Pins auf digitale Eingänge einzustellen, siehe Register 21-2 (ADCON1) im Datenblatt. Sie könnten versuchen:

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

Wenn Sie dies nicht tun, erhalten Sie niemals die Eingabedaten von Ihren Schaltern, es sei denn, der Proteus-Simulator macht ungewöhnliche Dinge.

Vereinfachen von getMatrixX()

Sie können Ihre getMatrixX()-Funktion auf verschiedene Weise vereinfachen, je nachdem, ob Sie sich für Code oder Datenraum interessieren. Hier ist eine, die eine Tabellensuche verwendet (ungetestet):

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];
}

Es wäre einfach, dasselbe mit einer Verschiebung und etwas Logik zu tun und die Nachschlagetabelle zu vermeiden:

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

  return 0xFF ^ (0x80 >> in_X);
}
Super Antwort David, es hat funktioniert, es hat wirklich funktioniert! Die analoge Funktion ist das Problem, deine LAT-Erklärung und Nachschlagetabelle hilft mir auch sehr, habe es bis jetzt nicht verstanden. Du rettest nur meinen Tag, wirst dir eine Stimme geben, wenn ich genug Ansehen habe
Schön, dass es geholfen hat. Sehen Sie sich immer den Abschnitt im Datenblatt mit dem Titel „SUMMARY OF REGISTERS ASSOCIATED WITH PORTA“ an, zum Beispiel Tabelle 10-2 für den PIC 18F4550. Dies kann sehr hilfreich sein, um andere Funktionen aufzuspüren, die deaktiviert werden müssen.

Zunächst müssen Sie Ihre Ein- und Ausgabe richtig konfigurieren.

Sie haben verwendet TRISA = 1;, was bedeutet, dass nur RA0 ein INPUT ist. Bitte ändern Sie dies auf TRISA = 0b00000111;oder TRISA = 0x07;um alle 3 Tasten als INPUT zu konfigurieren.

Gleiches gilt für TRISB. Ändern Sie diesen Wert in 0x00000111 oder 0x07.

Wie Peter erwähnt hat, ändern Sie alle Ihre Fälle auf dem Schalter zu:

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

Außerdem sehe ich nicht einmal, wo Sie geschrieben haben, was die MCU tun muss, wenn eine Taste gedrückt wird?

+1 für das Bitmusterproblem. Das heißt, bitte bearbeiten Sie Ihre Antwort - Pause; ist bei Rückgabe überflüssig; ist im Fall vorhanden: Aussage.
danke für die Antwort, ich habe TRISA = 0xFF und 0x07 bereits ausprobiert, es funktioniert nicht, außerdem hatte ich, wie ich kommentiere, bereits eine Rückgabe, es hat mir einen Wert zurückgegeben und die Funktion verlassen, also glaube ich nicht, dass ich Pausen brauche . Über die Schaltflächen wollte ich nur den Wert davon erhalten, also habe ich die LATA in die getMatrixX-Funktion eingefügt, wie Sie sehen können (Proteus erlaubt mir, die Schaltfläche gedrückt oder nicht gedrückt zu halten).
Auf den erweiterten PICs sollten Sie von einem PORT lesen und in einen LATch schreiben.
@ David Das ist genau der Punkt, den ich machen wollte. Ich kenne mich mit PICs nicht aus, aber LATCH soll richtig ausgegeben werden? Kann man daraus überhaupt lesen?
Sie können aus dem LATx-Register lesen, aber Sie erhalten nur den Wert, der für das Ausgangslatch eingestellt wurde. Wenn ein Pin auf Eingabe im TRISx-Register eingestellt ist, dann ist der Wert in PORTx das Richtige, um für Eingaben gelesen zu werden.
danke für deinen Vorschlag, David, ich habe es gerade versucht und immer noch keine Anzeichen dafür, dass es funktioniert :( Ich habe das Oszilloskop beobachtet, imageshack.com/a/img837/7949/ci8a.png , das Signal von Q0 von 74HC595 (4. Zeile) scheint nie zu sein ändern, wenn ich die Tastenzustände ändere