Lendo estados GPIO usando C

8

Eu implementei este exemplo para me familiarizar com a programação GPIO básica em C. O código demonstra como gravar nos pinos do GPIO, mas não indica explicitamente como ler o estado dos pinos. Suspeito que o WiringPi acabe sendo uma solução melhor, pois , eventualmente, vou querer ler o estado de um pino de saída , mas, enquanto isso, gostaria de concluir minha jornada pelo código de Dom e Gert. Como então, eu poderia ler o valor de um alfinete?

bobthechemist
fonte
Importa-se de explicar o voto negativo?
bobthechemist
2
Os votos negativos são ridículos, talvez você tenha chateado alguém (s) em algum momento. +1 de mim apenas para compensar.
goldilocks

Respostas:

6

Esse exemplo do elinux usa E / S mapeadas na memória . O kernel também exporta uma interface de espaço do usuário via /sys/class/gpio, 1 que também está documentada no elinux . Trabalhando em C, você usaria baixo nível read()/ em write()vez de echo, obviamente. Não use funções baseadas em fluxo de nível superior.

Alguns programadores ficam um pouco chateados quando instruídos a usar uma interface de arquivo para coisas que eles acreditam que devem ser feitas com chamadas do sistema. Isso é puramente uma questão de estilo - eles representam exatamente a mesma coisa . Não há "sobrecarga adicional de E / S", etc., acessando um arquivo nesse caso porque não é um arquivo real, é uma interface do kernel. Exatamente como qualquer outro sistema ABI que você já usou, apenas diferente. O uso de /proce /sysnós tem sido preferido pelos desenvolvedores do kernel, mas ainda vejo pessoas determinadas a usar chamadas do sistema onde podem - por exemplo sysfs(), apesar do fato de man 2 sysfsdizer claramente:

Essa chamada de sistema derivada do System-V é obsoleta; não use. Em sistemas com / proc, as mesmas informações podem ser obtidas via / proc / filesystems; use essa interface.

Essa é uma página de manual da biblioteca C que diz para você usar a /procinterface . Se isso não é bom o suficiente para convencê-lo, nada é. /sysé o mesmo tipo de coisa. Ponto é: só porque você está usando um nó de arquivo em vez de algum API C específico não significa que você não está fazendo a programação real, ou que o desempenho vai sofrer, etc. etc. Algumas pessoas podem dizer que é realmente um bom recurso. É também o método recomendado pelas pessoas que escreveram o kernel do SO.

Uma rápida introdução à interface GPIO pode ser encontrada em [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)

Parece haver vários tutoriais e outros online, além do elinux. Só uso I2C, caso contrário, daria uma resposta mais direta.

Se você estiver interessado em escrever o código de espaço do kernel acessando o GPIO, pode dar uma olhada aqui , embora eu pense que isso é realmente útil apenas se você quiser escrever um driver para um dispositivo específico e criar sua própria API de espaço do usuário.


1. Como as E / S mapeadas por mem também devem usar leitura / gravação, não tenho certeza se um método oferece uma vantagem significativa sobre o outro aqui. O uso da /sysinterface certamente será mais portátil, se você estiver procurando por um código que será executado em outras coisas que não um pi framboesa.

Cachinhos Dourados
fonte
Obrigado. Meu idioma foi o Mathematica, então, quando foi portado para o RPi, eu pulei. O acesso ao GPIO via comandos nativos do Wolfram é um pouco lento no momento, então estou tentando aprender c suficiente para me manter longe de problemas. (assim nenhuma escrita espaço código do kernel para mim!)
bobthechemist
read()/ write()e as funções baseadas no descritor de arquivo associado (em oposição ao fluxo de arquivos ) não são realmente o Padrão C, mas são POSIX e padrão no linux. Há uma introdução aqui: gnu.org/software/libc/manual/html_node/… Os fluxos de arquivos padrão podem funcionar, mas, na minha experiência, eles também foram problemáticos para o WRT /syse /proc; usar os descritores de nível inferior não é mais difícil ou difícil. Boa sorte!
goldilocks