lcd驱动程序如何编写显示图片功能.doc

上传人:sccc 文档编号:4842063 上传时间:2023-05-18 格式:DOC 页数:17 大小:68.50KB
返回 下载 相关 举报
lcd驱动程序如何编写显示图片功能.doc_第1页
第1页 / 共17页
lcd驱动程序如何编写显示图片功能.doc_第2页
第2页 / 共17页
lcd驱动程序如何编写显示图片功能.doc_第3页
第3页 / 共17页
lcd驱动程序如何编写显示图片功能.doc_第4页
第4页 / 共17页
lcd驱动程序如何编写显示图片功能.doc_第5页
第5页 / 共17页
点击查看更多>>
资源描述

《lcd驱动程序如何编写显示图片功能.doc》由会员分享,可在线阅读,更多相关《lcd驱动程序如何编写显示图片功能.doc(17页珍藏版)》请在三一办公上搜索。

1、lcd驱动程序如何编写显示图片功能以前没有写Lcd驱动程序,现在开始做项目了,才发现Lcd驱动程序必须认真学习,我总结所以驱动中LCD和网卡驱动是最难的,LCD主要是需要配置的寄存器太多了,还是老规矩先上代码。内核版本:linux-3.4.2 lcd:4.3上代码之前我得讲解一些基本的知识点,LCD驱动我们只需要写硬件这一块的代码就可以了,下面有三个函数内核已经帮我们写好了,我们只需要调用就可以了,这几个函数实现了内核层和应用成数据的传递,有兴趣的朋友去分析一下源码,我里驱动写好了我们可以选择动态加载驱动或者直接静态编译进内核,这个的区别在前文中我讲解的非常清楚了,希望朋友一定要去看一下,Li

2、nux驱动静态编译和动态编译方法详解这个代码相对有点复杂,朋友们一定要仔细分析。驱动程序如下:lcd.c文件如下:#include linux/module.h#include linux/kernel.h#include linux/errno.h#include linux/string.h#include linux/mm.h#include linux/slab.h#include linux/delay.h#include linux/fb.h#include linux/init.h#include linux/dma-mapping.h#include linux/interru

3、pt.h#include linux/workqueue.h#include linux/wait.h#include linux/platform_device.h#include linux/clk.h#include asm/io.h#include asm/uaccess.h#include asm/div64.h#include asm/mach/map.hstaTIc int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,unsigned int green, unsigned int blue,unsigned

4、int transp, struct fb_info *info);struct lcd_regs unsigned long lcdcon1;unsigned long lcdcon2;unsigned long lcdcon3;unsigned long lcdcon4;unsigned long lcdcon5;unsigned long lcdsaddr1;unsigned long lcdsaddr2;unsigned long lcdsaddr3;unsigned long redlut;unsigned long greenlut;unsigned long bluelut;un

5、signed long reserved9;unsigned long dithmode;unsigned long tpal;unsigned long lcdintpnd;unsigned long lcdsrcpnd;unsigned long lcdintmsk;unsigned long lpcsel;staTIc struct fb_ops s3c_lcdfb_ops = .owner = THIS_MODULE,.fb_setcolreg = s3c_lcdfb_setcolreg,.fb_fillrect = cfb_fillrect, /* 这三个函数是在内核自带的,动态加载

6、时候,需要把这个三个编译成模块当吧驱动程序编译进内核时候,就不用去管着三个函数 */val |= chan_to_field(blue,info-var.blue);/(u32 *)(info-pseudo_palette)regno = val;pseudo_paletteregno = val;return 0;staTIc int lcd_init(void)/* 1. 分配一个fb_info */s3c_lcd = framebuffer_alloc(0, NULL);/* 2. 设置 */* 2.1 设置固定的参数 */strcpy(s3c_lcd-fix.id, mylcd);s3

7、c_lcd-fix.smem_len = 480*272*16/8;s3c_lcd-fix.type = FB_TYPE_PACKED_PIXELS;s3c_lcd-fix.visual = FB_VISUAL_TRUECOLOR; /* TFT */s3c_lcd-fix.line_length = 480*2;/* 2.2 设置可变的参数 */s3c_lcd-var.xres = 480;s3c_lcd-var.yres = 272;s3c_lcd-var.xres_virtual = 480;s3c_lcd-var.yres_virtual = 272;s3c_lcd-var.bits_

8、per_pixel = 16;/* RGB:565 */s3c_lcd-var.red.offset = 11;s3c_lcd-var.red.length = 5;s3c_lcd-var.green.offset = 5;s3c_lcd-var.green.length = 6;s3c_lcd-var.blue.offset = 0;s3c_lcd-var.blue.length = 5;s3c_lcd-var.acTIvate = FB_ACTIVATE_NOW;/* 2.3 设置操作函数 */s3c_lcd-fbops = s3c_lcdfb_ops;/* 2.4 其他的设置 */s3c

