一、需求分析 智能家居系统是一种近年来兴起的智能化系统,在家庭场合基本都能看到它的身影,各种家居通过一个智能控制终端来进行人机交互。本课题基于粤嵌GEC-6818开发平台,定制的Linux系统,通过C语言的编程,经过交叉编译环境,让编译的文件能够直接适用于ARM开发板。用7寸LCD电容式触摸屏作为人机互交的方式,做到可以LED控制、液晶屏检测、报警控制、电子相册、音乐播放、家电控制的功能,显示相应的界面。具有音频输出的功能,获取屏幕触摸点的坐标,实现界面上相应的功能。 通过这次的设计,掌握了ARM的结构体系,了解了部分的Linux命令,对文件的读写操作等,初步掌握了交叉编译方式,加强了对嵌入式产品的认知。同时,在本课程设计时的调试、排错,让我们对C语言进行了一次查漏补缺,也巩固了C语言基础。让我们能够用团队的力量,对ARM系列的开发板进行开发,用固定的硬件设备实现多种功能,了解ARM开发的文件读取方式、交叉编译环境。扩大了我们的眼界,学会了无显示界面时使用Linux命令操作设备。
二、设计过程 1、嵌入式开发环境搭建 1 2 3 4 5 6 7 8 9 10 安装交叉编译器: arm-linux-gnueabi-5.4.0.tar.xz 1)复制arm-linux-gnueabi-5.4.0.tar.xz到/usr/local/arm 2)解压命令arm-linux-gnueabi-5.4.0.tar.xz 3)然后配置下编译环境路径: 在/usr/local/arm下输入:vi /etc/profile 加上下面代码: export PATH=/usr/local/arm/5.4.0/usr/bin:$PATH 4)重启 不重启:输入source /etc/profile使之生效
2、进行在液晶屏上显示单色–液晶屏检测的功能 打开液晶屏—open()
1 2 3 4 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open (const char *pathname, int flags) ;
参数说明: const char *pathname —–文件的路径名。液晶屏:“/dev/fb0” int flags —- 文件的访问属性:O_RDONLY, O_WRONLY, or O_RDWR2、写入颜色数据—write() 显示红色:
1 2 3 4 5 int lcd_buf[800 *480 ];for (int i=0 ; i<800 *480 ; i++) lcd_buf[i] = 0x00ff0000 ; write(fd_lcd, lcd_buf, 800 *480 *4 ); close(fd_lcd);
3、学会显存映射 液晶屏的驱动是在Linux内核中工作的,显存也是有Linux内核来管理的。应用程序操作显存的时候,就会有一个应用程序访问Linux内核的系统调用过程,这样如果数据量比较大、而且数据访问比较频繁,此时效率就比较低。这样可以使用内存映射的方式,将Linux内核中的显存映射到应用程序中,在应用程序中直接访问这个显存。 通常使用内存映射的硬件:液晶屏(显存)、声卡、摄像头 显存映射,在应用程序中得到显存的首地址—mmap()
1 2 3 #include <sys/mman.h> void *mmap (void *addr, size_t length, int prot, int flags, int fd, off_t offset) ;
4、访问触摸屏,获取坐标的过程。 1)打开触摸屏设备文件 2)读取触摸屏的数据
1 2 3 #include <linux/input.h> struct input_event ts_data ;read(fd_ts, &ts_data, sizeof (struct struct input_event));
3)从数据中获取坐标 分析struct inputevent的成员数据。从中得到触摸屏的坐标。
1 2 3 4 5 6 7 8 printf ("type=%d, code=%d,value=%d\n" , ts_data.type, ts_data.code,ts_data.value);if (ts_data.type == EV_ABS ){ if (ts_data.code == ABS_X) x = ts_data.value; else if (ts_data.code == ABS_Y) y = ts_data.value; }
4)关闭触摸屏
5、使用液晶屏显示bmp图片 1)打开bmp图片
1 2 3 4 5 6 7 int fd_bmp;fd_bmp = open(bmp_name, O_RDONLY); if (fd_bmp == -1 ){ perror("open bmp" ); return -1 ; }
2)移动文件指针54B,移动到RGB数据区
3)读取RGB数据,800480 3
1 2 char lcd_buf[800 *480 *3 ];read();
4)关闭文件
5)打开液晶屏—open() 6)显存映射,得到显存的首地址—mmap()
1 2 3 4 5 6 7 int *lcd_base = NULL ;lcd_base = (int *)mmap(NULL , 800 *480 *4 , PROT_READ|PROT_WRITE, MAP_SHARED, fd_lcd, 0 ); if (lcd_base == NULL ){ printf ("lcd mmap error\n" ); return -1 ; }
7)通过显存首地址,直接bmp_buf[]写入显存
1 2 for (int i=0 ;i<800 *480 ;i++) *(lcd_base+i) = (bmp_buf[3 *i+2 ]<<16 ) + (bmp_buf[3 *i+1 ] <<8 ) + bmp_buf[3 *i];
8)解除显存映射—-munmap()
1 munmap(lcd_base, 800 *480 *4 );
9)关闭液晶屏—-close()
6、学会多线程编程 1)创建线程
1 2 3 #include <pthread.h> int pthread_create (pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) ;
Compile and link with -pthread.
2)子线程的退出
1 2 #include <pthread.h> int pthread_cancel (pthread_t thread) ;
参数: pthread_t thread —- 线程的ID
7、学会驱动设计的流程
a、设计一个模块(module) 在Linux内核中,驱动程序是以内核模块的形式存在,module相当于是一个盒子,里面放了一个驱动。驱动编译的时候,每个盒子独立编译,生成一个ko文件(驱动的安装文件),驱动可安装(#insmod led_drv.ko),可卸载(#rmmod led_drv.ko)。
1)module的入口—驱动的安装函数 完成资源的申请,如GPIO口;注册驱动到内核。
2)module的出口—驱动的卸载函数 安装函数的反函数,释放资源,注销驱动。
3)module的描述 可有可无,主要是描述module的作者,版本,协议、作用…….
b、申请硬件资源(GPIO) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <linux/gpio.h> int gpio_request (unsigned gpio, const char *label) ; int gpio_direction_input (unsigned gpio) ; int gpio_direction_output (unsigned gpio, int value) ; int gpio_get_value (unsigned gpio) ; void gpio_set_value (unsigned gpio, int value) ; void gpio_free (unsigned gpio) ;
S5P6818的GPIO分成了5个组(ABCDE),每个组有32个引脚(0~31)。在Linux内核中,给每个GPIO分了一个ID,这个ID是32无符号整数,用这个ID(unsigned gpio)来表示这个GPIO。
GPIO口号是和处理器相关的。
1 2 3 4 5 6 7 8 9 enum { PAD_GPIO_A = (0 * 32 ), PAD_GPIO_B = (1 * 32 ), PAD_GPIO_C = (2 * 32 ), PAD_GPIO_D = (3 * 32 ), PAD_GPIO_E = (4 * 32 ), PAD_GPIO_ALV = (5 * 32 ), };
c、注册驱动 需要利用Linux内核的驱动模型,在安装驱动的时候,将设计的驱动注册到Linux内核中。简单的驱动模型是混杂设备驱动模型。
使用混杂设备驱动模型—miscdevice #include <linux/miscdevice.h>
1)定义一个混杂设备 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 struct miscdevice { int minor; const char *name; const struct file_operations *fops ; struct list_head list ; struct device *parent ; struct device *this_device ; const char *nodename; umode_t mode; }; static struct miscdevice GEC6818_misc_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "led_drv" , .fops = &gec6818_led_fops, }; #### 2 )混杂设备的注册 misc_register(struct miscdevice * misc); #### 3 )混杂设备注销 int misc_deregister (struct miscdevice *misc) ;
d、定义并初始化文件操作集 提供给应用程序的接口,open()\write()\close() #include <linux/fs.h>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 struct file_operations { struct module *owner ; ssize_t (*write) (struct file *, const char __user *, size_t , loff_t *); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); }; int gec6818_led_open (struct inode inode, struct file filp) { } ssize_t gec6818_led_write (struct file *filp, const char __user *buf, size_t len, loff_t *off) { } int gec6818_led_close (struct inode *inode, struct file *filp) { } static struct file_operations gec6818_led_fops = { .owner = THIS_MODULE, .write = gec6818_led_write, .open = gec6818_led_open, .release = gec6818_led_close, };
e、驱动程序的编译 编译驱动程序和编译应用程序完全不同。编译应用程序使用的是编译器中的库;编译驱动程序使用的是内核源码。 编译驱动程序之前,首先要编译内核源码。
1)使用的内核源码
2)将内核源码放在ubuntu中,注意不要放在共享目录下/mnt/hgfs /home/gec/6818GEC.tar.gz
3)解压内核源码 1 tar -jxvf 6818GEC.tar.gz
4)编译uboot 1 2 3 4 gec@ubuntu:~$ cd 6818GEC/ gec@ubuntu:~/6818GEC$ ls buildroot GEC6818uboot kernel linux mk out prebuilts prototype tools gec@ubuntu:~/6818GEC$ ./mk -u
5)编译Linux内核 1 gec@ubuntu:~/6818GEC$ ./mk -k
6)编写一个驱动程序的Makefile 1 2 3 4 5 6 7 8 9 10 11 obj-m := led_drv.o KERNELDIR:=/home/gec/6818GEC/kernel CROSS_COMPILE:=/home/gec/6818GEC/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi- PWD:=$(shell pwd ) default: $(MAKE) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules clean: rm -rf *.o *.order .*.cmd *.ko *.mod.c *.symvers *.tmp_versions
7)编译驱动 1 2 3 4 5 6 7 8 9 gec@ubuntu:/mnt/hgfs/上课笔记/day5/project/led_drv$ make make ARCH=arm CROSS_COMPILE=/home/gec/6818GEC/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi- -C /home/gec/6818GEC/kernel M=/mnt/hgfs/上课笔记/day5/project/led_drv modules make[1]: Entering directory '/home/gec/6818GEC/kernel' CC [M] /mnt/hgfs/上课笔记/day5/project/led_drv/led_drv.o Building modules, stage 2. MODPOST 1 modules CC /mnt/hgfs/上课笔记/day5/project/led_drv/led_drv.mod.o LD [M] /mnt/hgfs/上课笔记/day5/project/led_drv/led_drv.ko make[1]: Leaving directory '/home/gec/6818GEC/kernel'
8)通过串口将led_drv.ko下载到开发板 9)安装驱动
8、实现音乐播放 a、音乐播放器 音乐一般都是mp3格式的,需要解压和播放。播放器一般使用madplay,开源免费的播放器。 检查madplay是否安装:
1 2 [root@GEC6818 /mnt/udisk] /usr/bin/madplay
如何移植一个madplay。 去网上下载madplay的源码(多个软件包),经过配置、编译、布置才可以使用。
1 2 3 4 5 6 7 8 [root@GEC6818 /] [root@GEC6818 /] ./IOT/mp3 ./IOT/mp3/end.mp3 ./IOT/mp3/left.mp3 ./IOT/mp3/right.mp3 ./IOT/mp3/test.mp3 ./usr/local/Qt-Embedded-5.7.0/examples/svg/embedded/desktopservices/data/sax.mp3
播放:
b、编写程序,调用madplay播放器 1 2 #include <stdlib.h> int system (const char *command) ;
播放音乐:
1 2 system(“madplay /IOT/test.mp3”); system(“madplay /IOT/test.mp3 -r ”);
c、madplay的使用 创建一个新的进程,这个进程调用了madplay,用来播放mp3. 如何实现暂停、继续和停止。向madplay这个进程发送信号。 kill命令,发信号给进程的ID(PID) killall命令,发信号给进程的名字 PID是会变的。
1 2 3 4 5 6 7 8 system(“madplay /IOT/test.mp3 &”); system(“killall -STOP madplay &”); system(“killall -CONT madplay &”); system(“killall -KILL madplay &”);
注意: 声卡只有一个,在一个时刻只能播放一个mp3。否则声卡会报busy做错。
9、学会多线程编程后的多线程设计 a、创建线程 1 2 3 4 5 6 #include <pthread.h> int pthread_create (pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) ; Compile and link with -pthread.
参数说明
1 2 3 4 pthread_t *thread ---新创建的线程的ID,也是一个正整数const pthread_attr_t *attr ----线程的属性,一般为NULL void *(*start_routine) (void *) -----创建的线程的执行函数void *arg -----向子线程执行函数传递的参数
返回值:
1 2 3 RETURN VALUE On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.
注意:
1.编译多线程程序的时候,需要引用多线程库,需要加一个后缀 -lpthread 2.如果主线程退出,这个主线程常见的所有子线程都会自动退出。 3.子线程和主线程共享全局变量
b、子线程的退出 1)return 0,子线程直接退出 2)如果一个线程,让另一个线程退出,如何实现。 例:在主线程中,让子线程退出??
1 2 #include <pthread.h> int pthread_cancel (pthread_t thread) ;
参数: pthread_t thread —- 线程的ID
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 触屏的坐标 //全局变量 void color_thread() //子线程 { while(1)//不会产生阻塞 { 显示红色 显示绿色 显示蓝色 } } main() //主线程 { 判断是否进入循环播放单色(液晶屏检测) thread_create()创建一个子线程void color_thread() ,用来循环显示单色。 获取触摸屏坐标 //可能会产生阻塞。但是子线程可以持续运行 判断触摸屏坐标,否是退出循环播放单色,返回主控界面。 若是,pthread_cancel()退出子线程 }
10、进行各个功能的整合 编写各个单独功能函数后再编写Makefile来进行统一编译,生成最终开发板用的可执行文件main。 Makefile如下:
1 2 3 4 5 6 main:main.o lcd.o touch.o led.o beep.o arm-linux-gcc -o main $^ -lpthread %.o : %.c arm-linux-gcc -o $@ $< -c clean: rm *.o main
三、功能设计 1、LED控制功能 2、实现液晶屏显示界面,附带液晶屏检测功能 3、实现触摸屏功能 4、实现音乐播放 5、实现数码相册控制 6、蜂鸣器控制功能
四、运行结果及分析 1、LED控制功能
程序运行效果如上,LED驱动功能正常,可以控制LED的亮灭。 2、实现液晶屏显示界面,附带液晶屏检测功能
程序运行效果如上,功能正常,屏幕内容完美显示。 3、实现触摸屏功能
程序运行效果如上,可以通过触摸屏来判断点击的方位,正常切换界面。 4、音乐播放功能 音乐播放功能正常,能够控制音乐的暂停和播放。 5、实现数码相册控制 程序运行效果如上,数码相册功能正常。 6、蜂鸣器控制功能 驱动安装正常,程序能够正常控制蜂鸣器的开启和关闭。
五、总结 本次实训是做一个基于GEC-6818开发平台的智能家居控制系统,利用定制的Linux系统,通过C语言的编程,经过交叉编译环境,让编译的文件能够直接适用于ARM开发板。用7寸LCD电容式触摸屏作为人机互交的方式,可以切换相册、音乐、led蜂鸣器等功能,并显示相应的界面。 在过程中我收获了非常非常充足的嵌入式知识,包括驱动开发,应用开发,显存映射,掌握了ARM的结构体系,了解了部分的Linux命令,对文件的读写操作等,初步掌握了交叉编译方式,加强了对嵌入式产品的认知。同时,在本课程设计时的调试、排错,让我对C语言和linux环境下编程进行了一次查漏补缺,也巩固了C语言基础。让我对ARM系列的开发板进行开发,用固定的硬件设备实现多种功能,了解ARM开发的文件读取方式、交叉编译环境。也学会了无显示界面时使用Linux命令操作设备。这也让我对嵌入式开发产生的浓厚的兴趣。
附录:项目核心源程序 Main.c:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 #include <stdio.h> #include "lcd.h" #include "beep.h" #include "led.h" #include "touch.h" #include "pthread.h" #define MAIN 0 #define CTL 1 #define LED 2 #define LCDt 3 #define MUS 4 #define BEEP 5 #define DP 6 #define HA 7 void *check_lcd (void *arg) { while (1 ) { lcd_show_color(RED); sleep(1 ); lcd_show_color(GREEN); sleep(1 ); lcd_show_color(BLUE); sleep(1 ); lcd_show_color(YELLOW); sleep(1 ); lcd_show_color(WHITE); sleep(1 ); lcd_show_color(BLACK); sleep(1 ); } } void *digital_photo (void *arg) { while (1 ) { lcd_show_bmp("/pic/xx.bmp" ); usleep(50000 ); ts_get_xy(); lcd_show_bmp("/pic/jp.bmp" ); usleep(50000 ); ts_get_xy(); lcd_show_bmp("/pic/sl.bmp" ); usleep(50000 ); ts_get_xy(); } } int main (void ) { int mode=0 ; struct xy ts ; pthread_t tid_ts; lcd_show_bmp("/pic/main" ); while (1 ) { ts = ts_get_xy(); if (650 <ts.x && ts.x<800 && 420 <ts.y && ts.y<480 ) { lcd_show_bmp("/pic/control" ); mode = CTL; while (1 ) { ts = ts_get_xy(); if (!(ts.x==0 && ts.y==0 )) { printf ("position:(%d,%d)\n" ,ts.x,ts.y); } if (ts.x > 700 && ts.x < 800 && ts.y > 0 && ts.y < 60 ) { mode = CTL; lcd_show_bmp("/pic/control" ); printf ("BACK\n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 0 && ts.x < 100 && ts.y > 0 && ts.y < 60 && mode == CTL ) { mode = MAIN; lcd_show_bmp("/pic/main" ); printf ("BACK MAIN\n" ); ts.x=0 ;ts.y=0 ; } if ((60 <ts.x && ts.x<300 && 140 <ts.y && ts.y<200 && mode == CTL) || mode == LED) { mode = LED; lcd_show_bmp("/pic/led_ctrl" ); if (ts.x > 100 && ts.x < 250 && ts.y > 100 && ts.y < 160 ) { led_ctrl(LED1, LED_ON); printf ("LED1 on\n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 100 && ts.x < 250 && ts.y > 200 && ts.y < 260 ) { led_ctrl(LED1, LED_OFF); printf ("LED1 off\n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 100 && ts.x < 250 && ts.y > 300 && ts.y < 360 ) { led_ctrl(LED2, LED_ON); printf ("LED2 on\n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 100 && ts.x < 250 && ts.y > 400 && ts.y < 460 ) { led_ctrl(LED2, LED_OFF); printf ("LED2 off\n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 530 && ts.x < 680 && ts.y > 100 && ts.y < 160 ) { led_ctrl(LED3, LED_ON); printf ("LED3 on\n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 530 && ts.x < 680 && ts.y > 200 && ts.y < 260 ) { led_ctrl(LED3, LED_OFF); printf ("LED3 off\n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 530 && ts.x < 680 && ts.y > 300 && ts.y < 360 ) { led_ctrl(LED4, LED_ON); printf ("LED4 on\n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 530 && ts.x < 680 && ts.y > 400 && ts.y < 460 ) { led_ctrl(LED4, LED_OFF); printf ("LED4 off\n" ); ts.x=0 ;ts.y=0 ; } } if (ts.x > 60 && ts.x < 300 && ts.y > 240 && ts.y < 300 && mode == CTL) { mode = LCDt; int ret; ret = pthread_create(&tid_ts, NULL , check_lcd, NULL ); if (ret < 0 ) { perror("create ts_thread error" ); return -1 ; } while (1 ) { ts = ts_get_xy(); if (ts.x > 700 && ts.x < 800 && ts.y > 0 && ts.y < 60 ) { pthread_cancel(tid_ts); break ; } } mode=CTL; ts.x=0 ;ts.y=0 ; } if ((ts.x > 60 && ts.x < 300 && ts.y > 350 && ts.y < 420 && mode == CTL) || mode == MUS) { lcd_show_bmp("/pic/music.bmp" ); mode = MUS; if (ts.x > 30 && ts.x < 170 && ts.y > 210 && ts.y < 260 ) { printf ("Music begin\n" ); system("madplay /IOT/mp3/test.mp3 &" ); } if (ts.x > 135 && ts.x < 273 && ts.y > 300 && ts.y < 400 ) { printf ("Previous music \n" ); } if (ts.x > 515 && ts.x < 657 && ts.y > 300 && ts.y < 400 ) { printf ("Next music \n" ); } if (ts.x > 230 && ts.x < 370 && ts.y > 210 && ts.y < 260 ) { printf ("Music pause\n" ); system("killall -STOP madplay &" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 420 && ts.x < 560 && ts.y > 210 && ts.y < 260 ) { printf ("Music continue\n" ); system("killall -CONT madplay &" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 620 && ts.x < 760 && ts.y > 210 && ts.y < 260 ) { printf ("Music stop\n" ); system("killall -KILL madplay &" ); ts.x=0 ;ts.y=0 ; } } if ((ts.x > 460 && ts.x < 700 && ts.y > 140 && ts.y < 200 && mode == CTL )|| mode == BEEP) { mode = BEEP; lcd_show_bmp("/pic/beep_ctrl.bmp" ); if (ts.x > 120 && ts.x < 310 && ts.y > 200 && ts.y < 322 ) { beep_ctrl(BEEP_ON); printf ("Beep open \n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 490 && ts.x < 670 && ts.y > 200 && ts.y < 322 ) { beep_ctrl(BEEP_OFF); printf ("Beep stop \n" ); ts.x=0 ;ts.y=0 ; } } if (ts.x > 460 && ts.x < 700 && ts.y > 240 && ts.y < 300 && mode == CTL) { mode = HA; int ret; ret = pthread_create(&tid_ts, NULL ,digital_photo, NULL ); if (ret < 0 ) { perror("create ts_thread error" ); return -1 ; } while (1 ) { ts = ts_get_xy(); if (ts.x > 700 && ts.x < 800 && ts.y > 0 && ts.y < 60 ) { pthread_cancel(tid_ts); break ; } } mode=CTL; ts.x=0 ;ts.y=0 ; } if ((ts.x > 460 && ts.x < 700 && ts.y > 350 && ts.y < 420 )&& mode == CTL || mode == HA) { mode = HA; lcd_show_bmp("/pic/key.bmp" ); if (ts.x > 158 && ts.x < 298 && ts.y > 195 && ts.y < 255 ) { printf ("Fan:on \n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 158 && ts.x < 298 && ts.y > 320 && ts.y < 372 ) { printf ("Fan:off \n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 500 && ts.x < 640 && ts.y > 195 && ts.y < 255 ) { printf ("Air-conditioning:on \n" ); ts.x=0 ;ts.y=0 ; } if (ts.x > 500 && ts.x < 640 && ts.y > 320 && ts.y < 372 ) { printf ("Air-conditioning:off \n" ); ts.x=0 ;ts.y=0 ; } } if (ts.x > 650 && ts.x < 800 && ts.y > 420 && ts.y < 480 && mode == MAIN) { lcd_show_bmp("/pic/control" ); mode = CTL; ts.x=0 ;ts.y=0 ; } } ts.x=0 ;ts.y=0 ; } } return 0 ; }
touch.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include "touch.h" struct xy ts_get_xy (void ) { struct xy z ; int x,y; int fd_ts; fd_ts = open("/dev/input/event0" , O_RDONLY); if (fd_ts == -1 ) { perror("open ts" ); exit (-1 ); } struct input_event ts_data ; for (int i = 0 ; i < 6 ; i++) { read(fd_ts, &ts_data, sizeof (struct input_event)); if (ts_data.type == EV_ABS) { if (ts_data.code == ABS_X) x = ts_data.value*800 /1024 ; else if (ts_data.code == ABS_Y) y = ts_data.value*480 /600 ; } } z.x=x; z.y=y; close(fd_ts); return z; }
Touch.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #ifndef __TOUCH_H_ #define __TOUCH_H_ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <linux/input.h> #include <stdlib.h> struct xy { int x; int y; }; struct xy ts_get_xy () ;#endif
Lcd.c:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 #include <stdio.h> #include "lcd.h" int lcd_show_color (unsigned int color) { int lcd_fd; lcd_fd = open("/dev/fb0" ,O_RDWR); if (lcd_fd == -1 ) { perror("open lcd failed" ); return -1 ; } int *lcd_base = NULL ; lcd_base = mmap(NULL , 800 *480 *4 , PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0 ); if (lcd_base == NULL ) { printf ("lcd mmap error\n" ); return -1 ; } for (int i=0 ;i<800 *480 ;i++) *(lcd_base+i) = color; munmap(lcd_base, 800 *480 *4 ); close(lcd_fd); return 0 ; } int lcd_show_flag (unsigned int state) { int lcd_fd; int x,y; int buf2[480 ][800 ]; lcd_fd = open("/dev/fb0" ,O_RDWR); if (lcd_fd == -1 ) { perror("open lcd failed" ); return -1 ; } int *lcd_base = NULL ; lcd_base = (int *)mmap(NULL , 800 *480 *4 , PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0 ); if (lcd_base == NULL ) { printf ("lcd mmap error\n" ); return -1 ; } switch (state) { case JAPAN: for (x=0 ; x<480 ; x++) { for (y=0 ; y<800 ; y++) { if (0.8 *(x-240 )*(x-240 )+(y-400 )*(y-400 ) <= 150 *150 ) { buf2[x][y] = 0x00FF0000 ; } else { buf2[x][y] = 0x00FFFFFF ; } } } for (int x=0 ; x<480 ; x++) { for (int y=0 ; y<800 ; y++) *(lcd_base+x*800 +y) = buf2[x][y]; } break ; case RUS: for (y=0 ; y<480 /3 ; y++) for (x=0 ; x<800 ; x++) *(lcd_base+x+800 *y) = WHITE; for (y=480 /3 ; y<480 /3 *2 ; y++) for (x=0 ; x<800 ; x++) *(lcd_base+x+800 *y) = BLUE; for (y=480 /3 *2 ; y<480 ; y++) for (x=0 ; x<800 ; x++) *(lcd_base+x+800 *y) = RED; break ; default : break ; } munmap(lcd_base, 800 *480 *4 ); close(lcd_fd); return 0 ; } int lcd_show_bmp (char *bmp_name) { int lcd_fd; lcd_fd = open("/dev/fb0" ,O_RDWR); if (lcd_fd == -1 ) { perror("open lcd failed" ); return -1 ; } int *lcd_base = NULL ; lcd_base = (int *)mmap(NULL , 800 *480 *4 , PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0 ); if (lcd_base == NULL ) { printf ("lcd mmap error\n" ); return -1 ; } char buf[800 *480 *3 ]; int new_buf[800 *480 ]; int x, y; int bmp; bmp = open(bmp_name,O_RDONLY); if (bmp == -1 ) { printf ("打开BMP图片失败\n" ); return -1 ; } lseek(bmp,54 ,SEEK_SET); read(bmp,buf,800 *480 *3 ); close(bmp); for (y = 0 ; y < 480 ; y++) { for (x = 0 ; x < 800 ; x++) { new_buf[800 *(479 -y)+x] = buf[3 *(800 *y+x)]<<0 | buf[3 *(800 *y+x)+1 ]<<8 | buf[3 *(800 *y+x)+2 ]<<16 ; } } for (int i=0 ;i<800 *480 ;i++) *(lcd_base+i) = new_buf[i]; munmap(lcd_base, 800 *480 *4 ); close(lcd_fd); }
Lcd.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #ifndef _LCD_H #define _LCD_H 1 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/mman.h> #include <unistd.h> #define USSR 0 #define JAPAN 1 #define RUS 2 #define MAIN1 3 #define BLUE 0x000000FF #define RED 0x00FF0000 #define GREEN 0x0000FF00 #define WHITE 0x00FFFFFF #define YELLOW 0x00FFFF00 #define BLACK 0x00000000 int lcd_show_color (unsigned int color) ;int lcd_show_flag (unsigned int state) ;int lcd_show_bmp (char *bmp_name) ;#endif
Led.c:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <stdio.h> #include "led.h" int led_ctrl (unsigned char led_num, unsigned char led_state) { int led_fd; led_fd = open("/dev/led_drv" ,O_RDWR); if (led_fd == -1 ) { perror("open led failed" ); return -1 ; } char led_buf[2 ]; led_buf[1 ]=led_num;led_buf[0 ]=led_state; write(led_fd, led_buf, 2 ); close(led_fd); return 0 ; }
Led.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #ifndef __LED_H_ #define __LED_H_ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <linux/input.h> #include <stdlib.h> #define LED1 7 #define LED2 8 #define LED3 9 #define LED4 10 #define LED_ON 1 #define LED_OFF 2 int led_ctrl (unsigned char led_num, unsigned char led_state) ;#endif
Beep.c:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <stdio.h> #include "beep.h" int beep_ctrl (unsigned char beep_state) { int beep_fd; beep_fd = open("/dev/beep_drv" ,O_RDWR); if (beep_fd == -1 ) { perror("open led failed" ); return -1 ; } char beep_buf[1 ]; beep_buf[0 ]=beep_state; write(beep_fd,beep_buf, 1 ); close(beep_fd); return 0 ; }
Beep.h:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #ifndef __BEEP_H_ #define __BEEP_H_ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <linux/input.h> #include <stdlib.h> #define BEEP_ON 1 #define BEEP_OFF 0 int beep_ctrl (unsigned char beep_state) ;#endif
蜂鸣器驱动源文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 #include <linux/module.h> #include <linux/gpio.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include <linux/uaccess.h> #include "cfg_type.h" #define BEEP_GPIO PAD_GPIO_C + 14 #define BEEP_ON 1 #define BEEP_OFF 0 int gec6818_beep_open (struct inode *inode, struct file *filp) { printk(KERN_WARNING "gec6818 beep driver init\n" ); return 0 ; } ssize_t gec6818_beep_write (struct file *filp, const char __user *buf, size_t len, loff_t *off) { char beep_flag[1 ]; if (len != 1 ) return -EINVAL; if (copy_from_user(beep_flag, buf,len)) return -EFAULT; switch (beep_flag[0 ]){ case BEEP_OFF: gpio_set_value(BEEP_GPIO, 0 ); break ; case BEEP_ON: gpio_set_value(BEEP_GPIO, 1 ); break ; default : return -EINVAL; } return len; } int gec6818_beep_close (struct inode *inode, struct file *filp) { printk(KERN_WARNING "gec6818 beep driver close\n" ); return 0 ; } static const struct file_operations gec6818_beep_fops = { .owner = THIS_MODULE, .write = gec6818_beep_write, .open = gec6818_beep_open, .release = gec6818_beep_close, }; static struct miscdevice gec6818_misc_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "beep_drv" , .fops = &gec6818_beep_fops, }; static int __init gec6818_beep_init (void ) { int ret; gpio_free(BEEP_GPIO); ret = gpio_request(BEEP_GPIO, "BEEP" ); if (ret < 0 ) { printk(KERN_WARNING "gpio request error\n" ); return -1 ; } gpio_direction_output(BEEP_GPIO, 0 ); misc_register(&gec6818_misc_dev); printk(KERN_WARNING "gec6818 beep driver init\n" ); return 0 ; } static void __exit gec6818_beep_exit (void ) { gpio_free(BEEP_GPIO); misc_deregister(&gec6818_misc_dev); printk(KERN_WARNING "gec6818 beep driver exit\n" ); } module_init(gec6818_beep_init); module_exit(gec6818_beep_exit); MODULE_AUTHOR("1175595406@qq.com" ); MODULE_DESCRIPTION("BEEP driver for GEC6818)" ); MODULE_LICENSE("GPL" ); MODULE_VERSION("V1.0" );
LED驱动源文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 #include <linux/module.h> #include <linux/gpio.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include <linux/uaccess.h> #include "cfg_type.h" #define LED1_GPIO PAD_GPIO_E + 13 #define LED2_GPIO PAD_GPIO_C + 17 #define LED3_GPIO PAD_GPIO_C + 8 #define LED4_GPIO PAD_GPIO_C + 7 #define LED1 7 #define LED2 8 #define LED3 9 #define LED4 10 #define LED_ON 1 #define LED_OFF 2 int gec6818_led_open (struct inode *inode, struct file *filp) { printk(KERN_WARNING "gec6818 led driver init\n" ); return 0 ; } ssize_t gec6818_led_write (struct file *filp, const char __user *buf, size_t len, loff_t *off) { char led_flag[2 ]; if (len != 2 ) return -EINVAL; if (copy_from_user(led_flag, buf,len)) return -EFAULT; switch (led_flag[1 ]){ case LED1: if (led_flag[0 ] == LED_ON) gpio_set_value(LED1_GPIO, 0 ); else if (led_flag[0 ] == LED_OFF) gpio_set_value(LED1_GPIO, 1 ); else return -EINVAL; break ; case LED2: if (led_flag[0 ] == LED_ON) gpio_set_value(LED2_GPIO, 0 ); else if (led_flag[0 ] == LED_OFF) gpio_set_value(LED2_GPIO, 1 ); else return -EINVAL; break ; case LED3: if (led_flag[0 ] == LED_ON) gpio_set_value(LED3_GPIO, 0 ); else if (led_flag[0 ] == LED_OFF) gpio_set_value(LED3_GPIO, 1 ); else return -EINVAL; break ; case LED4: if (led_flag[0 ] == LED_ON) gpio_set_value(LED4_GPIO, 0 ); else if (led_flag[0 ] == LED_OFF) gpio_set_value(LED4_GPIO, 1 ); else return -EINVAL; break ; default : return -EINVAL; } return len; } int gec6818_led_close (struct inode *inode, struct file *filp) { printk(KERN_WARNING "gec6818 led driver close\n" ); return 0 ; } static const struct file_operations gec6818_led_fops = { .owner = THIS_MODULE, .write = gec6818_led_write, .open = gec6818_led_open, .release = gec6818_led_close, }; static struct miscdevice gec6818_misc_dev = { .minor = MISC_DYNAMIC_MINOR, .name = "led_drv" , .fops = &gec6818_led_fops, }; static int __init gec6818_led_init (void ) { int ret; gpio_free(LED1_GPIO); gpio_free(LED2_GPIO); gpio_free(LED3_GPIO); gpio_free(LED4_GPIO); ret = gpio_request(LED1_GPIO, "led1" ); if (ret < 0 ) { printk(KERN_WARNING "gpio request error\n" ); return -1 ; } gpio_request(LED2_GPIO, "led2" ); gpio_request(LED3_GPIO, "led3" ); gpio_request(LED4_GPIO, "led4" ); gpio_direction_output(LED1_GPIO, 1 ); gpio_direction_output(LED2_GPIO, 1 ); gpio_direction_output(LED3_GPIO, 1 ); gpio_direction_output(LED4_GPIO, 1 ); misc_register(&gec6818_misc_dev); printk(KERN_WARNING "gec6818 led driver init\n" ); return 0 ; } static void __exit gec6818_led_exit (void ) { gpio_free(LED1_GPIO); gpio_free(LED2_GPIO); gpio_free(LED3_GPIO); gpio_free(LED4_GPIO); misc_deregister(&gec6818_misc_dev); printk(KERN_WARNING "gec6818 led driver exit\n" ); } module_init(gec6818_led_init); module_exit(gec6818_led_exit); MODULE_AUTHOR("1175595406@qq.com" ); MODULE_DESCRIPTION("LED driver for GEC6818)" ); MODULE_LICENSE("GPL" ); MODULE_VERSION("V1.0" );