2018年七月实训笔记-03
7月5日
Q:今天做了些什么?
A:主要做了以下工作
学习如何使用触摸屏和了解输入子系统:
本次使用的开发板是电容式触摸屏。要获得手指点击的开发板的位置,需要用到/dev/input/event0。而在linux系统里,所有的输入类设备驱动都统一由输入子系统管理,一般都是字符设备驱动。在输入子系统里面,所有的输入设备都统一在输入子系统里面(/dev/input/event0)。
这里介绍一下输入类事件结构体:
struct input_event {
struct timeval time; // 时间
__u16 type; // 输入的类型(鼠标、键盘、触摸屏……)
__u16 code; // 相应类型的事件(如果是触摸屏,可能会是X轴)
__s32 value; // 相应的类型的事件具体的值(触摸屏--》X--》400)
};
更加详细的内容可以参考这篇文章:https://blog.csdn.net/liwei405499/article/details/42025123
其中,type表明了输入的类型,触摸屏输入对应的值为:0x03,此时code的值代表绝对坐标轴向,当值为0x00时代表x轴,x坐标值保存在value中,y轴同理,对应的code值为0x02
(注:此处未验明是否通用)
项目程序的框架搭建:
即本次项目的程序框架:
本次项目将会实现的功能包括:相册,播放音乐,播放视频,拍照,录像,语音识别,基于嵌入式的智能安防系统等模块。据此对界面进行大致设计。
主程序(main.c)负责初始化界面,并且提供进入各个功能的入口。各个功能将作为独立的模块开发。
主程序开启了一个用于获取触摸点信息的线程。这样可以在主程序处理某些任务(如播放音乐时),仍能够进行触摸响应。
JPEG格式的图片显示:
(感觉这部分可以单独再开一篇讲了)
Q:今天遇到了什么问题?
A:
1.解决开发板开机启动程序问题
开发板开机时会自动启动一个程序,该程序是开发板生产商预设的程序,可通过修改系统配置文件禁止该程序开机启动(我一直误以为该界面是linux系统的一种桌面)
具体步骤如下:
使用vi编辑器打开/etc/profile 文件,找到了一行代码:
cd /IOT
./iot
用#号(shell脚本的注释符号)注释这两行即可。同理,若想自定义开机启动程序,也可以按如上格式编写代码。注意保存和使用source /etc/profile 命令使配置生效。
2.触摸屏,屏幕
一直将这两个概念对应成了一件事物。实际上,虽然开发板看起来只有一个屏幕,但实际上包括了专门用于显示的屏幕和专门用于触摸输入的触摸屏。屏幕对应的设备文件是/dev/fb0,后者我们需要获取点击坐标,用到了输入子系统中的/dev/input/event0。
3.段错误
程序运行后报错:segmentation fault。
由于开发板不能安装gdb来调试,因此只能使出最基本的"printf大法"。经过排除发现段错误发生在strcpy函数中。查看手册,
char *strcpy(char *dest, const char *src);
用法:The strcpy() function copies the string pointed to by src,including the terminating null byte ('\0'), to the buffer
pointed to by dest. The strings may not overlap, and the destination string dest must be large enough to receive the copy.
以我这样飘过四级的英语水准来翻译一下:
“该函数将会赋值src指针指向的字符串,包括它的\0一起拷贝到dest指针下。”接下来的就很重要了,它说:“字符串(源)可能不会重叠,且目的字符串必须足够大,以便能够接受复制”。
在我的代码中,我定义了一个字符指针用来保存字符串,形式如下:char *path="/temp";并尝试复制给另一个已经定义好的字符串指针,这个字符指针初始化分配的空间略小于path,所以发生了这样的错误。
不得不说C语言没有字符串类型真的很不方便(或者说高级语言定义了字符串类型真是太方便了。),对于字符串操作虽然有string.h定义的几个函数——strcpy(复制),strlen(求长度),strcat(字符串拼接)等等,但是这几个函数还是有很大限制的。
Q:今天有什么收获?
A:在参考项目框架代码时,考虑整个程序经常出现“点击,执行”这样的模式,结合之前对Winform控件的学习,希望能将该模式抽象为一种控件,定义如下:
/*定义button结构体*/
struct button
{
int id;//标识button,与其他button的区分
int x;
int y;
int width;
int height;
int enable;//按钮是否可用
char* buttonface;
void(*button_click)();//点击函数
};
typedef struct button Button;
之后如需添加控件,只需要初始化该结构体的各项内容。其中,函数指针button_click的使用可以统一化点击事件。使得主程序的处理逻辑更加简单。(至少从形式上是这样的)
点击触发如下:
/*按钮的触发函数*/
int button_trigger(int x,int y,Button but )
{
if(but.enable==1)//当前按钮可用
{
if(x>but.x&&x<but.x+but.width)//判断x是否符合范围
{
if(y>but.y&&y<but.y+but.width)//判断y是否符合范围
{
return 1;
}
}
return 0;
}
}
可以省去对每个按钮单独执行点击判断。