9、_lcd-pseudo_palette = pseudo_palette;/s3c_lcd-screen_base = ; /* 显存的虚拟地址 */s3c_lcd-screen_size = 480*272*16/8;/* 3. 硬件相关的操作 */* 3.1 配置GPIO用于LCD */gpbcon = ioremap(0x56000010, 8);gpbdat = gpbcon+1;gpccon = ioremap(0x56000020, 4);gpdcon = ioremap(0x56000030, 4);gpgcon = ioremap(0x56000060, 4);*gpccon

10、= 0xaaaaaaaa; /* GPIO管脚用于VD7:0,LCDVF2:0,VM,VFRAME,VLINE,VCLK,LEND */*gpdcon = 0xaaaaaaaa; /* GPIO管脚用于VD23:8 */*gpbcon = (3); /* GPB0设置为输出引脚 */*gpbcon |= 1;*gpbdat = 1; /* 输出低电平 */*gpgcon |= (38); /* GPG4用作LCD_PWREN */* 3.2 根据LCD手册设置LCD控制器, 比如VCLK的频率等 */lcd_regs = ioremap(0x4D000000, sizeof(struct lc

11、d_regs);/* bit17:8: VCLK = HCLK / (CLKVAL+1) x 2, LCD手册P14* 10MHz(100ns) = 100MHz / (CLKVAL+1) x 2* CLKVAL = 4* bit6:5: 0b11, TFT LCD* bit4:1: 0b1100, 16 bpp for TFT* bit0 : 0 = Disable the video output and the LCD control signal.*/lcd_regs-lcdcon1 = (48) | (35) | (0x0c1);#if 1/* 垂直方向的时间参数* bit31:24

12、: VBPD, VSYNC之后再过多长时间才能发出第1行数据* LCD手册 T0-T2-T1=4* VBPD=3* bit23:14: 多少行, 320, 所以LINEVAL=320-1=319* bit13:6 : VFPD, 发出最后一行数据之后,再过多长时间才发出VSYNC* LCD手册T2-T5=322-320=2, 所以VFPD=2-1=1* bit5:0 : VSPW, VSYNC信号的脉冲宽度, LCD手册T1=1, 所以VSPW=1-1=0*/lcd_regs-lcdcon2 = (124) | (27114) | (16) | (9);/* 水平方向的时间参数* bit25:

13、19: HBPD, VSYNC之后再过多长时间才能发出第1行数据* LCD手册 T6-T7-T8=17* HBPD=16* bit18:8: 多少列, 240, 所以HOZVAL=240-1=239* bit7:0 : HFPD, 发出最后一行里最后一个象素数据之后,再过多长时间才发出HSYNC* LCD手册T8-T11=251-240=11, 所以HFPD=11-1=10*/lcd_regs-lcdcon3 = (119) | (4798) | (1);/* 水平方向的同步信号* bit7:0 : HSPW, HSYNC信号的脉冲宽度, LCD手册T7=5, 所以HSPW=5-1=4*/lc

14、d_regs-lcdcon4 = 40;#elselcd_regs-lcdcon2 = S3C2410_LCDCON2_VBPD(5) | S3C2410_LCDCON2_LINEVAL(319) | S3C2410_LCDCON2_VFPD(3) | S3C2410_LCDCON2_VSPW(1);lcd_regs-lcdcon3 = S3C2410_LCDCON3_HBPD(10) | S3C2410_LCDCON3_HOZVAL(239) | S3C2410_LCDCON3_HFPD(1);lcd_regs-lcdcon4 = S3C2410_LCDCON4_MVAL(13) | S3C

15、2410_LCDCON4_HSPW(0);#endif/* 信号的极性* bit11: 1=565 format* bit10: 0 = The video data is fetched at VCLK falling edge* bit9 : 1 = HSYNC信号要反转,即低电平有效* bit8 : 1 = VSYNC信号要反转,即低电平有效* bit6 : 0 = VDEN不用反转* bit3 : 0 = PWREN输出0* bit1 : 0 = BSWP* bit0 : 1 = HWSWP 2440手册P413*/lcd_regs-lcdcon5 = (111) | (010) |

16、(19) | (18) | (10);/* 3.3 分配显存(framebuffer), 并把地址告诉LCD控制器 */s3c_lcd-screen_base = dma_alloc_writecombine(NULL, s3c_lcd-fix.smem_len, s3c_lcd-fix.smem_start, GFP_KERNEL);lcd_regs-lcdsaddr1 = (s3c_lcd-fix.smem_start 1) (330);lcd_regs-lcdsaddr2 = (s3c_lcd-fix.smem_start + s3c_lcd-fix.smem_len) 1) 0x1ff

