Hallo, ich habe mir ein kleines Assembler und C++ - Programm geschrieben, mit dem ich Zahlen in der Größe eines Bytes vom PC über die parallele Schnittstelle in den Mikrocontroller übertragen kann. Das C++ - Programm ist eine Konsolenanwendung, bestehend aus „DataExchange.h“ und „DataExchange.cpp“, die ich mit Visual C++ compiliert habe. Die Assembler Datei heißt PCtoMC.asm Die über eingelesene Zahl wird auf LEDs über PORT B ausgegeben. Über PORT D wird die bisher eingegebene Zahl ausgegeben. Im Prinzip funktioniert das Zusammenspiel recht gut. Allerdings wenn vom PC eine Zahl größer 224 gesendet wurde und danach eine Zahl unter 32 (z.B. 8) ausgegeben werden soll wird vom MC Null ausgegeben. Beim 2. Versuch ist alles OK. Mein Eindruck ist, daß mit der Speicherverwaltung des MC etwas nicht stimmt, kann aber keinen Fehler finden. Die Verzweigungen sind vielleicht etwas unelegant programmiert, aber ich habe versucht mit möglichst wenig RJMP-Befehlen auszukommen. Vielleicht findet einer von Euch den Fehler Carsten C++ Dateien : Header-Datei „DataExchange.h“ /*Programm zur Eingabe bzw. Übernahme von 8Bit-Zahlen vom Mikrocontroller (MC) zum PC und umgekehrt. Das MSB-Bit (Bit 7) wird zuerst übertragen -> Belegung der Leitungen beim Senden der Daten vom PC zum MC Eingabeleitungen vom PC: X0: Datenleitung (Data0) X1: Taktsignal, das erste Bit wird mit HIGH-Pegel gesendet (Data1) X2: Byte korrekt gesendet (Data3) X3: Empfangsbereitschaft auslösen durch HIGH-Pegel (Data2) Empfangsleitung zum PC: X4: Datenleitung (ERROR) X5: Taktsignal (SELECT) X6: Byte erfolgreich empfangen (PAPER EMPTY) X7: Mikrocontroller ist empfangsbereit (ACKNOWLEDGE) */ #include <iostream.h> #include <stdlib.h> #include <conio.h> #include <string.h> #include <stdio.h> #include <time.h> #include <windows.h> //Für Sleep-Funktion //******************************************************************* class DataExchange //******************************************************************* { public: //Schnittstellenfunktionen //Verbindung zum Mikrocontroller herstellen int ConnectToMC(void); //Übernahme der an den MC zu sendenden Daten int DataToSend(int DataToMC); //Ausgabe der vom MC eingelesenen Daten int DataReadFromMC(void); //Verbindung zum Mikrocontroller beenden void DisconnectMC(void); DataExchange(); ~DataExchange(); private: //Sende- und Empfangsfunktionen int SendDataToMC(void); //Sendevorgang einleiten //Kontrollfunktionen //Prüfen Antworten MC beim Senden Daten PC an MC int ControlSendToMC(unsigned int Flag); //Prüfen Antworten MC beim Einlesen Daten vom MC an PC int ControlReadFromMC(unsigned int Flag); //allgemeine "Konstanten" int PORT; //LPT1 int HIGH, LOW; //Spannungspegel //Konstanten für Meldungen PC an MC int CONNECT; //Sendenbereitschaft auf DATA2 //Konstanten für Meldung MC an PC int MCREADY; //Bereitschaft MC auf Acknowledge int MCBYTEOK; //MC hat Byte korrekt empfangen/gesendet (PaperEmpty) int PCBYTEOK; //PC hat Byte korrekt empfangen/gesendet int MCTAKT; //Taktsignal auf Select int MCDATA; //Datensignal auf Error //Fehlermeldungen int NO; //Kein Fehler aufgetreten int YES; //Variablen int ByteIO, BitIO; //Übertragenes Bit bzw. Byte int Fehler; //Fehler bei Übertragung? int MsgToMC, MsgFromMC; //Übertragung zum und vom Mikrocontroller int TaktMC, TaktPC; //Taktsignal und übertragenes Bit time_t t_start, t_aktuell; }; //------------------------------------------------------------------- //******************************************************************* DataExchange::DataExchange() //Konstruktor //******************************************************************* { //Initialisierung der Konstanten PORT = 0x378; HIGH = 1; LOW = 0; NO = 0; YES = 1; CONNECT = 8; //Data3 PCBYTEOK = 4; //Data2 MCREADY = 64; //ACKNOWLEDGE MCBYTEOK = 32; //PAPER EMPTY MCTAKT = 16; //SELECT MCDATA = 8; //ERROR nicht benutzt return; } //------------------------------------------------------------------- //******************************************************************* DataExchange::~DataExchange() //Destruktor //******************************************************************* { _outp(PORT, 0); return; } //------------------------------------------------------------------- //******************************************************************* int DataExchange::DataToSend(int DataToMC) //******************************************************************* { ByteIO = DataToMC; //Bitweises Senden der Daten Fehler = SendDataToMC(); return Fehler; } //------------------------------------------------------------------- //******************************************************************* int DataExchange::ConnectToMC(void) //******************************************************************* { MsgToMC = CONNECT; _outp(PORT, MsgToMC); time(&t_start); for(;;) { MsgFromMC = _inp(PORT+1); //MsgFromMC so umformen, daß an gesetzen Eingängen //eine "1" steht MsgFromMC = MsgFromMC ^ 128; MsgFromMC = MsgFromMC & 248; MsgFromMC = ~MsgFromMC; MsgFromMC = MsgFromMC - 7; if((MsgFromMC & MCREADY) == MCREADY) { Fehler = NO; break; } //Bei Zeitüberschreitung Fehlermeldung time(&t_aktuell); if((t_aktuell - t_start) > 3) { Fehler = YES; break; } } return Fehler; } //------------------------------------------------------------------- //******************************************************************* void DataExchange::DisconnectMC(void) //******************************************************************* { _outp(PORT, 0); return; } //------------------------------------------------------------------- //******************************************************************* int DataExchange::SendDataToMC(void) //******************************************************************* { //ByteOut wird Bitweise ausgegeben //Maske zum Bitweisen senden von ByteOut unsigned int Mask, Flag; Mask = 128; //Zur Prüfung auf MSB-Bit Bit7 for(Flag = 1; Flag < 9; Flag++) { if(Flag % 2) TaktPC = HIGH; else TaktPC = LOW; if((ByteIO & Mask) == 128) BitIO = HIGH; else BitIO = LOW; //Ausgabe des Bits, DATA0 = Bit, DATA1 = Takt, DATA2 = Sendebereit MsgToMC = BitIO + 2 * TaktPC + CONNECT; _outp(PORT, MsgToMC); //Sleep(500); //Prüfen, ob Bit oder Byte angekommen ist Fehler = ControlSendToMC(Flag); if(Fehler != NO) break; //ByteOut nach links shiften ByteIO = ByteIO << 1; } return Fehler; } //------------------------------------------------------------------- //******************************************************************* int DataExchange::DataReadFromMC(void) //******************************************************************* { return ByteIO; } //------------------------------------------------------------------- //******************************************************************* int DataExchange::ControlSendToMC(unsigned int Flag) //******************************************************************* { time(&t_start); for(;;) { MsgFromMC = _inp(PORT+1); //MsgFromMC so umformen, daß an gesetzen Eingängen //eine "1" steht MsgFromMC = MsgFromMC ^ 128; MsgFromMC = MsgFromMC & 248; MsgFromMC = ~MsgFromMC; MsgFromMC = MsgFromMC - 7; //Feststellen des Taktes vom Mikrocontroller if((MsgFromMC & MCTAKT) == MCTAKT) TaktMC = HIGH; else TaktMC = LOW; //Ist das Bit erfolgreich angekommen, muß der TaktMC //wechseln und gleich dem TaktPC werden. if((Flag < 8) & (TaktMC == TaktPC)) { Fehler = NO; break; } //Prüfen, ob Byte vom Mikrocontroller vollständig eingelesen wurde //Falls ja erfolgt Rückmeldung an MC if((Flag == 8) & ((MsgFromMC & MCBYTEOK) == MCBYTEOK)) { Fehler = NO; MsgToMC = PCBYTEOK + CONNECT; _outp(PORT, MsgToMC); Sleep(50); //Weiter Sendebereitschaft PC anzeigen MsgToMC = CONNECT; _outp(PORT, MsgToMC); break; } //Bei Zeitüberschreitung Fehlermeldung time(&t_aktuell); if(t_aktuell - t_start > 5) { Fehler = YES; cout << "\nFehler bei Bit = " << Flag << "\n"; break; } } return Fehler; } //------------------------------------------------------------------- cpp-Datei „DataExchange.cpp“: #include "DataExchange.h" //******************************************************************* void main(void) //******************************************************************* { int Fehler, ByteOut, Flag; DataExchange DatenSenden; _outp(0x378, 0); cout << "\nDaten senden (1 = senden)? = "; cin >> Flag; if(Flag == 1) { Fehler = DatenSenden.ConnectToMC(); if(Fehler == 1) { cout << "\nKeine Verbindung zum Mikrocontroller!\n"; DatenSenden.DisconnectMC(); cout << "\nProgramm beendet.\n"; return; } } if(Flag == 1) { for(;;) { cout << "\nBei Zahlen > 255 und < 0 erfolgt Programmabbruch!\n"; cout << "\n\nEingabe Zahl < 256 = "; cin >> ByteOut; if((ByteOut > 255) || (ByteOut < 0)) break; Fehler = DatenSenden.DataToSend(ByteOut); if (Fehler == 1) { cout << "\nFehler bei Datenuebertragung!\n"; DatenSenden.DisconnectMC(); cout << "\nProgramm beendet.\n"; return; } } } DatenSenden.DisconnectMC(); cout << "\nProgramm beendet.\n"; return; }; //------------------------------------------------------------------- Assembler-Datei für Mikrocontroller „PCtoMC.asm“: ;Programm zur Eingabe von 8Bit-Zahlen vom PC zum Mikrocontroller ;Das MSB-Bit wird zuerst eingelesen ;Sendeleitungen vom PC zum Mikrocontroller: ;X0: Datenleitung (Data0) ;X1: Taktsignal (Data1). Das erste Bit wird mit HIGH-Pegel gesendet. Bei den ; folgenden Daten wird das Taktsignal jeweils zwischen HIGH und ; LOW umgeschaltet. Auch im LOW-Takt wird ein Bit gesendet! ;X2: Byte vollständig gesendet (Data2) ;X3: Empfangsbereitschaft beim MC auslösen durch HIGH-Pegel. Dieser bleibt ; ständig auf HIGH (Data3) ;Sendeleitung vom Mikrocntroller zum PC: ;X4: Datenleitung (ERROR), noch nicht benutzt ;X5: Taktsignal des Mikrocontrollers, zu Beginn der Sendebereitschaft ; auf LOW. Dient zur Synchronisation mit PC (SELECT) ;X6: Byte vollständig empfangen (PAPEREMPTY) ;X7: Mikrocontroller ist empfangsbereit. Bleibt ständig auf HIGH (ACKNOWLEDGE) .include "4414def.inc" ;Benötigte Register: .def Temp = R16 .def Count = R17 .def MsgPC = R18 ;Datensatz des aktuellen PC-Taktes .def MsgPCOld = R19 ;Datensatz des vorherigenn PC-Taktes .def MsgMC = R20 ;Datensatz des aktuellen MC-Taktes .def ByteIO = R22 ;aktuell empfangenes Byte ;Benötigte Konstanten .equ PCExch = 0b00001000 ;PC ist sendebereit .equ MCExch = 0b10000000 ;MC ist empfangsbereit .equ MCTakt = 0b00100000 ;Takt MC ist HIGH .equ PCTakt = 0b00000010 ;Takt PC HIGH .equ PCByteOK = 0b00000100 ;Byte vom PC erfolgreich gesendet .equ MCByteOK = 0b01000000 ;Byte vom MC erfolgreich empfangen .equ DataPC = 0b00000001 ; Datensignal .equ BYTE = 0b00001000 ;Länge des Bytes = 8 Bit ;*********************************************************************** ******** ;Initialisierung Initial: ;Port A wird als Ein- und Ausgang für die PC-Kommunikation genutzt ;PINs 0-3 als Eingänge, PINs 4-8 als Ausgänge des Controllers LDI Temp, 0b11110000 OUT DDRA, Temp ;PORT B als Ausgang für Ausgabe des Bytes LDI Temp, 0xFF OUT DDRB, Temp ;PORT D als Ausgang OUT DDRD, Temp ;Alle Ports auf Null setzen LDI Temp, 0x00 OUT PORTA, Temp OUT PORTB, Temp OUT PORTD, Temp ;----------------------------------------------------------------------- -------- ;*********************************************************************** ******** ;Hauptprogramm MAIN: ;Abfrage des I/O-Ports im Polling-mode IN MsgPC, PINA ;Prüfen, ob Bit 3 gesetzt ist ANDI MsgPC, PCExch CPI MsgPC, PCExch BRNE Main ;PC Sendebereitschaft anzeigen LDI MsgMC, MCExch OUT PORTA, MsgMC ;Rücksetzen Register LDI MsgPC, 0x00 LDI MsgPCOld, 0x00 LDI ByteIO, 0x00 LDI Count, 0x00 LDI Temp, 0x00 LDI MsgMC, 0x00 GetBit: ;Bitweises Einlesen IN MsgPC, PINA ;Sendebereitschaft PC prüfen, prüfen, ob Bit 3 gesetzt ist MOV Temp, MsgPC ANDI Temp, PCExch CPI Temp, PCExch BRNE Main ;Überprüfung Taktsignal durch Vergleich MsgPCOld/MsgPC ;Zuerst mit XOR auf ungleiche Pegel prüfen MOV Temp, MsgPCOld EOR Temp, MsgPC ;Wenn Bit 1 "1" ist war das Taktsignal in MsgFromPCOld ungleich ;MsgFromPCNew und ein neues Bit liegt vor ANDI Temp, PCTakt CPI Temp, PCTakt BRNE GetBit ;Einlesen des Bits, dazu ByteIO nach links schieben LSL ByteIO CLC ;Carry-Flag sicherheitshalber löschen INC Count MOV Temp, MsgPC ANDI Temp, DataPC ADD ByteIO, Temp OUT PORTD, ByteIO ;Ausgabe Zwischenergebnis ;Sichern MsgPC MOV MsgPCOld, MsgPC ;Rückmeldung MC an PC durch Taktwechsel ;Alle anderen Bits löschen ANDI MsgMC, MCTakt LDI Temp, MCTakt EOR MsgMC, Temp ;Bit 7 für Sendebereitschaft erhalten LDI Temp, MCExch ADD MsgMC, Temp OUT PORTA, MsgMC CPI Count, BYTE BRNE GetBit ;Byte vollständig eingelesen, Meldung an PC. Sendebereitschaft bleibt erhalten LDI MsgMC, MCExch LDI Temp, MCByteOK ADD MsgMC, Temp OUT PORTA, MsgMC PCOK: ;Meldung PC abwarten In MsgPC, PINA ANDI MsgPC, PCByteOK CPI MsgPC, PCByteOK BRNE PCOK ;Byte ausgeben OUT PORTB, ByteIO RJMP Main ;----------------------------------------------------------------------- --------
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.