[原创] 【米尔-TI AM62x开发板-试用评测】应用开发基础:GPIO点灯、EVENT按键控制

HonestQiao   2024-2-1 14:36 楼主

在之前的分享 【米尔-TI AM62x开发板-试用评测】使用Yocto工具构建开发板完整镜像和SDK工具  中,已经讲过完整镜像和SDK工具的构建全过程,这篇分享,就使用构建的SDK工具,进行应用基础开发。

 

一、硬件了解

在米尔-TI AM62x开发板开发板上,提供了三个按键,1个可以被在程序中使用:

image.png  

 

另外,开发板上还提供了多个LED,具体如下:

image.png  

后面的程序中,就使用上面的User按键和D53、D54 LED。

 

二、系统挂载了解

在手册中,给出了按键的测试方式:

image.png  

 

可以使用下面的命令,进行测试:

hexdump /dev/input/event0

image.png  

执行后,按下按键和松开,就会有对应的输出。

 

另外,手册中也给出了LED的测试方法:

image.png  

 

登录系统后,可以查看到具体的LED挂载情况:

image.png  

通过上面的系统信息我们可以得到:

  • 按键事件:/dev/input/event0
  • D53 LED:/sys/class/leds/am62-sk:d53/brightness
  • D54 LED:/sys/class/leds/am62-sk:d53/brightness

下面,就进行程序编写,进行调用和控制。

 

三、按键程序

按键通过系统input的event来进行获取,具体的代码如下:

#include <stdio.h>
#include <linux/input.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// gpio-keys
#define DEV_PATH "/dev/input/event0"

// 主函数
int main()
{
	int keys_fd;
	char ret[2];
	struct input_event t;
	keys_fd=open(DEV_PATH, O_RDONLY);
	if(keys_fd <= 0)
	{
		printf("open "DEV_PATH" device error!\n");
		return -1;
	}

	while(1)
	{
		if(read(keys_fd, &t, sizeof(t)) == sizeof(t))
		{
			if(t.type==EV_KEY)
				if(t.value==0 || t.value==1)
				{
					printf("key %d %s\n", t.code, (t.value) ? "Pressed" : "Released");
					if(t.code == KEY_ESC)
						break;
				}
		}
	}
	close(keys_fd);
	return 0;
}

 

在上述代码中,打开设备 /dev/input/event0 ,然后读取事件信息,如果事件信息为EV_KEY,则判断其值,根据值来判断,是按下1还是松开0

 

将上述代码保存到key.c,然后按照下面的步骤进行编译。

首次进行新应用开发的话,需要在开发环境,先执行如下命令安装SDK工具链:

./myd-ym62x-yocto/oe-layersetup/build/arago-tmp-default-glibc/deploy/sdk/arago-2023.04-toolchain-2023.04.sh

其中arago-2023.04-toolchain-2023.04.sh即为之前编译的SDK工具,安装路径为/opt/arago-2023.04/

 

然后使用SDK工具进行编译:

source /opt/arago-2023.04/environment-setup-aarch64-oe-linux

$CC key.c -o key

 

编译完成,将程序部署到开发板上,运行,然后按键,结果如下:

image.png  

 

四、LED控制

下面的程序,控制D53、D54交替点亮:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

// LED 引脚
#define SYSFS_GPIO_LED_1_VAL "/sys/class/leds/am62-sk:d53/brightness"
#define SYSFS_GPIO_LED_2_VAL "/sys/class/leds/am62-sk:d54/brightness"
#define SYSFS_GPIO_LED_VAL_H "1"
#define SYSFS_GPIO_LED_VAL_L "0"

