《智能家居》培训第三天------2019-01-07
目录:
一)如何把3字节数据转换为4字节数据
二)动态界面→触摸屏的实现
三)多个源文件编译以及链接库
四)cannot open shared object file的解决办法
五)界面转换函数的封装
六)音乐界面的实现
七)所想
八)总结
一)如何把3字节数据转换为4字节数据
1)我自己写的方法无法完美显示,虽然可以显示图片信息,但是整张图片都被染上了一层厚厚的深蓝色,代码如下,这段代码我还没有重新看看是哪里出错了
1 j=0; 2 for(i=0;i<800*480;i++) 3 { 4 bmp_buf[j]<<8; 5 a=bmp_buf[j]+bmp_buf[j+1]; 6 a<<8; 7 a+=bmp_buf[j+2]; 8 a>>8; 9 bmp_buf1[i]=a; 10 j+=3; 11 }
2)老师讲的方法如下,也是通过位操作实现,而且看起来很简洁明了,不像我那个一大串还不成功
1 int lcd_buf[800*480]; //int类型,4字节 2 char bmp_buf[800*480*3] //char类型,1字节 3 int i; 4 for(i=0;i<800*480;i++) 5 { 6 lcd_buf[i] = 0x00 <<24 | bmp_buf[3*i+2]<<16 | bmp_buf[3*i+1] <<8 | bmp_buf[3*i+0];
7 //0x00ff0000; //argb 8 }
知识:把两个字节前后拼接在一起,使用位运算符“|”,而不是用“+”,比如0xff00 | 0x00ff = 0xffff
二)动态界面→触摸屏的实现
(下面的内容可以不看了,直接看第五天的,触摸屏的详细介绍放在第五天,点击此链接跳转-------修改日期2019.1.11)
1)动态界面
动态界面就是可以和用户实现交互的界面,比如触摸,通过触摸屏幕使界面发生某种变化
2)触摸屏的原理
对于这块我目前还是没有真正理解,以下是我根据老师笔记以及培训时所讲得到的理解,如果大家有其他理解可以分享一下的话就谢谢啦
①“触摸屏”是一种设备文件,意思就是说有这么一个文件,这个文件上的内容专门用于描述用户对屏幕触摸的操作。
②当用户点击触摸屏时,linux系统就会记录下用户的操作,比如记录下所触摸位置的xy坐标,然后把这个记录下来的信息是保存到这个“触摸屏”文件中。
③那么触摸位置就确定了,这个时候我们就只需要读取出这个文件中保存的位置坐标,就可以得到用户触摸的位置,根据此位置就可以实现自己想要实现的功能。
④举个例子:我们希望当用户点击某个区域时,播放一首歌,那么相应的逻辑就是→用户触摸屏幕→触摸位置的坐标被保存到“触摸屏”文件中→从该文件中读取用户触摸的位置→判断该位置是不是播放音乐的位置→如果是就播放音乐
3)检测触摸屏操作的实现
①对于触摸屏来说,linux系统把它当做一种输入设备,在目录“/usr/include/linux”下的input.h文件中描述了触摸屏操作。
1 /* 2 * The event structure itself 3 */ 4 5 struct input_event { 6 struct timeval time; //事件发生的时间 7 __u16 type; //事件发生的类型:触摸屏 8 __u16 code; //x轴 或者 Y轴 9 __s32 value; //x的坐标或者y的坐标 10 };
②老师已经把检测触摸屏操作封装成了一个库,我们只需要直接调用函数get_x_y(&x,&y);就可以得到x,y的坐标了,老师在上课的时候也有讲解这个函数怎么写,但是由于时间问题就没有细讲,这部分就直接给个函数接口,因此此处不做太多详细描述。(给自己的话:可以看当日笔记了解更多)
三)多个源文件编译及链接库
1)多个源文件编译,源文件之间用空格隔开
比如触摸操作函数被封装为单个源文件ts.c,主程序在main.c中,现在要把这两个文件同时编译,生成一个传入开发板的文件main,编译语法为:arm-linux-gcc main.c ts.c -o main
2)链接库
小知识:动态库------未作深入学习,只知道其中的代码是不可见的,是linux下后缀为.so的文件。
用上述语句编译会产生错误,原因在于:触摸函数所在的源文件ts.c里的某些函数,需要使用到一个动态库里的内容,这个动态库才是最主要的,检测触摸的操作都是靠这个库来实现的,正确的编译语法如下:
arm-linux-gcc main.c ts.c -o main -L ./tslib/ -lts
-L ----- 表示要链接动态库
./tslib/ ----- 动态库所在的目录
-lts ----- 具体的动态库
四)cannot open shared object file的解决办法
错误提示:./aa: error while loading shared libraries: libts-0.0.so.0: cannot open shared object file: No such file or directory
上述错误是在执行编译生成的main文件时产生的,原因已经忘记,老师发送了一个压缩包和一个文件给我们,让我们根据以下进行操作,然后就解决问题了
1 1)上传tslib.tar.gz 2 rx tslib.tar.gz 3 2)在开发板上解压tslib.tar.gz到根目录(/) 4 [root@GEC210 /]# tar zxvf tslib.tar.gz 5 3)上传profile配置文件到 /etc目录下,替换原来的profile 6 cd /etc ----- 进入该目录 7 rx profile ----上传文件 8 4)重启开发板---reboot 9 5)进入tslib/bin ---- 10 [root@GEC210 /]# cd tslib/ 11 [root@GEC210 /tslib]# ls 12 bin etc include lib 13 [root@GEC210 /tslib]# cd bin/ 14 [root@GEC210 bin]# ls 15 ts_calibrate ts_harvest ts_print ts_print_raw ts_test 16 [root@GEC210 bin]# ./ts_calibrate ----进行触摸屏测试 17 校准:左上角 右上角 右下角 18 左下角 中心 ----依次点击,完成OK
触摸屏测试失败了,手上的触摸屏有问题,无法检测到触摸操作,第二天换了个板子就可以了,但换的那个板子其实触摸也还是有点问题。
五)界面转换函数的封装
1)为什么要封装函数
我的理解就是为了让main.c源文件看起来更加简洁,功能分区更加明显,为以后进行代码修改提供了方便。
2)如何封装界面转换函数
把昨天界面显示的代码全部封装到一个函数里面,再加个参数char *pathname,表示要显示的图片路径,在main函数里直接调用该函数就可以了(如:show_screen("my_screen.bmp")显示my_screen.bmp这张图)
int show_screen(char* pathname) { //[1]打开屏文件和图片--bmp int lcd_buf[800*480]; char bmp_buf[800*480*3]; int i,fd,fd_bmp; fd = open("/dev/fb0",O_WRONLY); if(fd == -1) { printf("open lcd error\n"); return -1; } fd_bmp = open(pathname,O_RDONLY); //与可执行程序同一目录 if(fd_bmp == -1) { printf("open bmp error\n"); return -1; } //偏移掉图片的文件信息---54B --- lseek lseek(fd_bmp,54,SEEK_SET); //[2] 读取bmp图片的数据存放在数组中 char bmp[800*480*3] read(fd_bmp,bmp_buf,800*480*3); //[3] 图片3字节数据转换屏对应4字节的数据 for(i=0;i<800*480;i++) { lcd_buf[i]=0x00<<24|bmp_buf[3*i+2]<<16|bmp_buf[3*i+1]<<8|bmp_buf[3*i+0]; } //[4] 把图片的坐标系转屏的坐标系统 //[5] 把数据写入到屏中 write(fd,lcd_buf,480*800*4); //[6] 关闭文件 close(fd); close(fd_bmp); }
六)音乐界面的实现
1)今日任务:实现功能------>进入主界面→用户点击“音乐”→进入音乐界面→该界面有以下功能:播放、暂停\继续、停止、上一首、下一首、返回主界面
2)实现逻辑
3)音乐界面与对应触摸位置
4)代码(代码包含第四天学习的内容,整个框架是今天也就是第三天培训学的)
1 int main() 2 { 3 int x,y; 4 int pause_flag=1; //用于判断是暂停歌曲还是继续歌曲 5 //打开触摸屏 6 my_tsopen(); 7 while(1) 8 { 9 //一级界面----主界面 10 show_screen("./my_screen.bmp"); 11 //等待用户点击,获取点击的x,y的坐标 12 get_x_y(&x,&y); 13 //若点击“音乐”则进入二级界面----音乐 14 if((x>=240&&x<=340)&&(y>=200&&y<=260)) 15 { 16 //显示音乐界面 17 show_screen("./music_screen2.bmp"); 18 while(1) 19 { 20 //等待用户点击,获取x,y的坐标 21 get_x_y(&x,&y); 22 if((x>=25&&x<=125)&&(y>=400&&y<=450))//点击播放 23 { 24 music_play(); 25 }else if((x>=160&&x<=260)&&(y>=400&&y<=450)){ //点击暂停 26 switch(pause_flag) 27 { 28 case 1:music_pause();pause_flag++;break; //第一次点击暂停为暂停音乐 29 case 2:music_continue();pause_flag--;break; //第二次点击暂停为继续音乐 30 } 31 }else if((x>=300&&x<=400)&&(y>=400&&y<=450)){ //点击停止 32 music_stop(); 33 }else if((x>=440&&x<=560)&&(y>=400&&y<=450)){ //点击上一首 34 music_previous(); 35 }else if((x>=620&&x<=740)&&(y>=400&&y<=450)){ //点击下一首 36 music_next(); 37 }else if((x>=690&&x<=780)&&(y>=50&&y<=100)){ //点击返回 38 music_back(); 39 break; 40 } 41 } 42 } 43 } 44 }
5)第四天培训实现播放等功能,今天就只是制作好音乐界面以及写好一个框架就行。
七)所想
1)今天没什么特别的想法,就只是因为触摸屏感应不了触摸而有一点伤心与焦急,晚上把框架码好了却无法在板子上试一下,希望自己写的代码没有问题。
八)总结
1)学习了如何通过位操作实现数据类型转换
2)封装的思想
3)C指针初始化问题:定义指针变量时可以不初始化,但是在使用指针变量时一定一定要先初始化
4)写了个音乐框架,制作了3张音乐界面图,其余两张如下: