打印
[应用相关]

【100ASK_STM32MP157(带屏)试用体验】STM32MP157 之GPIO编程

[复制链接]
306|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cr315|  楼主 | 2021-2-23 16:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
GPIO编程基础介绍
        GPIO(General-Purpose IO Ports),即通用IO接口。GPIO的使用较为简单,主要分为输入和输出两种功能。GPIO主要用于实现一些简单设备的控制。在作为输入型GPIO的情况下,我们可以将该IO连接外部按键或者传感器,用于检测外部状态。当作为输出时,我们可以通过输出高低电平来控制外部设备的运转。
        由于GPIO的功能多种多样,我们需要首先将引脚设置为GPIO。设置为GPIO之后,我们需要设置GPIO的方向。当设置为输出时,我们可以控制输出高电平或者低电平。当设置为输入时,我们可以读取GPIO的电平来判断外部输入电平的高低。
GPIO编程软件接口
        GPIO编程有多种实现方式,在这里,我们通过sysfs方式来实现GPIO的控制实现。
        如果要通过sysfs方式控制gpio,首先需要底层内核的支持。为了实现内核对sysfs gpio的支持,我们需要在内核中进行设置。在编译内核的时候,加入  Device Drivers-> GPIO Support ->/sys/class/gpio/… (sysfs inteRFace)。作为GPIO的引脚,不允许在内核中被用作其他用途。
        在系统正常运行之后,我们可以在/sys/class/gpio下看到sysfs控制相关的接口。有三种类型的接口, 分别是控制接口,GPIO信号和GPIO控制器三种接口。这部分的具体介绍可参考《kernel\Documentation\gpio\sysfs.txt》。
控制接口
        控制接口用于实现在用户空间对GPIO的控制,主要包括/sys/class/gpio/export和/sys/class/gpio/unexport两个接口。这这两个控制接口都是只写的,/sys/class/gpio/export实现将GPIO控制从内核空间导出到用户空间,/sys/class/gpio/unexport用于实现取消GPIO控制从内核空间到用户空间的导出。
        下面以引脚编号为19的GPIO为例进行说明,在/sys/class/gpio/目录下,我们执行"echo 19 > export"之后,将会产生一个”gpio19”节点来控制引脚编号为19的GPIO。我们执行"echo 19 > unexport"之后,将会删除之前通过export产生的”gpio19”节点。为了使用gpio,我们需要首先使用/sys/class/gpio/export导出gpio引脚编号。完成使用之后,通过/sys/class/gpio/unexport删除掉之前导出的gpio引脚。
GPIO信号
        GPIO信号,即为GPIO本身,其路径为/sys/class/gpio/gpioN/,拥有多个属性。通过对这些属性进行控制,就可以实现对GPIO的控制
“direction”属性,读取的值为”in”或者”out”。通过对该属性写入”in”或者”out”可以设置该GPIO为输入或者输出。如果直接写入”out”,则会使GPIO直接输出低电平。也可以通过写入”low”或者”high”来直接设置输出低电平或者高电平。
”value”属性,用于读取输入电平或者控制输出电平。如果GPIO为输出,则对value写入0为输出低电平,写入非0为输出高电平。如果设置为输入的话,则读到0表示输入为低电平,1为高电平。
”edge”属性,用于设置触发电平,只有在GPIO可以设置为中断输入引脚时才会出现该属性
GPIO控制器
        GPIO控制器,用于表示GPIO 控制实现的初始GPIO,其路径为/sys/class/gpio/gpiochipN/。比如/sys/class/gpio/gpiochip42/ 则表示实现GPIO控制器的初始化编号为42。GPIO控制器的属性为只读属性,包括base、label和ngpio等多个。
