According to the previous evaluation plan, there is still a lack of an evaluation of human-computer interaction related functions (buttons, display, touch, etc.), because the touch and display functions are directly made by the manufacturer, and the display and touch are also used in previous GTK-related articles, so I will write about the buttons, which are essentially GPIO input.
I have written an article about GPIO output before, which is about lighting up a lamp. Today, let’s do an experiment on GPIO INPUT.
Because I found that the user buttons on the development board were already occupied when I turned on the lights, I will use the large number of GPIOs on CN8.
The description of all pins can be found through the document, as shown in the figure below
Use the gpioinfo command used in lighting, and check the table to see which GPIO is not used. I just picked PB1, which corresponds to line 1 of gpiochip1.
Next, we will change the previous lighting code to GPIO input code. The code is as follows
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/gpio.h>
int main(int argc, char **argv)
{
struct gpiohandle_request req;
struct gpiohandle_data data;
char chrdev_name[20];
int fd, ret;
strcpy(chrdev_name, "/dev/gpiochip1");
/* 打开GPIO设备 */
fd = open(chrdev_name, 0);
if (fd == -1)
{
ret = -errno;
fprintf(stderr, "Failed to open %s\n", chrdev_name);
return ret;
}
/* 设置使用的几号GPIO,和输入输出模式等 */
req.lineoffsets[0] = 1;//1号,与之前的gpiochip1组合,即表示PB1
req.flags = GPIOHANDLE_REQUEST_INPUT;//输入模式
req.lines = 1; // 只请求一个线路的句柄
req.consumer_label[0] = '\0'; // 不需要为读取设置任何标签或默认值
/* 获取GPIO的输入句柄 */
ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
/* 如果获取失败 */
if (ret == -1)
{
ret = -errno;
fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n",
ret);
}
/* 已经获取到/获取失败句柄,关闭文件描述符 */
if (close(fd) == -1)
{
perror("Failed to close GPIO character device file");
}
/* 定时1s查询GPIO状态并打印 */
while(1)
{
/* 获取GPIO状态 */
ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
/* 如果获取失败 */
if (ret == -1)
{
ret = -errno;
fprintf(stderr, "Failed to issue %s (%d)\n",
"GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret);
}
else
{
/* 打印获取到的GPIO电平 */
printf("value: %d\n", data.values[0]); // 打印读取到的GPIO值(0或1)
}
/* delay 1S */
sleep(1);
}
/* 释放GPIO句柄文件描述符 */
ret = close(req.fd);
if (ret == -1)
{
perror("Failed to close GPIO LINEHANDLE device file");
ret = -errno;
}
return ret;
}
The matching makefile is as follows
PROG = gpioInput
SRCS = gpioInput.c
OBJS = $(SRCS:.c=.o)
CLEANFILES = $(PROG)
# Add / change option in CFLAGS if needed
# CFLAGS += <new option>
$(PROG): $(OBJS)
$(CC) $(CFLAGS) -o $(PROG) $(OBJS)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
all: $(PROG)
clean:
rm -f $(CLEANFILES) $(patsubst %.c,%.o, $(SRCS)) *~
The function implemented by this code is to initialize PB1 to input mode, and then print the level status of GPIO every 1S
I won't go into details about how to compile the code and run it. It is the same as the previous operation.
Use the DuPont line to give GPIO a low level (connected to GND) or a high level (connected to 3.3V), and you can see the level status read by GPIO in the printout. The code running effect is as follows
WeChat_20240114213318