一个基于PXA255嵌入式系统的简单24位图片读取输出程序
2012-06-12 12:31
495 查看
很简单有兴趣的可以扩展2位,4位,8位,16位读取和图片压缩放大 屏幕为16位TFT-LCE
键盘驱动:key_dd.c
键盘驱动:key_dd.c
#include <linux/module.h>//모듈에 관한 정의 ex)MOD_INC_USE_COUNT #include <linux/init.h>//init_module() 과 cleanup_module() #include <linux/delay.h>//udelay() #include <linux/kernel.h> #include <asm/uaccess.h>//copy_to_user() #include <asm/io.h>//GPIO controller에 관한 정의 #include <asm/irq.h>// interrupt에 관한 정의 /* Prototypes */ int key_init (void ); int key_open(struct inode *, struct file *); int key_release(struct inode *, struct file *); ssize_t key_read (struct file *inode, char *gdata, size_t length, loff_t *off_what); ssize_t key_write (struct file *inode, char *gdata, size_t length, loff_t *off_what); void led_blink(unsigned long i); void key_handler(int irq, void *dev_id, struct pt_regs *regs); void clean_module(void); #define DEVICE_NAME "KEY" #define KEY_MAJOR 233 //0x00000001로 정의됨 #define KEY_GPIO_0 GPIO_0 // IRQ_GPIO(0)는 0로 정의됨 #define KEY_IRQ IRQ_GPIO(0) //key pad data input address #define KEY_BASE 0x14000000 #define KEY_BYTES 1 #define GPIO_LED_82 0x40000 #define GPIO_LED_83 0x80000 static struct file_operations key_fops = { open: key_open, read: key_read, write: key_write, release:key_release, }; static DECLARE_WAIT_QUEUE_HEAD(wq); static int Major; static unsigned long *keyport; static char key_value; int key_init(void) { int return_val; printk("keypad_init n"); Major = register_chrdev (KEY_MAJOR, DEVICE_NAME, &key_fops); if (Major < 0) { printk ("KEY init_module: failed with %d n", Major); return Major; } printk ("KEY driver registred: major = %d n", KEY_MAJOR); //GPIO 0을 입력으로 설정 GPDR0 &= ~(GPIO_0); //alternate function을 normal GPIO function으로 설정 GAFR0_L &= ~(0x3); //GPIO 0을 falling edge일 때 detect 하도록 설정 set_GPIO_IRQ_edge( 0, GPIO_FALLING_EDGE); //IRQ 요청 return_val = request_irq(KEY_IRQ, key_handler, SA_INTERRUPT, "KEY PAD INT", NULL ); if( return_val < 0 ) { printk(KERN_ERR "pxa255_pro_key_init() : Can't reqeust irq %#010x n", IRQ_GPIO(0) ); return -1; } return 0; } /* interrupt service routine */ void key_handler(int irq, void *dev_id, struct pt_regs *regs) { // 키의 물리주소 값을 커널의 임의의 메모리 영역의 주소에 매핑 keyport = (unsigned long)ioremap(KEY_BASE, 0x10); //매핑된 메모리 주소를 이용하여 실제 물리 주소에 있는 값을 가져온다. key_value = *(keyport+0) & 0xf; printk("KEY INPUT : [0x%x] n",key_value); switch(key_value) { case 0x3 : printk("u pushed 3rd button. OST will be played.. n"); break; case 0xb : printk("u pushed 12th button. Ad will be played.. n"); break; default :led_blink(key_value);break; } //매핑되었던 물리 주소와 메모리 주소를 해제 iounmap(keyport); //block시켜놨던 read() process를 release한다. wake_up_interruptible(&wq); } ssize_t key_read (struct file *inode, char *gdata, size_t length, loff_t *off_what) { // interrupt가 발생할 때까지 sleep 시킴 interruptible_sleep_on(&wq); printk("value being sent to application : %x n",key_value); //application에게 interrupt 번호를 pass한다. copy_to_user(gdata, &key_value,sizeof(1)); return 0; } int key_open (struct inode *inode, struct file *file) { printk ("open..ok n"); printk ("push any key! n"); //LED D6, D7의 방향을 출력으로 설정한다. GPDR2 |= 0xC0000; MOD_INC_USE_COUNT; return 0; } int key_release (struct inode *inode, struct file *file) { printk ("device_release(%p,%p) n", inode, file); MOD_DEC_USE_COUNT; return 0; } ssize_t key_write (struct file *inode, char *gdata, size_t length, loff_t *off_what) { return 0; } void led_blink(unsigned long i) { int j=(i & 0xf)+1; printk("LED will toggle %x times n", j); while(j) { GPCR2 |= GPIO_LED_83;//83번을 CLEAR, LED D7 GREEN이 켜짐 GPSR2 |= GPIO_LED_82;//82번을 SET, LED D6 RED가 꺼짐 udelay(90000000000); GPCR2 |= GPIO_LED_82;//82번을 CLEAR, LED D6 RED가 켜짐 GPSR2 |= GPIO_LED_83;//83번을 SET, LED D7 GREEN이 꺼짐 udelay(90000000000); j--; } GPSR2 |= GPIO_LED_82;//82번을 SET, LED D6 RED가 꺼짐 return; } module_init(key_init); module_exit(clean_module); void clean_module (void) { int ret; ret = unregister_chrdev (KEY_MAJOR, DEVICE_NAME); if (ret < 0) { printk ("unregister_chrdev: error %d n", ret); } else { printk ("module clean up ok!! n"); } } /****************************************************************************/ 键盘测试程序:app-key-test.c #include <stdio.h> #include <fcntl.h> //open()의 flag 정의되어 있음 #include <errno.h> //errno에 정의 됨 int fd; int main(int argc, char **argv) { unsigned long status = 0; char passed_value; if( (fd = open("/dev/KEY", O_RDWR)) < 3) { fprintf(stderr, "/dev/int_test device file open error!! .. %s n",strerror(errno)); close(fd); return 0; } while(1) { //커널로부터 넘어온 interrupt 번호를 받는다. read(fd, &passed_value,sizeof(1)); printf("value passed from kernel :%x n", passed_value); //3번 key를 눌렸을 경우 if(passed_value==3) { system("mixer vol 100"); system("mixer pcm 100"); system("madplay /mnt/mtd/sample/sample.mp3"); } //12번 key를 눌렸을 경우 else if(passed_value==0xb) { system("mixer vol 100"); system("mixer pcm 100"); system("mplayer /mnt/mtd/sample/sample.mpg"); } }; close(fd); return 0; } /****************************************************************************/ Makefile文件: CC=arm-linux-gcc INCLUDEDIR = /home/es/Toolchain/linux-2.4.19-pro3_nlcd/include CFLAGS = -D__KERNEL__ -DMODULE -Wall -O2 CFLAGS2 = -I.. -I$(INCLUDEDIR) All: key_test_dd test key_test_dd : key_dd.c $(CC) $(CFLAGS) $(CFLAGS2) -c -o key_dd.o key_dd.c test :app-key-test.c $(CC) -o test app-key-test.c clean : rm -rf key_dd.o test /****************************************************************************/ 程序主文件: #include <math.h> #include <dirent.h> #include <fcntl.h> #include <string.h> #include <errno.h> //errno에 정의 됨 #include <termios.h> #include <stdio.h> #include <stdlib.h> /* for exit */ #include <unistd.h> /* for open/close.. */ #include <fcntl.h> /* for O_RDONLY */ #include <sys/ioctl.h> /* for ioctl */ #include <sys/types.h> /* for lseek() */ #include <sys/stat.h> #include <sys/signal.h> #include <linux/fb.h> /*for fb_var_screeninfo, FBIOGET_VSCREENINFO*/ #define FBDEVFILE "/dev/fb" #define WIDTHBYTES(bits) (((bits)+31)/32*4) typedef unsigned char ubyte; unsigned short makepixel(struct fb_var_screeninfo *fbvar, ubyte r, ubyte g, ubyte b) { return (unsigned short)(((r>>3)<<11)|((g>>2)<<5)|(b>>3)); } typedef struct { unsigned short bfType;//表明位图文件的类型,必须为BM unsigned long bfSize;//表明位图文件的大小,以字节为单位 unsigned short bfReserved1;//属于保留字,必须为本0 //unsigned short bfReserved2;//也是保留字,必须为本0 unsigned long bfOffBits;//位图阵列的起始位置,以字节为单位 } BITMAPFILEHEADER; typedef struct { unsigned long biSize; //指出本数据结构所需要的字节数 long biWidth;//以象素为单位,给出BMP图象的宽度 long biHeight;//以象素为单位,给出BMP图象的高度 unsigned short biPlanes;//输出设备的位平面数,必须置为1 unsigned short biBitCount;//给出每个象素的位数 unsigned long biCompress;//给出位图的压缩类型 unsigned long biSizeImage;//给出图象字节数的多少 long biXPelsPerMeter;//图像的水平分辨率 long biYPelsPerMeter;//图象的垂直分辨率 unsigned long biClrUsed;//調色板中图象实际使用的颜色素数 unsigned long biClrImportant;//给出重要颜色的索引值 } BITMAPINFOHEADER; typedef struct { //public: ubyte rgbBlue; //该颜色的蓝色分量 ubyte rgbGreen; //该颜色的绿色分量 ubyte rgbRed; //该颜色的红色分量 ubyte rgbReserved; //保留值 } RGBQUAD; int bmpload(char* filename) { FILE* fp; BITMAPFILEHEADER bmpfile; BITMAPINFOHEADER bmpinfo; RGBQUAD *dataOfBmp; int i, j, k; int index = 0; long plant; int num; int bmpwidth; int bmpheigh; int lwidth; ubyte *pColorData; long nData; int fbfd; int ret; struct fb_var_screeninfo fbvar; unsigned short pixel; int offset; fbfd = open(FBDEVFILE, O_RDWR); if(fbfd < 0) { perror("fbdev open"); exit(1); } // 커널로부터 lcd에 관한 정보를 fbvar에 저장한다. ret = ioctl(fbfd, FBIOGET_VSCREENINFO, &fbvar); if(ret < 0) { perror("fbdev ioctl"); exit(1); } if(fbvar.bits_per_pixel!=16) { //bpp가 16bit인지 check fprintf(stderr, "bpp is not 16n"); exit(1); } fp = fopen(filename, "rb"); fread(&bmpfile,14L, 1, fp); if(bmpfile.bfType != 0x4d42) return -1; fseek(fp, 14L, 0); fread(&bmpinfo,sizeof(BITMAPINFOHEADER), 1, fp); bmpwidth = bmpinfo.biWidth;//图片宽度 bmpheigh = bmpinfo.biHeight;//图片长度 lwidth = WIDTHBYTES(bmpwidth * bmpinfo.biBitCount);//每行像素大小 pColorData = (ubyte *)malloc(bmpheigh * lwidth); memset(pColorData,0, bmpheigh * lwidth); nData = bmpheigh * lwidth; dataOfBmp = (RGBQUAD *)malloc(bmpwidth * bmpheigh * sizeof(RGBQUAD));//用于保存各像素对应的RGB数据 memset(dataOfBmp, 0, bmpwidth * bmpheigh * sizeof(RGBQUAD)); //把位图数据信息读到数组里 fread(pColorData,1,nData,fp); index = 0; for(i=0; i < bmpheigh; i++) for(j= 0; j < bmpwidth ; j++) { k = i * lwidth + j*3; dataOfBmp[index].rgbRed = pColorData[k+2]; dataOfBmp[index].rgbGreen = pColorData[k+1]; dataOfBmp[index].rgbBlue = pColorData[k]; index++; } k = 0; for (i = 479; i > -1; i--) for (j = 0; j < 640; j++) { offset = i*fbvar.xres*(16/8)+ j*(16/8); if(lseek(fbfd, offset, SEEK_SET) < 0) //file point를 맨 앞에서 offset만큼 옮김 { perror("fbdev lseek"); exit(1); } pixel = makepixel(&fbvar, dataOfBmp[k].rgbRed, dataOfBmp[k].rgbGreen, dataOfBmp[k].rgbBlue); write(fbfd, &pixel, 2); k += 1; } fclose(fp); free(dataOfBmp); free(pColorData); return 0; } int getkey() { int fd, c, res, i; char key; fd = open("/dev/KEY", O_RDONLY); if(fd < 0) { perror("/dev/KEY"); exit(-1); } else { while(key != 0x7) { printf("Key test startn"); read(fd, &key, sizeof(1)); switch(key) { case 0x0: //printf("Number 3"); return 3; break; case 0x1: //printf("Number 6"); return 6; break; case 0x2: //printf("Number 9"); return 9; break; case 0x3: //printf("Number *"); return 11; break; case 0x4: //printf("Number 2"); return 2; break; case 0x5: //printf("Number 5"); return 5; break; case 0x6: //printf("Number 8"); return 8; break; case 0x7: //printf("Number 0"); return 0; break; case 0x8: //printf("Number 1"); return 1; break; case 0x9: //printf("Number 4"); return 4; break; case 0xa: //printf("Number 7"); return 7; break; case 0xb: //printf("Number #"); return 10; break; } } } close(fd); return 0; } int load_dd() { int ret; ret = system("insmod key_dd.o"); if (ret == 0) ret = system("mknod /dev/KEY c 233 0"); if (ret != 0) { printf ("KeyPad fail!"); } return 0; } int load_bmp(int key) { char fname[255]; struct dirent *ptr; DIR *dir; dir=opendir("/mnt/usbdisk/"); while((ptr=readdir(dir))!=NULL) { //跳过'.'和'..'两个目录 if(ptr->d_name[0] == '.') continue; else if(strstr(ptr->d_name,".bmp")) { printf("%s is ready...n",ptr->d_name); sprintf(fname,"/mnt/usbdisk/%s",ptr->d_name); bmpload(fname); if (key == 1) { sleep(4); } else if (key == 2) { sleep(4); } else { key = getkey(); while (1) { if (key == 5) break; else if (key == 1) break; else if (key == 2) break; else if(key == 0) { closedir(dir); return -1; } key = getkey(); } } } } closedir(dir); switch (key) { case 1 : return 1; break; case 2: return 2; break; default : return 0; break; } } int main() { int ret; int key; load_dd(); key = load_bmp(100); while (1) { if(key == 1) key = 100; else if(key == -1) break; key = load_bmp(key); } exit(0); }
相关文章推荐
- 用java编写一个简单的字符串加密解密程序,将字符串分成若干行,实现字符串以一列一列读取,并还原之前输入的字符串。这里实现4行输出。
- 基于QT和opencv的摄像头(本地图片)读取并输出程序
- 基于atmel mega88编写了一个简单的时间触发系统单片机框架程序
- ARM嵌入式编程(无操作系统、基于MDK)之最简单的程序:点亮一个LED灯
- 一个简单的java读取网页图片并保存图片的程序
- 嵌入式 一个简单的个人通讯录(基于二叉排序树,带注释)
- 基于jQuery的一个简单的图片查看器实现
- 一个简单的基于udp协议的聊天程序
- 一个简单的将GUI程序的log信息输出到关联的Console窗口中
- 浅谈:使用Java基于MVC模式开发一个简单商品管理系统
- 一个班有n个学生,需要把每个学生的简单资料(姓名和学号)输入计算机保存。然后可以通过输入某一学生的姓名查找其有关资料。当输入一个姓名后程序就查找该班有无此学生,如果有,则输出他的姓名和学号,如果找不到
- 一个简单的爬虫程序,爬取网站的图片
- 基于JUnit3.8的一个简单的测试程序
- 基于jQuery的一个简单的图片查看器实现
- 自己动手弄基于QT5和directx11的简单粒子编辑器v0.1(一个编辑器,一个更新器,一个linux服务端程序)
- [转]一个简单的基于Tesseract的数字识别程序
- 一个简单的web点名程序(基于javascript)
- c#入门:简单的数组,编写一个程序,接收每件商品的价格,计算应付的总金额并输出
- C下学生管理系统:从文件中读取30位学生的信息(含邮箱),并实现简单的增、删、查找、统计(邮箱使用人数)。---附程序哦!
- 一个简单的系统托盘程序