linux应用开发篇
1、应用编程点灯:
使用交叉编译器
source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
2022.5.15 GPIO
linuxc 应用文档p526控制gpio输出
在GPIO中断测试章节中,使用到了 poll()
多路转接。作用:检测文件当前状态是否就绪,是不是需要使用到的状态。
文档交叉P475。
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
截取中断部分重要代码 P532。
这里用到了access函数,解释说明如下:access函数用法,主要功能是判断进程时候可以对文件进行相应的操作。
//open file_path
sprintf(gpio_path,"/sys/class/gpio%s",argv[1]);
//如果GPIO不存在就将GPIO导出,判断文件是否存在。
if (access(gpio_path,F_OK)){
int len;
int fd;
if (0 > (fd = open("/sys/class/gpio/export",O_WRONLY))){
perror("open error");
exit(-1);
}
len = strlen(argv[1]);
if (len != write(fd,argv[1],len)){
perror("write error");
exit(-1);
}
close(fd);
}
if (gpio_config("direction","in"))
exit(-1);
if (gpio_config("edge","both"))
exit(-1);
if (gpio_config("active_low","0"))
exit(-1);
sprintf(file_path,"%s/%s",gpio_path,"value");
if (0 > (pfd.fd = open(file_path,O_RDONLY))){
perror("open error");
exit(-1);
}
pfd.events = POLLPRI;
read(pfd.fd,&val,1);
while(1)
{
if (0 > (ret = poll(&pfd,1,-1))){
perror("poll error");
exit(-1);
}
else if (ret == 0){
fprintf(stderr,"poll timeout.\n");
continue;
}
//校验高优先级数据是否可读
if (pfd.revents & POLLPRI){
if (0 >lseek(pfd.fd,0,SEEK_SET))
{
perror("lseek error");
exit(-1);
}
if (read(pfd.fd,&val,1)<0){
perror("read error");
exit(-1);
}
printf("GPIO 中断触发<value = %c>\n",val);
}
}
2022.5.16 输入设备
linuxc 应用文档p537
输入设备,这章节中判断输入设备的状态和数据解析最重要的是用到了 个 struct input_event
结构体。把握住这个结构体就好啦!!!
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
type
:type 用于描述发生了哪一种类型的事件。比如:鼠标事件。
code
:code 表示该类事件中的哪一个具体事件。
例如:
value
:内核每次上报事件都会向应用层发送一个数据 value,对 value 值的解释随着 code 的变化而变化。
多点触摸:MT 协议之 Type B 协议 P549
获取触摸点信息。
ioctl()
函数P553的原型列出:
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
对于 input 输入设备,对其执行 ioctl()操作需要使用这些宏,不同的宏表示不同请求指令;譬如使用EVIOCGNAME 宏获取设备名称,使用方式如下:
char name[100];
ioctl(fd, EVIOCGNAME(sizeof(name)), name);
获取触摸屏支持的最大触摸点数:
使用ioctl()
函数将触摸屏信息写入info结构体中。
struct input_absinfo info;
int max_slots; //最大触摸点数
if (0 > ioctl(fd, EVIOCGABS(ABS_MT_SLOT), &info))
perror("ioctl error");
max_slots = info.maximum + 1 - info.minimum;
例程代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
int main(int argc, char *argv[])
{
struct input_event in_event = {0};
int x,y;
int down;
int valid;
int fd = -1;
if (argc<2){
fprintf(stderr, "usage: %s <input-dev>\n", argv[0]);
exit(-1);
}
if (0>open(argv[1],O_RDONLY)){
perror("open error");
exit(-1);
}
x=y=0;
down=-1;
valid=0;
for (;;)
{
if (sizeof(struct input_event)!=read(fd,&in_event,sizeof(struct input_event))){
perror("open error");
exit(EXIT_FAILURE);
}
switch(in_event.type){
case EV_KEY: //按键事件
if (BTN_TOUCH == in_event.code){
down = in_event.value;
valid = 1;
}
break;
case EV_ABS: //绝对位移事件
switch(in_event.code){
case ABS_X://x坐标
x = in_event.value;
valid = 1;
break;
case ABS_Y://y
y = in_event.value;
valid = 1;
break;
}
break;
case EV_SYN: //同步事件
if (SYN_REPORT == in_event.code){
if(valid){
switch(down){
case 1://y
printf("按下(%d %d)\n",x,y);
break;
case 0:
printf("按下(%d %d)\n",x,y);
break;
case -1:
printf("移动(%d %d)\n",x,y);
break;
}
valid = 0;//重置valid
down = -1;//重置down
}
}
break;
}
}
exit(0);
}
2022.5.18 FrameBuffer应用编程
介绍P583。