int main()
{
    int fd1;
    int fd2;
    int count = 30;

    // 打开LED GPIO
    fd1 = open(SYSFS_GPIO_LED_1_VAL, O_RDWR);
    if (fd1 == -1)
    {
        printf("ERR: gpio1 open error.\n");
        return EXIT_FAILURE;
    }
    fd2 = open(SYSFS_GPIO_LED_2_VAL, O_RDWR);
    if (fd2 == -1)
    {
        printf("ERR: gpio2 open error.\n");
        return EXIT_FAILURE;
    }

    while (count)
    {
        count--;
        write(fd1, SYSFS_GPIO_LED_VAL_H, sizeof(SYSFS_GPIO_LED_VAL_H));
        write(fd2, SYSFS_GPIO_LED_VAL_L, sizeof(SYSFS_GPIO_LED_VAL_L));
        usleep(1000000);
        write(fd1, SYSFS_GPIO_LED_VAL_L, sizeof(SYSFS_GPIO_LED_VAL_L));
        write(fd2, SYSFS_GPIO_LED_VAL_H, sizeof(SYSFS_GPIO_LED_VAL_H));
        usleep(1000000);
    }
    close(fd1);
    close(fd2);

    return 0;
}

上述代码逻辑较为简单,就是打开两个LED对应的设备,然后分别写入0、1,从而控制亮灭。

 

source /opt/arago-2023.04/environment-setup-aarch64-oe-linux

$CC led.c -o led

将上述代码保存到led.c,然后按照key.c的步骤进行编译,再部署到开发板上,就能控制LED了。

 

五、按键控制LED

在这一步中,我对按键的时间进行检测,从而判断是长按还是短按。

短按控制LED1,长按控制LED2。每个LED,第一次按键点亮,第二次按键熄灭。

 

要检测按键时长,可以先测试下面的程序,使用系统clock_gettime()调用来获取运行时间:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long getTimeNs()
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME,&ts);

    return ts.tv_sec*1000000000+ts.tv_nsec;
}

// 测试函数
void Test()
{
    int i,j;
    for(i=1000;i>0;i--)
        for(j=2000;j>0;j--);
}

// 主函数
int main()
{
    clock_t  start, stop;//定义2个变量用来存放开始和结束时间
    double duration;
    start = getTimeNs();//开始计时
    Test(); //被测函数
    stop = getTimeNs(); //结束计时
    duration = ((double)(stop - start))/1000000000;//计算以秒为单位的运行时间,(结束时间-开始时间)
    printf("测试函数耗费时间为 %0.6f 秒\n",duration);
    return 0;
}

将上述代码保存为time_calc.c,编译运行后部署到开发板,运行结果如下:

image.png  

 

结合上面的程序,通过按键时长是否超过1秒,来判断是否是否长按,具体代码如下:

#include <stdio.h>
#include <linux/input.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <stdbool.h>

// gpio-keys
#define DEV_PATH "/dev/input/event0"
#define TIME_LONG  1

long getTimeNs()
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME,&ts);

    return ts.tv_sec*1000000000+ts.tv_nsec;
}

// 主函数
int main()
{
    clock_t  start, stop;//定义2个变量用来存放开始和结束时间
    double duration;
    bool status;
	int keys_fd;
	char ret[2];
	struct input_event t;
	keys_fd=open(DEV_PATH, O_RDONLY);
	if(keys_fd <= 0)
	{
		printf("open "DEV_PATH" device error!\n");
		return -1;
	}

    status = false;
    start = 0;
    stop = 0;
	while(1)
	{
		if(read(keys_fd, &t, sizeof(t)) == sizeof(t))
		{
			if(t.type==EV_KEY)
				if(t.value==0 || t.value==1)
				{
					printf("key %d %s\n", t.code, (t.value) ? "Pressed" : "Released");
                    if(t.code==0x100) {
                        if(t.value) {
                            if(!status) {
                                status = true;
                                start = getTimeNs();
                            }
                        } else {
                            status = false;
                            stop = getTimeNs();
                            duration = ((double)(stop - start))/1000000000;//计算以秒为单位的运行时间,(结束时间-开始时间)
                            printf("按键时长 %0.6f 秒\n",duration);
                            if(duration>TIME_LONG) {
                                printf("长按\n");
                            } else {
                                printf("短按\n");
                            }
                        }
                    }
					if(t.code == KEY_ESC)
						break;

                    printf("\n");
				}
		}
	}
	close(keys_fd);
	return 0;
}

 

将上述代码保存为key_short_long.c,编译运行后部署到开发板,运行结果如下:

image.png  

通过按键的时长,程序会根据其判断是否长按短按。

 

最后,结合LED控制的程序,通过短按控制LED1、长按控制LED2,具体程序如下:

