Ich versuche gerade verzweifelt Taster an einem Port einzulesen und an
einem anderen Port 1:1 wieder auszugeben.
Der Taster soll als Schalter fungieren.
Erstes drücken -> LED ein, zweites Drücken -> LED aus.
Also XOR.
hier der Code:
Theoretisch müsste es so funktionieren.
Habe es zum testen auf einem STK500. Hat aber nicht funktioniert. Erst
als ich jeden zweiten Parameter negiert habe.
Ich weiß zwar, dass die LED negativ angesteuert werden, aber was
interessiert es das interne Register? Verstehe ich nicht so ganz.
Aber gut.
Nachdem ich nun den nächsten Pin abfrage, funktioniert der Erste zwar,
wenn ich den zweiten Taster drücke, setzt es Pin 1 zurück.
Also Ta0 = 0x01, Ta1 = 0x02 und beide zusammen sollten dann 0x03
ergeben. Macht es aber nicht.
Michael D. schrieb:> Was genau mache ich falsch?
Primär hast du den Fehler gemacht, unlesbaren Code zu schreiben. Weil
man (du und ich) da nicht mehr durch blickt, sieht man den Fehler nicht.
Schreibe dir Funktionen zur Abfrage der Taster und ansteuern der
Ausgänge, mit sprechenden Namen. Beispiel:
1
#include<avr/io.h>
2
#include<stdbool.h>
3
4
boolstart_button_pressed()
5
{
6
return(PINA&(1<<PA0))==0;
7
}
8
9
boolstop_button_pressed()
10
{
11
return(PINA&(1<<PA1))==0;
12
}
13
14
15
voidstatus_led_on()
16
{
17
PORTB&=~(1<<PB0);
18
}
19
20
voidstatus_led_off()
21
{
22
PORTB|=(1<<PB0);
23
}
24
25
intmain()
26
{
27
for(;;)// forever
28
{
29
if(start_button_pressed())
30
{
31
status_led_on();
32
}
33
elseif(stop_button_pressed())
34
{
35
status_led_off();
36
}
37
}
38
}
Schreibe dein Programm erst einmal so um, dann sehen wir weiter, falls
dir die Fehler nicht schon selbst ins Auge springen.
Und keine Sorgen bezüglich der Performance. Der Compiler ist so schlau,
diese Funktionsaufrufe weg zu optimieren. Das Programm wird dadurch kein
bisschen größer.
> {PORTB = (1<<PB0);}
Da fehlt ein Zeichen, du wolltest |= schreiben.
Bitte poste den GANZEN CODE!
Und ein Schaltplan bitte.
Glaskugelei und raten wie du die Register geschrieben hast und wie es
verdrahtet ist ist nicht soo spaßig
Stefan ⛄ F. schrieb:>> {PORTB &= ~(1<<PB1);}>> else>> {PORTB &= ~(1<<PB1);}>> In der unteren Zeile wolltest du vermutlich "PORTB |= (1<<PB1)"> schreiben.
danke für den Hinweis, ist beim kopieren passiert.
Magier schrieb:> Bitte poste den GANZEN CODE!> Und ein Schaltplan bitte.> Glaskugelei und raten wie du die Register geschrieben hast und wie es> verdrahtet ist ist nicht soo spaßig
Ok, weiß nicht ob das was bringt, wollte mich erstmal nur auf das
Wesentliche beschränken.
Aufgebaut ist es auf STK500, Atmega8515, LED an PORTB, Taster an PORTA
also wirklich viel Verdrahtung gibt es nicht.
Übrigens, der Schaltplan ist noch nicht fertig und spiegelt nicht 100%
den aktuellen Zustand wieder, sollte aber für den Anfang reichen.
und der code.
glaube aber, dass es jetzt noch verwirrender wird.
Am einfachsten geht das, wenn man das Entprellen und Flanke erkennen in
eine separate Lib auslagert, z.B.:
Beitrag "Universelle Tastenabfrage"
Dann reduziert sich der eigentliche Code zu:
Michael D. schrieb:> Erstes drücken -> LED ein, zweites Drücken -> LED aus.
Dazu mußt Du die Flanke erkennen, d.h. Du brauchst einen
Zwischenspeicher.
Nur eine logische Verknüpfung reicht daher nicht.
Michael D. schrieb:> Theoretisch müsste es so funktionieren.
Nö.
Erstmal danke für die Hilfe soweit.
Sehe, ich muss die Abfrage nochmal komplett überdenken, da einiges mehr
nicht zusammenpasst. Auch die If-Abfrage ohne den Gegenwert ==. Wundert
mich im Nachhinein, dass es überhaupt funktioniert.
Meine Idee soweit:
Funktion Taster
Fragt ab einzelnen Taster ab und entprellt diesen auch gleich.
Funktion Taster abfragen
Schleife, die nacheinander die 8 Taster abfragt, den Rückgabewert dann
in einem Array zwischenspeichert.
UND DANN ERST die Auswertung und Vergleiche. Das macht es auch
einfacher, später die weiteren Zwei Taster einzubinden.
Andere Frage zum Schaltungsentwurf selbst. Bei den Tastern. Keine
Ahnung, welche Idee ich da hatte aber im Nachhinein sehe ich es so, dass
ich jetzt eine Mischform zwischen Active High/Low habe und während des
Zeitpunktes der Umschaltung undefiniert, da keine Pullups. Glaube es ist
sinnvoller nur den Schließer zu verwenden und die Masse zu schalten,
dann kann ich die internen Pullups verwenden. Oder spricht da was
dagegen? Der Rest sollte eigentlich soweit passen. Der 8515 hat keinen
I2C-Bus? Jedenfalls hab ich im Datenblatt nichts darüber gefunden.
Michael D. schrieb:> . Bei den Tastern. Keine Ahnung, welche Idee ich da hatte aber im> Nachhinein sehe ich es so, dass ich jetzt eine Mischform zwischen Active> High/Low habe und während des Zeitpunktes der Umschaltung undefiniert,> da keine Pullups.
Da wird nicht so viel passieren, so lange du nicht gaaaaannnnzzz langsam
umschaltest, oder arge Störungen unterwegs sind. Allerdings hättest du
dann wenigstens diese Widerstände nach 5V weglassen und die 5V wie den
GND direkt auf den Portpin schalten können... ;-)
> Glaube es ist sinnvoller nur den Schließer zu> verwenden und die Masse zu schalten, dann kann ich die internen Pullups> verwenden. Oder spricht da was dagegen?
Möglicherweise die Länge des Kabels zu den Schaltern.
> Funktion Taster abfragen> Schleife, die nacheinander die 8 Taster abfragt, den Rückgabewert dann> in einem Array zwischenspeichert.
Ich würde einfach das Pinregister in ein Byte einlesen, dann eigentlich
ist aus Hardwaresicht ein Byte auch schon ein "Array" (besser ein
Vektor) mit 8 Bits. Und dann hätte ich mit 1 einzigen Zugriff den
zeitgleichen Pegel sämtlicher Taster eingelesen.
Michael D. schrieb:> Andere Frage zum Schaltungsentwurf selbst. Bei den Tastern. Keine> Ahnung, welche Idee ich da hatte aber im Nachhinein sehe ich es so, dass> ich jetzt eine Mischform zwischen Active High/Low habe und während des> Zeitpunktes der Umschaltung undefiniert, da keine Pullups. Glaube es ist> sinnvoller nur den Schließer zu verwenden und die Masse zu schalten,> dann kann ich die internen Pullups verwenden.
Es wird so gehen, wie du es gezeichnet hast. Aber man braucht keinen
Umschalter, es reicht ein Taster gegen GND. Ein offener Taster wird mit
dem PU ja auf HIGH gehalten. Externe PUs sind durchaus sinnvoll, den die
internen sind relativ hochohmig, es geht aber damit auch.
Zu deiner Software kann ich dir ein Beispiel geben, das ich kürzlich für
einen Tiny26 geschrieben haben zur Freude meines Enkels und auch um die
Entprellroutine von Peter D. mal zu implementieren. (Teile daraus habe
ich aber nicht übernommen.)
Allerdings nur mit 7 LEDs und 8 Tasten, die 8. ist ein quasi Reset. Lag
auch an dem nicht nutzbaren PortB7 (Reset) vom Tiny26.
Da gäbe es drei Varianten:
- Buzzer Mode, der erste, der drückt sollte gewinnen, die andern werden
gesperrt. Leider passt das noch nicht ganz: bei passendem 'Gleichzeitig'
werden beide LEDs akiviert :-(
- Selection Mode: drückt man eine Taste, geht eine LED an; eine die
schon an war, geht aus.
- individuell: man kann alle LEDs durch die jeweilige Taste ein- und
ausschalten. Das ist wohl das, was du machen wolltest.
Ich bin kein SW-Profi, funktionieren tut es aber, verbessern kann man
sicherlich.
Also, ich hab in der Woche ein wenig weitergemacht, aber nicht alles,
was ich mir vorgenommen hatte geschafft.
Hab den Schaltplan fertig und etwas umgezeichnet. Habe die Taster zwar
jetzt mit Pull-Ups versehen, werde aber trotzdem erstmal die internen
verwenden. Nachträglich bestücken und eine Zeile im Programm ändern kann
ich immer noch. Somit bin ich flexibel.
Das Programm hab ich jetzt komplett umgeschrieben, so wie einige das
vorgeschlagen haben.
Ist noch nicht ganz fertig, aber funktioniert schon mal so weit.
Was noch fehlt, die weiteren 2 Taster einbinden. Aber das denke ich,
bekomme ich dann hin.
Hab die Entprell-Routine, die mir vorgeschlagen wurde, verwendet,
angepasst und eingefügt.
Wundert euch nicht, wenn die Ports/Adressen bei dem einen nicht passen.
Hab das erstmal auf einem Arduino mit Mega8 getestet, damit ich mir
meinen eigentliche Aufbau nicht kaputt mache.
Noch eine andere wichtige Frage. Habe vor, auch einen I2C-Bus zu
implementieren (irgendwann einmal, zumindest will ich das Hardware-mäßig
erstmal vorsehen) Ich verwende einen Atmega 8515. Im Datenblatt steht
nichts darüber. Ich gehe mal davon aus, dass ich das per Software
nachbilden muss. Nicht dass ich jetzt die falschen Pins dafür vorgesehen
habe oder irgendwas anderes nicht passen würde.
Und falls ich es noch nicht erwähnt haben sollte oder sich jemanden der
Sinn nicht ganz erschließt.
Ich will ein Eingabe-Board bauen, dass ich für Mikrocontroller/-Computer
verwenden kann. Einfach aus Spaß und zu Lernzwecken und damit ich nicht
immer alles auf Steckbrettern aufbauen muss sondern nur an den Port
anschließen brauche. Und auch multifunktional, damit ich nicht 10
verschiedene bauen muss.
Funktionen sollen sein:
- 8x einfacher Taster
- 8x Schalter (EIN/AUS) mit LED als Rückmeldung
- wie oben, zusätzlich mit Reset und Eingabe (Ausgabe am Port erst nach
nach Freigabe, danach sind Änderungen möglich, aber letzter Zustand
bleibt solange erhalten, bis ich erneut Eingabe betätige.)
Ungefähr so wie beim Altair wenn den jemand kennt. Keine Ahnung, ob ich
eine sinnvolle Anwendung dafür finde, fand die Idee aber ganz nett.
- Und das ganze soll auch über den I2C möglich sein. (Ist aber momentan
nicht wichtig/dringend)
Was ich nicht will, dass jemand für mich die ganze Arbeit macht. Will
das schon selber machen. Brauch nur gelegentliche Hilfestellung und
Tipps/Denkanstöße.
Michael D. schrieb:> Habe vor, auch einen I2C-Bus zu implementieren ...> Ich verwende einen Atmega 8515. Im Datenblatt steht nichts darüber.> Ich gehe mal davon aus, dass ich das per Software> nachbilden muss.
Der ATmega8515 hat kein I²C (TWI) Interface. Man kann die USI
Schnittstelle dazu verwenden, die ist aber eklig. Ich würde sie mir nur
antun, wenn es unbedingt sein muss. Der I²C Master lässt sich rein in
Software erhebliche einfacher implementieren.
An den Reset Pin könntest du noch einen Kondensator packen, damit er
zuverlässig nicht auf Radiowellen reagiert.
Zu dem Kondensator, den du vorgeschlagen hast. Finde ich für meine
Anwendung vielleicht etwas übertrieben, da ich noch nie Probleme damit
hatte und EMV bisher immer ignoriert hatte.
Habe mich dazu ein wenig eingelesen. Zwischen Reset und GND. Atmel
empfiehlt 100nF woran ich mich auch halten würde. In anderen Foren wird
zwischen 10-100nF aber auch 1-10uF Elkos diskutiert. Was wäre denn ein
guter Richtwert?
Nutze ich für den USI den UART oder ISP? So ganz klar ist mir das nicht,
da das Datenblatt dazu nichts sagt und eine wirklich aufschlussreiche
Erklärung habe ich bisher noch nicht gefunden.
Welche Pins soll ich dann dafür vorsehen. Habe bisher PD0/PD1.
Im Zweifel lasse ich es weg und bastle mir dann extern etwas zusammen.
Gibt es dafür sowas wie 8-Bit Schieberegister/Latch...bit BUS?
Habe auf die Schnelle sowas gefunden: MAX7328/MAX7329
Bin gerade am Layout erstellen, daher wäre diese Information ganz
nützlich.
Stefan ⛄ F. schrieb:> Der ATmega8515 hat kein I²C (TWI) Interface. Man kann die USI> Schnittstelle dazu verwenden
Der 8515 hat kein USI.
Single-Master I2C geht prima mit 2 beliebigen IO-Pins.
Peter D. schrieb:> Der 8515 hat kein USI.
Wo habe ich das bloss her? Ich muss mich verguckt haben. Das ist aber
schon seltsam: ein AVR ohne I²C und ohne USI.
Michael D. schrieb:> Gibt es dafür sowas wie 8-Bit Schieberegister/Latch
Klar. Reichlich.
Gängige einfache Kandidaten sind 74HC165 und 74HC594 (oder 595).
Peter D. schrieb:> Der 8515 hat kein USI.> Single-Master I2C geht prima mit 2 beliebigen IO-Pins.Stefan ⛄ F. schrieb:> Ich nehme 100nF.
Ok, bis jetzt alles richtig gemacht.
Stefan ⛄ F. schrieb:> Wo habe ich das bloss her? Ich muss mich verguckt haben. Das ist aber> schon seltsam: ein AVR ohne I²C und ohne USI.
Naja, der MCU ist ja auch schon uralt. Ich verwende den auch nur, weil
ich noch eine Handvoll von denen rumliegen habe und dieser für meine
Anwendung völlig ausreichend ist.
Stefan ⛄ F. schrieb:> Michael D. schrieb:>> Gibt es dafür sowas wie 8-Bit Schieberegister/Latch>> Klar. Reichlich.>> Gängige einfache Kandidaten sind 74HC165 und 74HC594 (oder 595).
Das sind aber die normalen Modelle. Dachte eher an eines mit
TWI-Schnittstelle. So wie MAX7328/MAX7329, die ich zufällig gefunden
habe. Wenn ich das richtig lese (nur schnell überflogen) ist es genau
das, was ich brauche.
Aber wenn ich so wie Peter D. vorgeschlagen, 2 beliebige Pins verwenden
kann und das Ganze virtualisiert nachbilden kann, reicht es auch.
Ich habe das Layout soweit schon mal fertig.
Ja, ich weiß, es ist nicht perfekt. Aber denke, schon mal ein guter
Anfang.
Muss mich noch um die ein oder andere Ecke/Kurve kümmern.
Kann man das halbwegs so lassen, oder hab ich grobe Fehler dinnen?
Was könnte man besser machen?
Michael D. schrieb:> Das sind aber die normalen Modelle. Dachte eher an eines mit> TWI-Schnittstelle.
Ach so. Da sind meine Lieblinge PCF8574 und MCP23017. Die Chips von
Maxim können viel aber sind deswegen auch komplizierter anzuwenden und
teuer.
> Aber wenn ich so wie Peter D. vorgeschlagen, 2 beliebige Pins verwenden> kann und das Ganze virtualisiert nachbilden kann, reicht es auch.
Ich hatte noch nie Probleme mit Soft-I²C - im Gegenteil. Der Code ist
einfach und wenn man sowieso blockierend auf die Antwort wartet, hat man
keine großen Nachteile.
Die Filter, die eine echte I²C Schnittstelle hat, ist auf der Slave
Seite wichtiger.