1.实现功能:
用LCD来显示图片结合按键来实现上一幅下一幅图片显示,加上自动播放图片功能
2.开发时间:2012年8月
3.所需环境:
Linux虚拟机,交叉编译链4.3.3,ARM开发板
4.项目描述:
(1)通过TQ2440开发板实现一个电子相册,用2440的按键实现各种操作并实现相应的中断定时
(2)主要用到Linux下多进程异步运行,进程间通信和内存共享,信号量,帧缓冲区操作,同时用到select进行监控,mmap()函数进行显示缓冲区的物理地址到用户空间的映射
(3)实现ARM开发板按键驱动和测试程序
(4)实现1341声卡移植,LCD移植
具体LCD和1341声卡移植请看我其它的博客,这里主要说一下按键驱动,其实跟以前按键驱动差不多的,还有就是测试程序
下面先看测试程序
*功能电子相册
*k1 自动放映相片带音乐
*k2停止
*k3停止或刚开始时下一幅图片
*k4停止或刚开始时上一幅图片
*
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/select.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
//把存放图片的数组包含进来
extern
extern
extern
extern
extern
extern
extern
//把计算大小的函数包含进来
extern int
extern int
extern int
extern int
extern int
extern int
extern int
//共享内存申请标记
#define PERM S_IRUSR|S_IWUSR
//双向循环列表:存放歌曲名
struct song
{
};
//孙子进程id号
pid_t gradchild;
//子进程id号
pid_t pid;
//共享内存描述标记
int shmid;
char *p_addr;
//播放标记
int first_key=1;
int play_flag=0;
//帧缓冲区的标记
int fbfd = 0;
struct fb_var_screeninfo vinfo;//记录用户可修改的显示控制器参数
unsigned long screensize = 0;
char *fbp = 0;
int x = 0,y = 0;
int i = 0;
//上一幅下一幅图片标记
int nex1 = 0;
int pre1 = 6;
int bb;
*************************************************
Function name: play
Parameter
Description
Return
Argument
Autor & date : ada 09,12,07
**************************************************
void play(struct song *currentsong)
{
}
*************************************************
Function name: creat_song_list
Parameter
Description
Return
Argument
Autor & date : ada 09.12.07
**************************************************
struct song *creat_song_list(void)
{
}
*************************************************
Function name: startplay
Parameter
Description
Return
Argument
Autor & date : ada 09.12.07
**************************************************
void startplay(pid_t *childpid,struct song *my_song)
{
}
*************************************************
Function name: my_pause
Parameter
Description
Return
Argument
Autor & date : ada 09,12,07
**************************************************
void my_pause(pid_t pid)
{
}
*************************************************
Function name: my_pause
Parameter
Description
Return
Argument
Autor & date : ada 09,12,07
**************************************************
void my_stop(pid_t g_pid)
{
}
*************************************************
Function name: conti_play
Parameter
Description
Return
Argument
Autor & date : ada 09,12,07
**************************************************
void conti_play(pid_t pid)
{
}
*************************************************
Function name: next
Parameter
Description
Return
Argument
Autor & date : ada 09.12.07
**************************************************
void next(pid_t next_pid)
{
}
*************************************************
Function name: prev
Parameter
Description
Return
Argument
Autor & date : yuanhui 09.12.08
**************************************************
void prev(pid_t prev_pid)
{
}
//下一个图片
void next1(int i)
{
}
//上一张图片
void prev1(int i)
{
*************************************************
Function name: main
Parameter
Description
Return
Argument
Autor & date : ada 09.12.07
**************************************************
int main(void)
{
if(!fbfd){
}
printf("The framebuffer device was opened successfully n");
if(ioctl(fbfd,FBIOGET_VSCREENINFO,&vinfo)){//获得可变屏幕参数
}
printf("%dx%d, �ppn",vinfo.xres,vinfo.yres,vinfo.bits_per_pixel);
if(vinfo.bits_per_pixel != 16) {
}
screensize = vinfo.xres * vinfo.yres * 2;//16位2个字节
//将显示缓冲区的物理地址映射到用户空间
fbp = (char *)mmap(0,screensize,PROT_READ | PROT_WRITE,MAP_SHARED,fbfd,0);
if((int)fbp == -1){
}
printf("The framebuffer device was mapped to memory successfully.n");
}
上面的代码由于博客里面的注释会自动去掉,所以我把它改成了//,不过还有些地方没有屏蔽掉,主要是*************************************************函数开头注释没有屏蔽,把它复制到Linux加上屏蔽就可以了,不过这样还不能编译通过因为上面还没有图片的代码(由于图片代码太长了就不贴出了),下面说一下怎样把一张图片转换成可以在开发板上显示的16进制代码:
1.首先拿到一张图片,把它先转化成开发板LCD上的分辨率,也就是像素转换,在pc windows就有一个很好的转换工具不用在网上下载什么软件,pc上点击开始菜单找到附件里面有一个画图点击它,打开照片后在左上角那里有一个重新调整大小点击它,会弹出一个对话框,依据那里选择像素,中间有一个保存纵行比去掉它,然后就可以输入要转换水平方向像素和垂直方向像素了,完之后点击确定就可以了,然后就把弄好的图片另保存,保存成24位为图.bmp格式,这样就能得到转换后图片了
2.在网上下载一个BMP图片转换软件(也可以留言给我我发给你),就可以把刚才做好的图片转换成16进制格式了,也就是可以给我们的LCD识别了
3.转换后图片有一个.c文件和一个.h头文件.h这个文件不用理会它,把.c里面头文件也去掉了,并在最后面加上下面代码:
int cgy()
{
return sizeof(xxx);//xxx是转换后图片数组名
}
4.把数组名和测试程序里面包括的数组对应起来(可以改转换后.c文件里数组名,建议改这个,也可以改测试程序里数组名),这样之后用如下命令就可以编译出测试程序来了(下面1.c,2.c,3.c等是改了名字的转换后的.c文件,我写了一个简单的Makefile文件)
root@www:/opt/qudong/qd12# make
arm-linux-gcc a.c 0.c 1.c 2.c 3.c 4.c 5.c 6.c -o a
root@www:/opt/qudong/qd12#
到了这一步测试程序就好了
下面的是按键驱动程序,和以前的差不多的这里重复贴出一次
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#define DEVICE_NAME
//#define DEBUG
struct button_irq_desc {
};
static struct button_irq_desc button_irqs [] = {
};
//static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'};
static int key_values = 0;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press = 0;
static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
}
static int s3c24xx_buttons_open(struct inode *inode, struct file *file)
{
}
static int s3c24xx_buttons_close(struct inode *inode, struct file *file)
{
}
static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
}
static unsigned int s3c24xx_buttons_poll( struct file *file, struct poll_table_struct *wait)
{
}
static struct file_operations dev_fops = {
};
static struct miscdevice misc = {
};
static int __init dev_init(void)
{
#ifdef DEBUG
#endif
}
static void __exit dev_exit(void)
{
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");
这样之后驱动开发版把驱动程序和编译好的测试程序还有一个madplay执行文件放到文件系统的一个目录里之后,加载驱动,运行测试程序,按下按键k1后就可以自动播放图片了(如果看了前面的MP3实现过程,把歌曲加进来的话,就可以一边播放音乐一边看移动图片了)
[root@cgyl2010 ~]#
[root@cgyl2010 ~]#
[root@cgyl2010 ~]#cd /qd17
[root@cgyl2010 /qd17]#insmod mini2440_buttons.ko
buttons initialized
[root@cgyl2010 /qd17]#./a
The framebuffer device was opened successfully
480x272, 16bpp
The framebuffer device was mapped to memory successfully.
==================================song list=====================================
123.mp3
222.mp3
================================================================================
===================================OPTION=======================================
================================================================================
THIS SONG IS /qd15/song/123.mp3
MPEG Audio Decoder 0.15.2 (beta) - Copyright (C) 2000-2004 Robert Leslie et al.
但按下停止之后(或开始时没按k1前),这是按下k3和k4就会一张张图片的显示出来
....