Somit hast Du Deinen Ansatz sogar noch perfektioniert. Ich wollte Dir nicht "ans bein pinkeln", sondern lediglich meine Bedenken äußern. Und Du hast sie wunderbar umschifft. Gratuliere!
Und diesen Ausgang schaltet man nach low (GND) damit man die internen Pullups nutzen kann.Oder Einfach alle auf Eingang schalten, mit PullUp, und nur eine Reihe auf Ausgang?
Ich hab den Code schnell mal aus dem Kopf zusammengezimmert.Code:// Port C wäre der Tastaturport. // Portc.6 = Spalte 1 // Portc.5 = Spalte 2 // Portc.4 = Spalte 3 // Initialisierung ... PORTC=0b01111111; DDRC=0b00000000; ... // Tastaturabfrage: unsigned char read_tast(void) { taste1=15; // Tastenparameter vorbelegen -> keine Taste gedrückt taste2=15; PORTC.6=0; // Spalte 1 auf low DDRC.6=1; uc_tastabfr1=PINC&0b00001111; // Zeilen 1...4 ausfiltern switch (uc_tastabfr1) { case 0b00001110: taste1=1; break; case 0b00001101: taste1=2; break; case 0b00001011: taste1=3; break; case 0b00000111: taste1=4; break; default: }; PORTC.6=1; // Spalte wieder auf high DDRC.6=0; PORTC.5=0; // Spalte auf low DDRC.5=1; uc_tastabfr1=PINC&0b00001111; // Zeilen 1...4 ausfiltern switch (uc_tastabfr1) { case 0b00001110: taste1=5; break; case 0b00001101: taste1=6; break; case 0b00001011: taste1=7; break; case 0b00000111: taste1=8; break; default: }; PORTC.5=1; // Spalte wieder auf high DDRC.5=0; PORTC.4=0; // Spalte auf low DDRC.4=1; uc_tastabfr1=PINC&0b00001111; // Zeilen 1...4 ausfiltern switch (uc_tastabfr1) { case 0b00001110: taste1=9; break; case 0b00001101: taste1=10; break; case 0b00001011: taste1=11; break; case 0b00000111: taste1=12; break; default: }; PORTC.4=1; // Spalte wieder auf high DDRC.4=0; delay_ms(10); // 2te Tastaturabfrage: PORTC.6=0; // Spalte 1 auf low DDRC.6=1; uc_tastabfr1=PINC&0b00001111; // Zeilen 1...4 ausfiltern switch (uc_tastabfr1) { case 0b00001110: taste2=1; break; case 0b00001101: taste2=2; break; case 0b00001011: taste2=3; break; case 0b00000111: taste2=1; break; default: }; PORTC.6=1; // Spalte wieder auf high DDRC.6=0; PORTC.5=0; // Spalte auf low DDRC.5=1; uc_tastabfr1=PINC&0b00001111; // Zeilen 1...4 ausfiltern switch (uc_tastabfr1) { case 0b00001110: taste2=5; break; case 0b00001101: taste2=6; break; case 0b00001011: taste2=7; break; case 0b00000111: taste2=8; break; default: }; PORTC.5=1; // Spalte wieder auf high DDRC.5=0; PORTC.4=0; // Spalte auf low DDRC.4=1; uc_tastabfr1=PINC&0b00001111; // Zeilen 1...4 ausfiltern switch (uc_tastabfr1) { case 0b00001110: taste2=9; break; case 0b00001101: taste2=10; break; case 0b00001011: taste2=11; break; case 0b00000111: taste2=12; break; default: }; PORTC.4=1; // Spalte wieder auf high DDRC.4=0; if(taste1==taste2) { return (taste1); } else { return(255); };
Es kann also sein das noch ein paar Fehler drin sind.
Ich meine aber das Prinzip ist erkennbar und somit für Dich umzusetzen.
Somit hast Du Deinen Ansatz sogar noch perfektioniert. Ich wollte Dir nicht "ans bein pinkeln", sondern lediglich meine Bedenken äußern. Und Du hast sie wunderbar umschifft. Gratuliere!
So hab ich das auch nicht aufgefasst.Ich wollte Dir nicht "ans bein pinkeln", ....
Ich hab das mit dem Umschalten auf "LOW" bei meinem Projekt, ohne die Umschaltung der DDR Register, tatsächlich gemacht und bin froh, das ich da jetzt auch eine potentielle Fehlerquelle ausmerzen kann. =D>
Aber es ist so wie ich schon öfter mal sagte:
"Man lernt mit jedem Beitrag den man hier verfasst / beantwortet selber was dazu".
Hallo Roboter Genie,
vielen Dank für deine Bemühungen....
Werde es gleich mal versuchen
Danke nochmals
PS: Gibt's da nicht schon fertige Header Datei. Denn die Sprache C ist ja weit verbreitet. Für die LCD, Delay..., I/O's gibt es sie ja auch?
Möglich, ich würde mir das Prog aber an Deiner Stelle selber schreiben.Gibt's da nicht schon fertige Header Datei.
Erstens ist es nicht sonderlich kompliziert.
Zweitens kannst Du fast jeden beliebigen Controllerpin für die Funktionen auswählen.
Drittens können auch noch andere Funktionen ( z.B. eine A/D Wandlerabfrage ) in den Quellcode mit eingefügt werden.
Viertens hast Du volle Kontrolle über die Funktionalität des Quellcodes.
Das ist bei fertigen Library's nicht möglich.
...Fünftens ist eine Einarbeitung in die Benutzung einer Library manchmal nicht ohne.
...Sechstens haben auch Libs Fehler, die Dir viel Frust bringen können.
...Siebtens ist eine Library i.d.R. für allgemeine Lösungen und/oder viele verschiedene Hardware gedacht, so dass Du für Deinen Anwendungsfall mglw. zu viel Code mit reinbekommst.
Hallo....!
Wie fügt man eigentlich Assembler-Befehle in einem C- Code ein?
Denn ich möchte einen Wert, den ich mittels Tastendruck ermittle, in ein allgemeines Regíster, zB: r16 (bzw. ins EE-PROM) bringen.
wie sieht das in C aus
wie in Assembler aus (unter C)
Ich versuche es im AVR-Studion (WinAVR)
danke für deine (eure) Hilfe
papua
Bei winavr weiß ich nicht wie inline Assembler geht.
Bei CodeVision AVR siehts so aus
// Ein einzelner Befehl
#asm("NOP");
// Mehrere Zeilen inline Assembler
#asm
NOP
SEI
LDI R16,0x12
#endasm
Wie's geht sollte eigentlich im Benutzerhandbuch stehen.
Die Werte, die die Tastaturroutine ermittelt geb ich immer per RETURN zurück.
Also am Ende der Funktion steht die Anweisung
return(uc_taste);
Somit kriegt das aufrufende Programm die Tastaturwerte der Routine zurück geliefert und kann diese in einer eigenen Variable weiter verarbeiten.
Ich mach auch meistens in die aufrufende Routine eine zweite Variable mit dem Namen uc_oldtast auf.
Die beinhaltet den Wert der vorherigen Tastenabfrage.
Nur wenn sich daran was ändert wird eine Auswerte- Steuer- oder sonstige Routine verarbeitet.
Wenn die Ausführungsroutine verarbeitet wurde wird der aktuelle Tastenzustand ( uc_tast ) in die Variable uc_oldtast übernommen und somit verhindert, das die Auswerteroutine ständig anläuft.
also man kann das auch direkt machen indem man
2 Reihen blockiert und dann den pin statusregister auslist
Code:uint8_t taste_lesen() { uint8_t keys = 0; char wert ='-'; PORTD=0x03; _delay_us( 10 ); keys = PIND; if (keys == 115) wert ='3'; if (keys == 179) wert ='6'; if (keys == 211) wert ='9'; if (keys == 227) wert ='#'; PORTD=0x05; _delay_us( 10 ); keys = PIND; if (keys == 117) wert ='2'; if (keys == 181) wert ='5'; if (keys == 213) wert ='8'; if (keys == 229) wert ='0'; PORTD=0x06; _delay_us( 10 ); keys = PIND; if (keys == 118) wert ='1'; if (keys == 182) wert ='4'; if (keys == 214) wert ='7'; if (keys == 230) wert ='*'; keys =wert; _delay_us( 10 ); return keys; }
@magic33
Das ist im Prinzip das gleiche wie in meinem Quellcode.
Wobei bei Deiner Variante wieder das Kurzschlußproblem bei 2 gleichzeitig gedrückten Tasten auftritt, wenn es nicht durch Hardwaremassnahmen verhindert wird.
Mit dem direkten Zugriff auf die Register musst Du vorsichtig sein.Denn ich möchte einen Wert, den ich mittels Tastendruck ermittle, in ein allgemeines Regíster, zB: r16 (bzw. ins EE-PROM) bringen.
Die meisten Register werden durch den C-Compiler belegt und dürfen nicht so ohne weiteres verändert werden.
Auskunft sollte auch hier das Handbuch des Compilers geben.
Der Zugriff aufs EEPROM wird in Codevision schon bei der Initialisierung der Variable gemacht.
eeprom unsigned int ui_test=0;
ui_test=ui_variable; // Schreibt den Wert von ui_variable ins eeprom.
Bei Win AVR hilft nur nachschauen.
Mit dem Beschreiben des EEPROM's solltest Du aber sehr sparsam umgehen.
1. Dauert es ziemlich lange.
2. Ist nur eine beschränkte Anzahl von Schreibvorgängen möglich. Bei den neueren Typen sind es 100.000 soweit ich weiß. Das steht aber im jeweiligen Datenblatt.
Lesezeichen