Leggere gli stati GPIO usando C


8

Ho implementato questo esempio per familiarizzare con la programmazione GPIO di base in C. Il codice mostra come scrivere sui pin GPIO ma non indica esplicitamente come leggere lo stato dei pin. Ho il sospetto che WiringPi alla fine sarà una soluzione migliore poiché alla fine vorrò leggere lo stato di un pin di output , ma nel frattempo mi piacerebbe completare il mio percorso attraverso il codice di Dom e Gert. Come potrei quindi leggere il valore di un pin?


Ti interessa spiegare il downvote?
bobthechemist,

2
I voti negativi sono ridicoli, forse hai sconvolto qualcuno (i) ad un certo punto. +1 da parte mia solo per compensare.
riccioli d'oro

Risposte:


6

Quell'esempio di elinux usa un IO mappato in memoria . Il kernel esporta anche un'interfaccia dello spazio utente tramite /sys/class/gpio, 1 che è anche documentata su elinux . Lavorando in C useresti basso livello read()/ write()anziché echo, ovviamente. Non utilizzare funzioni basate su stream di livello superiore.

Alcuni programmatori si arrabbiano un po 'quando gli viene detto di usare un'interfaccia di file per cose che credono debbano essere fatte con le chiamate di sistema. Questa è puramente una questione di stile : equivalgono esattamente alla stessa cosa . Non esiste un "sovraccarico I / O aggiuntivo", ecc., Che accede a un file in questo caso perché non è un file reale, è un'interfaccia del kernel. Esattamente come qualsiasi altro sistema ABI che tu abbia mai usato, solo diverso. L'uso di /proce /sysnodi è stato a lungo preferito dagli sviluppatori del kernel, ma vedo ancora persone determinate a utilizzare le chiamate di sistema dove possono - ad esempio sysfs(), nonostante il fatto che man 2 sysfsdica chiaramente:

Questa chiamata di sistema derivata da System-V è obsoleta; non usarlo. Sui sistemi con / proc, le stesse informazioni possono essere ottenute tramite / proc / filesystems; usa invece quell'interfaccia.

Questa è una pagina man della libreria C che ti dice di usare l' /procinterfaccia . Se non è abbastanza buono per convincerti, niente lo è. /sysè lo stesso tipo di cose. Il punto è: solo perché stai usando un nodo di file invece di qualche API specifica in C non significa che non stai facendo una vera programmazione, o che le prestazioni ne risentiranno, ecc. Ecc. Alcune persone potrebbero dire che in realtà è una bella funzionalità. È anche il metodo raccomandato dalle persone che hanno scritto il kernel del sistema operativo.

Una rapida introduzione all'interfaccia GPIO è disponibile in [kernel-src]/Documentation/ABI/testing/sysfs-gpio:

  GPIOs are only made available to userspace by an explicit
  "export" operation.  If a given GPIO is not claimed for use by
  kernel code, it may be exported by userspace (and unexported later).
  Kernel code may export it for complete or partial access.

  GPIOs are identified as they are inside the kernel, using integers in
  the range 0..INT_MAX.  See Documentation/gpio.txt for more information.

    /sys/class/gpio
        /export ... asks the kernel to export a GPIO to userspace
        /unexport ... to return a GPIO to the kernel
        /gpioN ... for each exported GPIO #N
            /value ... always readable, writes fail for input GPIOs
            /direction ... r/w as: in, out (default low); write: high, low
            /edge ... r/w as: none, falling, rising, both
        /gpiochipN ... for each gpiochip; #N is its first GPIO
            /base ... (r/o) same as N
            /label ... (r/o) descriptive, not necessarily unique
            /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1)

Sembrano vari tutorial e simili online oltre a quello di elinux. Ho usato solo I2C, altrimenti ti darei una risposta più diretta.

Se sei interessato a scrivere il codice spaziale del kernel accedendo a GPIO, puoi dare un'occhiata qui , anche se penso che sia davvero utile solo se vuoi scrivere un driver per un dispositivo specifico e creare la tua API dello spazio utente.


1. Dato che anche l'IO mappato a mem deve utilizzare la lettura / scrittura, non sono sicuro che un metodo offra un vantaggio significativo rispetto all'altro qui. L'uso /sysdell'interfaccia sarà sicuramente più portatile, se stai cercando un codice che verrà eseguito su cose diverse da un raspberry pi.


Grazie. La mia conoscenza della lingua è stata Mathematica, quindi quando è stato portato su RPi ho saltato. L'accesso GPIO tramite comandi nativi di Wolfram è un po 'lento al momento, quindi sto cercando di imparare abbastanza c per tenermi fuori dai guai. (quindi nessun codice nello spazio del kernel per me!)
bobthechemist,

read()/ write()e le funzioni basate sul descrittore di file associato (al contrario del flusso di file ) in realtà non sono Standard C, ma sono POSIX e standard su Linux. C'è un'introduzione qui: gnu.org/software/libc/manual/html_node/… I flussi di file standard possono funzionare, ma nella mia esperienza sono stati anche problematici WRT su /syse /proc; usare i descrittori di livello inferiore non è più imbarazzante o difficile comunque. In bocca al lupo!
riccioli d'oro
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.