#include <stdio.h>
#include <linux/input.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <stdbool.h>

// gpio-keys
#define DEV_PATH "/dev/input/event0"
#define TIME_LONG  1

// LED 引脚
#define SYSFS_GPIO_LED_1_VAL "/sys/class/leds/am62-sk:d53/brightness"
#define SYSFS_GPIO_LED_2_VAL "/sys/class/leds/am62-sk:d54/brightness"
#define SYSFS_GPIO_LED_VAL_H "1"
#define SYSFS_GPIO_LED_VAL_L "0"

long getTimeNs()
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME,&ts);

    return ts.tv_sec*1000000000+ts.tv_nsec;
}

// 主函数
int main()
{
    clock_t  start, stop;//定义2个变量用来存放开始和结束时间
    double duration;
    bool status;
	int keys_fd;
	char ret[2];
	struct input_event t;

    int fd1;
    int fd2;
    bool status1;
    bool status2;

    // 打开LED GPIO
    fd1 = open(SYSFS_GPIO_LED_1_VAL, O_RDWR);
    if (fd1 == -1)
    {
        printf("ERR: gpio1 open error.\n");
        return EXIT_FAILURE;
    }
    fd2 = open(SYSFS_GPIO_LED_2_VAL, O_RDWR);
    if (fd2 == -1)
    {
        printf("ERR: gpio2 open error.\n");
        return EXIT_FAILURE;
    }

    status1 = false;
    status2 = false;
    write(fd1, SYSFS_GPIO_LED_VAL_L, sizeof(SYSFS_GPIO_LED_VAL_L));
    write(fd2, SYSFS_GPIO_LED_VAL_L, sizeof(SYSFS_GPIO_LED_VAL_L));

	keys_fd=open(DEV_PATH, O_RDONLY);
	if(keys_fd <= 0)
	{
		printf("open "DEV_PATH" device error!\n");
		return -1;
	}

    status = false;
    start = 0;
    stop = 0;
	while(1)
	{
		if(read(keys_fd, &t, sizeof(t)) == sizeof(t))
		{
			if(t.type==EV_KEY)
				if(t.value==0 || t.value==1)
				{
					printf("key %d %s\n", t.code, (t.value) ? "Pressed" : "Released");
                    if(t.code==0x100) {
                        if(t.value) {
                            if(!status) {
                                status = true;
                                start = getTimeNs();
                            }
                        } else {
                            stop = getTimeNs();
                            duration = ((double)(stop - start))/1000000000;//计算以秒为单位的运行时间,(结束时间-开始时间)
                            printf("按键时长 %0.6f 秒\n",duration);
                            if(duration>TIME_LONG) {
                                printf("长按:操作LED2\n");
                                status2 = !status2;
                                if(status2) {
                                    write(fd2, SYSFS_GPIO_LED_VAL_H, sizeof(SYSFS_GPIO_LED_VAL_H));
                                } else {
                                    write(fd2, SYSFS_GPIO_LED_VAL_L, sizeof(SYSFS_GPIO_LED_VAL_L));
                                }
                            } else {
                                printf("短按:操作LED1\n");
                                status1 = !status1;
                                if(status1) {
                                    write(fd1, SYSFS_GPIO_LED_VAL_H, sizeof(SYSFS_GPIO_LED_VAL_H));
                                } else {
                                    write(fd1, SYSFS_GPIO_LED_VAL_L, sizeof(SYSFS_GPIO_LED_VAL_L));
                                }
                            }
                            status = false;
                        }
                    }
					if(t.code == KEY_ESC)
						break;

                    printf("\n");
				}
		}
	}
    close(fd1);
    close(fd2);
	close(keys_fd);
	return 0;
}

 

将上述代码保存为button_led.c,编译运行后部署到开发板,运行结果如下:

image.png  

 

六、总结

以上使用米尔提供的构建环境,构建出来的SDK工具,进行应用的基础开发。

SDK工具有了,那么其他的开发,大部分就和通常Linux环境下面的开发类似了。

当然,有一些根据系统硬件情况的不同,还是会有差异的,后续进一步开发过程中,再逐步分享。

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复