”base”属性,和gpiochipN的N代表的含义相同,表示被该组GPIO控制器实现的第一个GPIO.
” ngpio”属性,用于表示该控制器支持多少个GPIO,支持的GPIO编号为从N到N+ngpio-1
” label”属性,用于判断控制器,并不总是唯一的
STM32MP157(开发板GPIO编号的确定
        每个芯片可以有N组GPIO,每组GPIO最多有32个GPIO,即最多有N*32个GPIO。但是在实际设计中,每组的GPIO数量各有不同。在imx6ULL中,实际每组拥有的GPIO数量如下图所示,具体详见《IMX6ULLRM.pdf》手册1347页。


      




  • 01 #include <stdio.h>
  • 02 #include <stdlib.h>
  • 03 #include <unistd.h>
  • 04 #include <string.h>
  • 05 #include <errno.h>
  • 06 #include <fcntl.h>
  • 07 #include <sys/stat.h>
  • 08  /****************************************************************
  • 09  * 宏定义,定义GPIO编号以及LED和按键各自对应的编号 ,计算方法为GPION_X对应的编号为 (N-1)*32+X
  • 10  ****************************************************************/
  • 11 #define GPIO4_14        110
  • 12 #define GPIO5_1         129
  • 13 #define GPIO5_3                131
  • 14
  • 15 #define GPIO_KEY1     GPIO4_14
  • 16 #define GPIO_KEY2     GPIO5_1
  • 17 #define GPIO_LED          GPIO5_3
  • 18 //定义数组大小
  • 19 #define MAX_BUF                  128
  • 20 //定义用于GPIO控制的统一路径
  • 21 #define SYSFS_GPIO_DIR "/sys/class/gpio"
  • 22 /**********************************************************************
  • 23          * 函数名称: sysfs_gpio_export
  • 24          * 功能描述: 向/sys/class/gpio/export写入引脚编号,即通知系统需要导出的GPIO引脚编号
  • 25          * 输入参数:@GPIO :要导出的引脚编号
  • 26          * 输出参数:是否成功执行
  • 27          * 返 回 值: 0 成功执行;其他:执行失败
  • 28          * 修改日期            版本号         修改人                  修改内容
  • 29          * -----------------------------------------------
  • 30          * 2020/05/14                 V1.0          芯晓                  创建
  • 31  ***********************************************************************/
  • 32 int sysfs_gpio_export(unsigned int gpio)
  • 33 {
  • 34     int fd, len;
  • 35     char buf[MAX_BUF];
  • 36         // /sys/class/gpio/export
  • 37     fd = open( "/sys/class/gpio/export", O_WRONLY);//打开文件
  • 38     if (fd < 0) {
  • 39         perror("gpio/export");
  • 40         return fd;
  • 41     }
  • 42
  • 43     len = snprintf(buf, sizeof(buf), "%d", gpio);//从数字变换为字符串,即1 变为”1“
  • 44     write(fd, buf, len);//将需要导出的GPIO引脚编号进行写入
  • 45     close(fd);//关闭文件
  • 46
  • 47     return 0;
  • 48 }
  • 49 /**********************************************************************
  • 50          * 函数名称: sysfs_gpio_unexport
  • 51          * 功能描述: 向/sys/class/gpio/unexport写入引脚编号,即通知系统需要取消导出的GPIO引脚编号
  • 52          * 输入参数:@gpio :要取消导出的引脚编号
  • 53          * 输出参数:是否成功执行
  • 54          * 返 回 值: 0 成功执行;其他:执行失败
  • 55          * 修改日期            版本号         修改人                  修改内容
  • 56          * -----------------------------------------------
  • 57          * 2020/05/14                 V1.0          芯晓                  创建
  • 58  ***********************************************************************/
  • 59 int sysfs_gpio_unexport(unsigned int gpio)
  • 60 {
  • 61     int fd, len;
  • 62     char buf[MAX_BUF];
  • 63         // /sys/class/gpio/unexport
  • 64     fd = open("/sys/class/gpio/unexport", O_WRONLY);//打开文件
  • 65     if (fd < 0) {
  • 66         perror("gpio/export");
  • 67         return fd;
  • 68     }
  • 69
  • 70     len = snprintf(buf, sizeof(buf), "%d", gpio);//从数字变换为字符串,即1 变为”1“
  • 71     write(fd, buf, len);//将需要取消导出的GPIO引脚编号进行写入
  • 72     close(fd);//关闭文件
  • 73     return 0;
  • 74 }
  • 75 /**********************************************************************
  • 76          * 函数名称: sysfs_gpio_set_dir
  • 77          * 功能描述: 向/sys/class/gpio/gpioN/direction写入引脚方向,即设置导出的GPIO引脚的方向
  • 78          * 输入参数:@gpio :要设置方向的引脚编号
  • 79                                         @out_flag :要设置的引脚方向。1:表示设置为输出。0:表示设置为输入。
  • 80          * 输出参数:是否成功执行
  • 81          * 返 回 值: 0 成功执行;其他:执行失败
  • 82          * 修改日期            版本号         修改人                  修改内容
  • 83          * -----------------------------------------------
  • 84          * 2020/05/14                 V1.0          芯晓                  创建
  • 85  ***********************************************************************/
  • 86 int sysfs_gpio_set_dir(unsigned int gpio, unsigned int out_flag)
  • 87 {
  • 88     int fd, len;
  • 89     char buf[MAX_BUF];
  • 90         // /sys/class/gpio/gpioN/direction
  • 91     len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);
  • 92
  • 93     fd = open(buf, O_WRONLY);//打开文件
  • 94     if (fd < 0) {
  • 95         perror(buf);
  • 96         return fd;
  • 97     }
  • 98
  • 99     if (out_flag)//为1,则写入“out",即设置为输出
  • 100         write(fd, "out", 4);
  • 101     else//为0,则写入“in",即设置为输入
  • 102         write(fd, "in", 3);
  • 103
  • 104     close(fd);//关闭文件
  • 105     return 0;
  • 106 }
  • 107 /**********************************************************************
  • 108          * 函数名称: sysfs_gpio_set_value
  • 109          * 功能描述: 向/sys/class/gpio/gpioN/value写入输出电平,即设置GPION输出的电平高低
  • 110                                         (在引脚为输出的时候进行使用)
  • 111          * 输入参数:@gpio :要设置输出电平的引脚编号
  • 112                                         @value :要设置的输出电平。1:表示设置输出为高电平。0:表示设置输出为低电平。
  • 113          * 输出参数:是否成功执行
  • 114          * 返 回 值: 0 成功执行;其他:执行失败
  • 115          * 修改日期            版本号         修改人                  修改内容
  • 116          * -----------------------------------------------
  • 117          * 2020/05/14                 V1.0          芯晓                  创建
  • 118  ***********************************************************************/
  • 119 int sysfs_gpio_set_value(unsigned int gpio, unsigned int value)
  • 120 {
  • 121     int fd, len;
  • 122     char buf[MAX_BUF];
  • 123         // /sys/class/gpio/gpioN/value
  • 124     len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
  • 125
  • 126     fd = open(buf, O_WRONLY);//打开文件
  • 127     if (fd < 0) {
  • 128         perror(buf);
  • 129         return fd;
  • 130     }
  • 131
  • 132     if (value)//为1,则写入“1",即设置为输出高电平
  • 133         write(fd, "1", 2);
  • 134     else//为0,则写入“0",即设置为输出低电平
  • 135         write(fd, "0", 2);
  • 136
  • 137     close(fd);//关闭文件
  • 138     return 0;
  • 139 }
  • 140 /**********************************************************************
  • 141          * 函数名称: sysfs_gpio_get_value
  • 142          * 功能描述: 从/sys/class/gpio/gpioN/value读取引脚电平,即读取GPION输入的电平高低
  • 143                                         (在引脚为输入的时候进行使用)
  • 144          * 输入参数:@gpio :要读取输入电平的引脚编号
  • 145                                         @value :读取的电平高低存储的位置
  • 146          * 输出参数:是否成功执行
  • 147          * 返 回 值: 0 成功执行;其他:执行失败
  • 148          * 修改日期            版本号         修改人                  修改内容
  • 149          * -----------------------------------------------
  • 150          * 2020/05/14                 V1.0          芯晓                  创建
  • 151  ***********************************************************************/
  • 152 int sysfs_gpio_get_value(unsigned int gpio, unsigned int *value)
  • 153 {
  • 154     int fd, len;
  • 155     char buf[MAX_BUF];
  • 156     char ch;
  • 157         // /sys/class/gpio/gpioN/value
  • 158     len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
  • 159
  • 160     fd = open(buf, O_RDONLY);//打开文件
  • 161     if (fd < 0) {
  • 162         perror("gpio/get-value");
  • 163         return fd;
  • 164     }
  • 165
  • 166     read(fd, &ch, 1);//读取外部输入电平
  • 167
  • 168     if (ch != '0') {//为'1',则设置为1,即输入为高电平
  • 169         *value = 1;
  • 170     } else {//为'0',则设置为0,即输入为低电平
  • 171         *value = 0;
  • 172     }
  • 173
  • 174     close(fd);//关闭文件
  • 175     return 0;
  • 176 }
  • 177 /**********************************************************************
  • 178          * 函数名称: main函数
  • 179          * 功能描述: 导出相关引脚并进行功能实现
  • 180
  • 181          * 2020/05/14                 V1.0          芯晓                  创建
  • 182  ***********************************************************************/
  • 183 int main(int argc, char **argv) {
  • 184     unsigned int i;
  • 185     unsigned int value1,value2;
  • 186
  • 187         printf("\t********************************************\n");
  • 188     printf("\t********  SYSFS_GPIO_TEST_DEMO**************\n");
  • 189     printf("\t******** version date: 2020/05    **********\n");
  • 190     printf("\t********************************************\n");
  • 191
  • 192         printf("gpio begin to export gpio\r\n");
  • 193     sysfs_gpio_export(GPIO_KEY1);//export gpio key1
  • 194     sysfs_gpio_export(GPIO_KEY2);//export gpio key2
  • 195     sysfs_gpio_export(GPIO_LED);//export gpio led
  • 196     printf("gpio export gpio ok\r\n");
  • 197
  • 198
  • 199     return 0;
  • 200 }



