Bits setzen mit Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Balu
User
Beiträge: 6
Registriert: Freitag 11. Februar 2011, 16:50

Hallo zusammen,

ich möchte mit einem Python-Programm einen GPIO-Port meines Rechners ansteuern. Dazu muss ich zuerst an Port 0x800 das 5. Bit High setzen. Nun weiß ich leider nicht wie ich einzelne Bits eines Ports setzen, bzw. beschreiben kann.
Hat damit zufällig jemand Erfahrung und kann mir evtl. weiterhelfen?

Schöne Grüße und ein schönes Wochenende

Flo
BlackJack

@Balu: Das sind deutlich zu wenig Informationen. Was ist das für ein System? Wie wird die gewünschte GPIO-Leitung da angesprochen? Beziehungsweise wie werden "Ports" dort angesprochen? Ohne mehr Details zu Hardware und Betriebssystem kann man da nichts sagen.
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Und wieder ein mal hätte sich diese Frage erübrigen können. :roll:
SCNR
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Py-Prog hat geschrieben:Und wieder ein mal hätte sich diese Frage erübrigen können. :roll:
SCNR
Inwiefern? Ich sehe das da Information fehlt, aber in sich ist die Frage doch total ok. Ich würde eher sagen dein Post dient keinem Zweck, außer "flamebait" vielleicht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Py-Prog
User
Beiträge: 673
Registriert: Dienstag 16. Februar 2010, 17:52
Wohnort: G:\ermany

Du hast mich auf eine Idee gebracht, man könnte auch eine "Anleitung" darüber schreiben was man alles in einen Beitrag schreiben muss: System, Python-Version, Traceback, ... . Das würde dann sogar die Felder im Profil unnötig machen. :D
Technik ist: wenn alles funktioniert und keiner weiß warum.
Wer Rechtschreibfehler findet darf sie behalten.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Py-Prog hat geschrieben:Du hast mich auf eine Idee gebracht, man könnte auch eine "Anleitung" darüber schreiben was man alles in einen Beitrag schreiben muss: System, Python-Version, Traceback, ... . Das würde dann sogar die Felder im Profil unnötig machen. :D
Das gibt es schon, ist sogar im Thread "Vor dem Posten lesen" im Allgemeinen Forum verlinkt ;-)
http://wiki.python.de/Forum/Regeln
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hyperion hat geschrieben:
Py-Prog hat geschrieben:Du hast mich auf eine Idee gebracht, man könnte auch eine "Anleitung" darüber schreiben was man alles in einen Beitrag schreiben muss: System, Python-Version, Traceback, ... . Das würde dann sogar die Felder im Profil unnötig machen. :D
Das gibt es schon, ist sogar im Thread "Vor dem Posten lesen" im Allgemeinen Forum verlinkt ;-)
http://wiki.python.de/Forum/Regeln
Klassischer Fall von *OWNED* :D
Balu
User
Beiträge: 6
Registriert: Freitag 11. Februar 2011, 16:50

ok, ok. Sorry hab das Freitag abend noch schnell zusammengeschrieben. ohne das durchzulesen... :K Tut mir leid... :roll:

Also ich arbeite mit Ubuntu 10.10, und möchte auf einem Nexcom Panel-PC APPC die GPIO-Ports ansprechen. Dazu steht im Handbuch folgendes:
I/O Base Address: 800h
Bit0: GPI 50
Bit1: GPI 51
Bit2: GPI 52
Bit3: GPI 53
Bit4: GPO 54
Bit5: GPO 55
Bit6: GPO 56
Bit7: GPO 57

1. Selsect GPIO group5 by setting I/O port 800h to 5h.
2 Read/Write GPIO data by I/O port 802h.
Um den Port zu testen hatte ich bereits an einem anderen Gerät, an dem ich den Schritt 1 weglassen konnte einfach das Beispielprogramm toggle.py, welches bei PortIO vorhanden ist benutzt. Dort werden alle Ausgänge im Takt von 3 Sekunden zwischen High und Low umgeschalten. Der Beispielcode ist folgender:

Code: Alles auswählen

#!/usr/bin/python
# .+
#
# .context    : PortIO
# .title      : Toggle parallel port lines
# .kind	      : command shell
# .author     : Fabrizio Pollastri <f.pollastri@inrim.it>
# .site	      : Torino - Italy
# .creation   :	13-Nov-2008
# .copyright  :	(c) 2008 Fabrizio Pollastri
# .license    : GNU General Public License (see below)
#
# This file is part of "PortIO, python low level I/O for Linux x86".
#
# PortIO is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# PortIO is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# .-

import sys, time, os
import portio

# check for root privileges
if os.getuid():
  print 'You need to be root! Exiting.'
  sys.exit()

# acquire permission for I/O on lp0
status = portio.ioperm(0x378, 1, 1)
if status:
  print 'ioperm:',os.strerror(status)
  sys.exit()

