• 17.linuxGPIO应用编程


            除了LED类设备可以通过sysfs文件系统控制以外,还可以使用该虚拟文件系统控制GPIO的高低电平,输入以及中断检测。

    一、GPIO控制高低电平

            进入目录sys/class/gpio下可以看到有如下文件,其中gpiochip0对应硬件的GPIO0,gpiochip1对应硬件的GPIO1,以此类推。每个gpiochipX都管理一组32个gpio管脚。

            如果要使用某一个gpio管脚,需要先使用export命令将其导出。例如命令echo 0 > export,可以以将GPIO0_IO0导出,同理使用命令echo 0 > unexport命令删除GPIO0_IO0管脚

    打开导出的管脚可以看到有如下文件 :

            active_low:代表有效极性
            direction:代表输入或输出
            value:代表管脚电平 

    对于给定的一个 GPIO 引脚,如何计算它在 sysfs 中对应的编号?

    GPIO4_IO16,GPIO4 对应于 gpiochip96,所以GPIO4_IO16对应的编号就是96 + 16 = 112.

    应用程序编写:

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <sys/types.h>
    4. #include <sys/stat.h>
    5. #include <fcntl.h>
    6. #include <unistd.h>
    7. #include <string.h>
    8. static char gpio_path[100];
    9. static int gpio_config(const char *attr, const char *val)
    10. {
    11. char file_path[100];
    12. int len;
    13. int fd;
    14. sprintf(file_path, "%s/%s", gpio_path, attr);
    15. if (0 > (fd = open(file_path, O_WRONLY))) {
    16. perror("open error");
    17. return fd;
    18. }
    19. len = strlen(val);
    20. if (len != write(fd, val, len)) {
    21. perror("write error");
    22. close(fd);
    23. return -1;
    24. }
    25. close(fd); //关闭文件
    26. return 0;
    27. }
    28. int main(int argc, char *argv[])
    29. {
    30. /* 校验传参 */
    31. if (3 != argc) {
    32. fprintf(stderr, "usage: %s <gpio> <value>\n", argv[0]);
    33. exit(-1);
    34. }
    35. /* 判断指定编号的 GPIO 是否导出 */
    36. sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);
    37. if (access(gpio_path, F_OK)) {//如果目录不存在 则需要导出
    38. int fd;
    39. int len;
    40. if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
    41. perror("open error");
    42. exit(-1);
    43. }
    44. len = strlen(argv[1]);
    45. if (len != write(fd, argv[1], len)) {//导出 gpio
    46. perror("write error");
    47. close(fd);
    48. exit(-1);
    49. }
    50. close(fd); //关闭文件
    51. }
    52. /* 配置为输出模式 */
    53. if (gpio_config("direction", "out"))
    54. exit(-1);
    55. /* 极性设置 */
    56. if (gpio_config("active_low", "0"))
    57. exit(-1);
    58. /* 控制 GPIO 输出高低电平 */
    59. if (gpio_config("value", argv[2]))
    60. exit(-1);
    61. /* 退出程序 */
    62. exit(0);
    63. }

    代码流程:代码使用样例:        ./testApp 36 1,将编号为36的GPIO管脚设置为高电平

            ① 检查是否导出要操作的管脚,如果未导出则将其导出
            ②  将管脚配置为输出模式,有效极性低,输出对应的电平。

     二、GPIO控制高低电平

            

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <sys/types.h>
    4. #include <sys/stat.h>
    5. #include <fcntl.h>
    6. #include <unistd.h>
    7. #include <string.h>
    8. static char gpio_path[100];
    9. static int gpio_config(const char *attr, const char *val)
    10. {
    11. char file_path[100];
    12. int len;
    13. int fd;
    14. sprintf(file_path, "%s/%s", gpio_path, attr);
    15. if (0 > (fd = open(file_path, O_WRONLY))) {
    16. perror("open error");
    17. return fd;
    18. }
    19. len = strlen(val);
    20. if (len != write(fd, val, len)) {
    21. perror("write error");
    22. close(fd);
    23. return -1;
    24. }
    25. close(fd); //关闭文件
    26. return 0;
    27. }
    28. int main(int argc, char *argv[])
    29. {
    30. char file_path[100];
    31. char val;
    32. int fd;
    33. /* 校验传参 */
    34. if (2 != argc) {
    35. fprintf(stderr, "usage: %s <gpio>\n", argv[0]);
    36. exit(-1);
    37. }
    38. /* 判断指定编号的 GPIO 是否导出 */
    39. sprintf(gpio_path, "/sys/class/gpio/gpio%s", argv[1]);
    40. if (access(gpio_path, F_OK)) {//如果目录不存在 则需要导出
    41. int len;
    42. if (0 > (fd = open("/sys/class/gpio/export", O_WRONLY))) {
    43. perror("open error");
    44. exit(-1);
    45. }
    46. len = strlen(argv[1]);
    47. if (len != write(fd, argv[1], len)) {//导出 gpio
    48. perror("write error");
    49. close(fd);
    50. exit(-1);
    51. }
    52. close(fd); //关闭文件
    53. }
    54. /* 配置为输入模式 */
    55. if (gpio_config("direction", "in"))
    56. exit(-1);
    57. /* 极性设置 */
    58. if (gpio_config("active_low", "0"))
    59. exit(-1);
    60. /* 配置为非中断方式 */
    61. if (gpio_config("edge", "none"))
    62. exit(-1);
    63. /* 读取 GPIO 电平状态 */
    64. sprintf(file_path, "%s/%s", gpio_path, "value");
    65. if (0 > (fd = open(file_path, O_RDONLY))) {
    66. perror("open error");
    67. exit(-1);
    68. }
    69. if (0 > read(fd, &val, 1)) {
    70. perror("read error");
    71. close(fd);
    72. exit(-1);
    73. }
    74. printf("value: %c\n", val);
    75. /* 退出程序 */
    76. close(fd);
    77. exit(0);
    78. }

    代码流程:代码使用样例:        ./testApp 36 ,读取编号为36的管脚电平

            ① 检查是否导出要操作的管脚,如果未导出则将其导出
            ②  将管脚配置为输入模式,有效极性低,读取对应电平。

  • 相关阅读:
    什么是Sparse by default for crates.io
    顺序表--C语言版(从0开始,超详细解析 ,小白一听就懂!!!)
    聊一下kafka的消费组
    PositiveSSL通配符SSL证书能保护几个域名
    智慧食堂到底“智”在哪里?解决传统食堂5大问题
    Go开始:Go基本元素介绍
    如何查看MySQL的安装位置
    调试日记 | main got an exception: Expecting value: line 35 column 13
    上门服务小程序系统|多元化服务和高效便捷的服务体验
    30出头成为复旦博导,陈思明:敲代码和写诗,我两样都要
  • 原文地址:https://blog.csdn.net/qq_42174306/article/details/125560936