[color=rgb(51, 102, 153) !important]复制代码







  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <unistd.h>
  • #include <string.h>
  • #include <errno.h>
  • #include <fcntl.h>
  • #include <sys/stat.h>
  • /****************************************************************
  • * 宏定义,定义GPIO编号以及LED和按键各自对应的编号 ,计算方法为GPION_X对应的编号为 (N-1)*32+X
  • ****************************************************************/
  • #define GPIO4_14        110
  • #define GPIO5_1         129
  • #define GPIO5_3                131
  • #define GPIO_KEY1     GPIO4_14
  • #define GPIO_KEY2     GPIO5_1
  • #define GPIO_LED          GPIO5_3
  • //定义数组大小
  • #define MAX_BUF                  128
  • //定义用于GPIO控制的统一路径
  • #define SYSFS_GPIO_DIR "/sys/class/gpio"
  • /**********************************************************************
  •          * 函数名称: sysfs_gpio_export
  •          * 功能描述: 向/sys/class/gpio/export写入引脚编号,即通知系统需要导出的GPIO引脚编号
  •          * 输入参数:@gpio :要导出的引脚编号
  •          * 输出参数:是否成功执行
  •          * 返 回 值: 0 成功执行;其他:执行失败
  •          * 修改日期            版本号         修改人                  修改内容
  •          * -----------------------------------------------
  •          * 2020/05/14                 V1.0          芯晓                  创建
  • ***********************************************************************/
  • int sysfs_gpio_export(unsigned int gpio)
  • {
  •     int fd, len;
  •     char buf[MAX_BUF];
  •         // /sys/class/gpio/export
  •     fd = open( "/sys/class/gpio/export", O_WRONLY);//打开文件
  •     if (fd < 0) {
  •         perror("gpio/export");
  •         return fd;
  •     }
  •     len = snprintf(buf, sizeof(buf), "%d", gpio);//从数字变换为字符串,即1 变为”1“
  •     write(fd, buf, len);//将需要导出的GPIO引脚编号进行写入
  •     close(fd);//关闭文件
  •     return 0;
  • }
  • /**********************************************************************
  •          * 函数名称: sysfs_gpio_unexport
  •          * 功能描述: 向/sys/class/gpio/unexport写入引脚编号,即通知系统需要取消导出的GPIO引脚编号
  •          * 输入参数:@gpio :要取消导出的引脚编号
  •          * 输出参数:是否成功执行
  •          * 返 回 值: 0 成功执行;其他:执行失败
  •          * 修改日期            版本号         修改人                  修改内容
  •          * -----------------------------------------------
  •          * 2020/05/14                 V1.0          芯晓                  创建
  • ***********************************************************************/
  • int sysfs_gpio_unexport(unsigned int gpio)
  • {
  •     int fd, len;
  •     char buf[MAX_BUF];
  •         // /sys/class/gpio/unexport
  •     fd = open("/sys/class/gpio/unexport", O_WRONLY);//打开文件
  •     if (fd < 0) {
  •         perror("gpio/export");
  •         return fd;
  •     }
  •     len = snprintf(buf, sizeof(buf), "%d", gpio);//从数字变换为字符串,即1 变为”1“
  •     write(fd, buf, len);//将需要取消导出的GPIO引脚编号进行写入
  •     close(fd);//关闭文件
  •     return 0;
  • }
  • /**********************************************************************
  •          * 函数名称: sysfs_gpio_set_dir
  •          * 功能描述: 向/sys/class/gpio/gpioN/direction写入引脚方向,即设置导出的GPIO引脚的方向
  •          * 输入参数:@gpio :要设置方向的引脚编号
  •                                         @out_flag :要设置的引脚方向。1:表示设置为输出。0:表示设置为输入。
  •          * 输出参数:是否成功执行
  •          * 返 回 值: 0 成功执行;其他:执行失败
  •          * 修改日期            版本号         修改人                  修改内容
  •          * -----------------------------------------------
  •          * 2020/05/14                 V1.0          芯晓                  创建
  • ***********************************************************************/
  • int sysfs_gpio_set_dir(unsigned int gpio, unsigned int out_flag)
  • {
  •     int fd, len;
  •     char buf[MAX_BUF];
  •         // /sys/class/gpio/gpioN/direction
  •     len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", gpio);
  •     fd = open(buf, O_WRONLY);//打开文件
  •     if (fd < 0) {
  •         perror(buf);
  •         return fd;
  •     }
  •     if (out_flag)//为1,则写入“out",即设置为输出
  •         write(fd, "out", 4);
  •     else//为0,则写入“in",即设置为输入
  •         write(fd, "in", 3);
  •     close(fd);//关闭文件
  •     return 0;
  • }
  • /**********************************************************************
  •          * 函数名称: sysfs_gpio_set_value
  •          * 功能描述: 向/sys/class/gpio/gpioN/value写入输出电平,即设置GPION输出的电平高低
  •                                         (在引脚为输出的时候进行使用)
  •          * 输入参数:@gpio :要设置输出电平的引脚编号
  •                                         @value :要设置的输出电平。1:表示设置输出为高电平。0:表示设置输出为低电平。
  •          * 输出参数:是否成功执行
  •          * 返 回 值: 0 成功执行;其他:执行失败
  •          * 修改日期            版本号         修改人                  修改内容
  •          * -----------------------------------------------
  •          * 2020/05/14                 V1.0          芯晓                  创建
  • ***********************************************************************/
  • int sysfs_gpio_set_value(unsigned int gpio, unsigned int value)
  • {
  •     int fd, len;
  •     char buf[MAX_BUF];
  •         // /sys/class/gpio/gpioN/value
  •     len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
  •     fd = open(buf, O_WRONLY);//打开文件
  •     if (fd < 0) {
  •         perror(buf);
  •         return fd;
  •     }
  •     if (value)//为1,则写入“1",即设置为输出高电平
  •         write(fd, "1", 2);
  •     else//为0,则写入“0",即设置为输出低电平
  •         write(fd, "0", 2);
  •     close(fd);//关闭文件
  •     return 0;
  • }
  • /**********************************************************************
  •          * 函数名称: sysfs_gpio_get_value
  •          * 功能描述: 从/sys/class/gpio/gpioN/value读取引脚电平,即读取GPION输入的电平高低
  •                                         (在引脚为输入的时候进行使用)
  •          * 输入参数:@gpio :要读取输入电平的引脚编号
  •                                         @value :读取的电平高低存储的位置
  •          * 输出参数:是否成功执行
  •          * 返 回 值: 0 成功执行;其他:执行失败
  •          * 修改日期            版本号         修改人                  修改内容
  •          * -----------------------------------------------
  •          * 2020/05/14                 V1.0          芯晓                  创建
  • ***********************************************************************/
  • int sysfs_gpio_get_value(unsigned int gpio, unsigned int *value)
  • {
  •     int fd, len;
  •     char buf[MAX_BUF];
  •     char ch;
  •         // /sys/class/gpio/gpioN/value
  •     len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
  •     fd = open(buf, O_RDONLY);//打开文件
  •     if (fd < 0) {
  •         perror("gpio/get-value");
  •         return fd;
  •     }
  •     read(fd, &ch, 1);//读取外部输入电平
  •     if (ch != '0') {//为'1',则设置为1,即输入为高电平
  •         *value = 1;
  •     } else {//为'0',则设置为0,即输入为低电平
  •         *value = 0;
  •     }
  •     close(fd);//关闭文件
  •     return 0;
  • }
  • /**********************************************************************
  •          * 函数名称: main函数
  •          * 功能描述: 导出相关引脚并进行功能实现
  •          * 2020/05/14                 V1.0          芯晓                  创建
  • ***********************************************************************/
  • int main(int argc, char **argv) {
  •     unsigned int i;
  •     unsigned int value1,value2;
  •         printf("\t********************************************\n");
  •     printf("\t********  SYSFS_GPIO_TEST_DEMO**************\n");
  •     printf("\t******** version date: 2020/05    **********\n");
  •     printf("\t********************************************\n");
  •         printf("gpio begin to export gpio\r\n");
  •     sysfs_gpio_export(GPIO_KEY1);//export gpio key1
  •     sysfs_gpio_export(GPIO_KEY2);//export gpio key2
  •     sysfs_gpio_export(GPIO_LED);//export gpio led
  •     printf("gpio export gpio ok\r\n");
  •     return 0;
  • }



[color=rgb(51, 102, 153) !important]复制代码


使用特权

评论回复
沙发
maqianqu| | 2021-3-4 23:41 | 只看该作者
      

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1196

主题

3011

帖子

0

粉丝