• 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的管脚电平

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

  • 相关阅读:
    快速搭建一个go语言web后端服务脚手架
    「DaoCloud 道客」郭峰:云原生加速金融信创发展
    谷歌计划从Chrome119起测试IP隐私保护功能
    速卖通双11大促期间如何让商品爆单,这些运营技巧一定要知道
    LeetCode LCR 103. 零钱兑换【完全背包,恰好装满背包的最小问题】中等
    Oracle使用遇到的问题
    3d建模都是美术生学的吗
    环境感知——自动驾驶模型训练(菜鸟版本)
    C语言进制转换(1112:进制转换(函数专题))
    vue3+ts实现幻灯片效果
  • 原文地址:https://blog.csdn.net/qq_42174306/article/details/125560936