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.
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.
Bitte beachten Sie die Antwort von Handoko, die sich damit befasst.
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:
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).
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.
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);
}
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?
Peter Bennett
Benutzer3669754
Dzarda
Adam Kopf
Benutzer3669754