17、fff;lcd_regs-lcdsaddr3 = (480*16/16); /* 一行的长度(单位: 2字节) */s3c_lcd-fix.smem_start = xxx; /* 显存的物理地址 */* 启动LCD */lcd_regs-lcdcon1 |= (10); /* 使能LCD控制器 */lcd_regs-lcdcon5 |= (13); /* 使能LCD本身 */*gpbdat |= 1; /* 输出高电平, 使能背光 */* 4. 注册 */register_framebuffer(s3c_lcd);return 0;static void lcd_exit(void)unre

18、gister_framebuffer(s3c_lcd);lcd_regs-lcdcon1 = (10); /* 关闭LCD本身 */*gpbdat = 1; /* 关闭背光 */dma_free_writecombine(NULL, s3c_lcd-fix.smem_len, s3c_lcd-screen_base, s3c_lcd-fix.smem_start);iounmap(lcd_regs);iounmap(gpbcon);iounmap(gpccon);iounmap(gpdcon);iounmap(gpgcon);framebuffer_release(s3c_lcd);modul

19、e_init(lcd_init);module_exit(lcd_exit);MODULE_LICENSE(GPL);测试程序怎么编写就看你的应用程序了,但是框架是不变的如下:下面是在Lcd上显示一幅图片,用到了libjpeg库,这个地方可以不用关注,主要是看看应用程序怎么调用驱动程序的,我总结有如下当函数:static int FBDeviceInit(void) /* FB初始化函数 */static int FBShowPixel(int iX, int iY, unsigned int dwColor) /* 填充像素,具体怎么填充看如下代码中 */static int FBClean

20、Screen(unsigned int dwBackColor) /* 清屏函数,把显示屏初始化为黑色 */#include stdio.h#include jpeglib.h#include setjmp.h#include sys/types.h#include sys/stat.h#include fcntl.h#include sys/ioctl.h#include sys/mman.h#include linux/fb.h#include string.h#include stdlib.h#define FB_DEVICE_NAME /dev/fb0#define DBG_PRINT

21、F printfstatic int g_fd;static struct fb_var_screeninfo g_tFBVar;static struct fb_fix_screeninfo g_tFBFix;static unsigned char *g_pucFBMem;static unsigned int g_dwScreenSize;static unsigned int g_dwLineWidth;static unsigned int g_dwPixelWidth;static int FBDeviceInit(void)int ret;g_fd = open(FB_DEVIC

22、E_NAME, O_RDWR); /* 打开lcd驱动设备节点 */if (0 g_fd)DBG_PRINTF(cant open %sn, FB_DEVICE_NAME);ret = ioctl(g_fd, FBIOGET_VSCREENINFO, g_tFBVar); /* 获取lcd可变参数 */if (ret 0)DBG_PRINTF(cant get fbs varn);return -1;ret = ioctl(g_fd, FBIOGET_FSCREENINFO, g_tFBFix); /* 获取lcd固定参数 */if (ret 0)DBG_PRINTF(cant get fbs

23、 fixn);return -1;g_dwScreenSize = g_tFBVar.xres * g_tFBVar.yres * g_tFBVar.bits_per_pixel / 8; /* 计算lcd屏幕大小 */g_pucFBMem = (unsigned char *)mmap(NULL , g_dwScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0); /* 把显存映射成内存一样,方便我们直接操作 ,这个地方是很有意思的*/if (0 g_pucFBMem)DBG_PRINTF(cant mmapn);return -1;

24、g_dwLineWidth = g_tFBVar.xres * g_tFBVar.bits_per_pixel / 8;g_dwPixelWidth = g_tFBVar.bits_per_pixel / 8;return 0;static int FBShowPixel(int iX, int iY, unsigned int dwColor) /* 填充像素,dwcolor就是我们要在一个像素显示的颜色 */unsigned char *pucFB;unsigned short *pwFB16bpp;unsigned int *pdwFB32bpp;unsigned short wColo

25、r16bpp; /* 565 */int iRed;int iGreen;int iBlue;if (iX = g_tFBVar.xres) | (iY = g_tFBVar.yres)DBG_PRINTF(out of regionn);return -1;pucFB = g_pucFBMem + g_dwLineWidth * iY + g_dwPixelWidth * iX;pwFB16bpp = (unsigned short *)pucFB;pdwFB32bpp = (unsigned int *)pucFB;switch (g_tFBVar.bits_per_pixel)case