# toggle for ever the data lines of lp0
data = 0
while 1:
  lp0in = portio.inb(0x378)
  portio.outb(data,0x378) 
  print 'read %x from lp0, written %x to lp0' % (lp0in,data)
  data = ~data & 0xff
  time.sleep(3)

#### END
Im Beispiel ist der gewünschte Port zum schreiben der Ausgänge 0x378. Ändert man diesen auf 802 sollte das mit meinem Gerät funktionieren.
Nun würde ich eben gerne wissen, wie ich es hinbekomme, vorher eben noch das 5. Bit von Port 800 auf High setzen kann?

Leider hab ich bisher noch nicht wirklich viel Erfahrung mit Python, daher hoffe ich das mir hier jemand helfen kann.

Schöne Grüße
Flo
Zuletzt geändert von Anonymous am Montag 14. Februar 2011, 13:36, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@Balu: Bits manipuliert man mit den gängigen bitweisen Operatoren. Gezielt Bits setzen geht zum Beispiel mit einer Oder-Verknüpfung und der entsprechenden Bitmaske. Wenn Du also einen Wert `x` hast, kannst den Wert mit gesetztem 5. Bit mit ``x | 2**5`` ermitteln. Python benutzt syntaktisch die gleichen Operatoren wie C (und C#, Java, und viele andere).
Balu
User
Beiträge: 6
Registriert: Freitag 11. Februar 2011, 16:50

Sorry das ich so blöd frage, aber habe leider wirklich nicht viel Ahnung von dem ganzen...
wenn ich jetzt port 800 schreiben möchte, dann könnte ich doch theoretisch wie im Beispiel schreiben:

input = portio.inb(0x800)
mask= 0x16
data= (input|mask)
portio.outb(data,0x800)

Damit lese ich Port 800 aus, dann definiere ich meine Maske in HEX, wobei das 5. Bit HIgh ist und mache eine Oder-Verknüpfung. Zum SChluß schreibe ich dann an port 800 den Wert, der bei der Oder-Verknüpfung herauskam.
Wenn ich das so mache, bekomme ich aber immer die Meldung Segmentation fault. Sobald ich meine Änderungen wieder rückgängig mache, läuft alles wieder.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dann versuch es doch mal mit einer Maske die auch tatsaechlich das 5. Bit setzt, zb `0x20` ;)

Code: Alles auswählen

>>> 0x16 & 2**5
0
>>> 0x20 & 2**5
32
Balu
User
Beiträge: 6
Registriert: Freitag 11. Februar 2011, 16:50

Ok, das mit dem 5. Bit stimmt natürlich. :roll:
Aber der Fehler bleibt leider der selbe...
BlackJack

@Balu: Hast Du Dir für den Port auch die nötigen Rechte geholt? Also auch den `ioperm()`-Aufruf angepasst?
Balu
User
Beiträge: 6
Registriert: Freitag 11. Februar 2011, 16:50

Ja, nachdem ich immer den Fehler bekam hab ich dort auch den Port 800 eingetragen.
Somit ist der Fehler Segmentation fault weg.
Aber wenn ich mit portio.outb(0x20,0x800) den Hexwert 20 schreibe, dann sollte bei einer Abfrage portio.inb(0x800) doch auch die 20 übernommen worden sein?
Wenn ich so vorgehen, bleibt nämlich bei der Abfrage des Ports eine 0 als Wert stehen.

Das ist alles sehr seltsam...
Trotzdem schon mal vielen Dank für die Hilfe!
BlackJack

@Balu: Auslesen kann man die Bits nur wenn die Hardware das entsprechend zulässt. Keine Ahnung ob das in diesem Fall so sein sollte oder nicht.

Die Dokumentation scheint mir auch ein wenig dünn zu sein. Was bedeutet "select" bei 0x800? Bit ist gesetzt, dann kann man das entsprechende Bit in 0x802 benutzen und sonst ist es undefiniert, oder was?

Hast Du denn Hardware an den Leitungen hängen, mit der Du die Funktion überprüfen kannst?
Balu
User
Beiträge: 6
Registriert: Freitag 11. Februar 2011, 16:50

Habe das Problem inzwischen gelöst, waren mehrere Fehler die noch Probleme darstellten.
Zum einem eine falsche Aussage vom Supprt, das ich das 5. Bit High setzen soll. Dies war falsch, ich musste lediglich in Port 800 0x5h schreiben. Dies scheint wohl eine Art Freigabe für die Nutzung der GPIO-Ports zu sein.
Zum andern hatte ich die Rechte mit ioperm nur für jeweils einen der beiden Ports gesetzt. Hatte ich da beide ausgewählt (802 und 800) konnte ich auch schreiben und bekam am Ende auch vernünftige Ergebnisse.

Ich danke euch allen für die Hilfe und melde mich sicher wieder einmal bei einer Frage.

Schöne Grüße

Flo
Antworten