26、8:*pucFB = (unsigned char)dwColor;break;case 16:iRed = (dwColor (16+3) 0x1f;iGreen = (dwColor (8+2) 0x3f;iBlue = (dwColor 3) 0x1f;wColor16bpp = (iRed 11) | (iGreen 5) | iBlue;*pwFB16bpp = wColor16bpp;break;case 32:*pdwFB32bpp = dwColor;break;default :DBG_PRINTF(cant support %d bppn, g_tFBVar.bits_pe

27、r_pixel);return -1;return 0;static int FBCleanScreen(unsigned int dwBackColor)unsigned char *pucFB;unsigned short *pwFB16bpp;unsigned int *pdwFB32bpp;unsigned short wColor16bpp; /* 565 */int iRed;int iGreen;int iBlue;int i = 0;pucFB = g_pucFBMem;pwFB16bpp = (unsigned short *)pucFB;pdwFB32bpp = (unsi

28、gned int *)pucFB;switch (g_tFBVar.bits_per_pixel)case 8:memset(g_pucFBMem, dwBackColor, g_dwScreenSize);break;case 16:iRed = (dwBackColor (16+3) 0x1f;iGreen = (dwBackColor (8+2) 0x3f;iBlue = (dwBackColor 3) 0x1f;wColor16bpp = (iRed 11) | (iGreen 5) | iBlue;while (i g_dwScreenSize)*pwFB16bpp = wColor

29、16bpp;pwFB16bpp+;i += 2;break;case 32:while (i g_dwScreenSize)*pdwFB32bpp = dwBackColor;pdwFB32bpp+;i += 4;break;default :DBG_PRINTF(cant support %d bppn, g_tFBVar.bits_per_pixel);return -1;return 0;static int FBShowLine(int iXStart, int iXEnd, int iY, unsigned char *pucRGBArray)int i = iXStart * 3;

30、int iX;unsigned int dwColor;if (iY = g_tFBVar.yres)return -1;if (iXStart = g_tFBVar.xres)return -1;if (iXEnd = g_tFBVar.xres)iXEnd = g_tFBVar.xres;for (iX = iXStart; iX iXEnd; iX+)/* 0xRRGGBB */dwColor = (pucRGBArrayi16) + (pucRGBArrayi+18) + (pucRGBArrayi+20);i += 3;FBShowPixel(iX, iY, dwColor);ret

31、urn 0;/*Allocate and initialize a JPEG decompression object / 分配和初始化一个decompression结构体Specify the source of the compressed data (eg, a file) / 指定源文件Call jpeg_read_header() to obtain image info / 用jpeg_read_header获得jpg信息Set parameters for decompression / 设置解压参数,比如放大、缩小jpeg_start_decompress(。.); / 启动解

32、压:jpeg_start_decompresswhile (scan lines remain to be read)jpeg_read_scanlines(。.); / 循环调用jpeg_read_scanlinesjpeg_finish_decompress(。.); / jpeg_finish_decompressRelease the JPEG decompression object / 释放decompression结构体*/* Uage: jpg2rgb jpg_file*/int main(int argc, char *argv)struct jpeg_decompress_

33、struct cinfo;struct jpeg_error_mgr jerr;FILE * infile;int row_stride;unsigned char *buffer;if (argc != 2)printf(Usage: n);printf(%s jpg_filen, argv0);return -1;if (FBDeviceInit()return -1;FBCleanScreen(0);/* 以下部分是把图片解压出来,取出各个像素值放在一个缓冲区中,我们只需要把这些像素填进lcd当中去就行 */ 分配和初始化一个decompression结构体cinfo.err = jpe

34、g_std_error(jerr);jpeg_create_decompress(cinfo);/ 指定源文件if (infile = fopen(argv1, rb) = NULL) fprintf(stderr, cant open %sn, argv1);return -1;jpeg_stdio_src(cinfo, infile);/ 用jpeg_read_header获得jpg信息jpeg_read_header(cinfo, TRUE);/* 源信息 */printf(image_width = %dn, cinfo.image_width);printf(image_height

35、 = %dn, cinfo.image_height);printf(num_components = %dn, cinfo.num_components);/ 设置解压参数,比如放大、缩小printf(enter scale M/N:n);scanf(%d/%d, cinfo.scale_num, cinfo.scale_denom);printf(scale to : %d/%dn, cinfo.scale_num, cinfo.scale_denom);/ 启动解压:jpeg_start_decompressjpeg_start_decompress(cinfo);/* 输出的图象的信息

36、 */printf(output_width = %dn, cinfo.output_width);printf(output_height = %dn, cinfo.output_height);printf(output_components = %dn, cinfo.output_components);/ 一行的数据长度row_stride = cinfo.output_width * cinfo.output_components;buffer = malloc(row_stride);/ 循环调用jpeg_read_scanlines来一行一行地获得解压的数据while (cinfo.output_scanline cinfo.output_height)(void) jpeg_read_scanlines(cinfo, buffer, 1);/ 写到LCD去FBShowLine(0, cinfo.output_width, cinfo.output_scanline, buffer);free(buffer);jpeg_finish_decompress(cinfo);jpeg_destroy_decompress(cinfo);return 0;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号