`
wodamazi
  • 浏览: 1414377 次
文章分类
社区版块
存档分类
最新评论

s3c6410_LCD & frame buffer 驱动分析(一)

 
阅读更多

s3c6410_LCD & frame buffer 驱动分析

代码很多啊,好多东西都是不明白,这里做个笔记,特别是对LCD寄存器初始化,真的是看得。。。。

看来得找个时间玩玩裸奔啊。。。。。。。。。。。

struct fb_ops s3cfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = s3cfb_check_var,
.fb_set_par = s3cfb_set_par,
.fb_blank = s3cfb_blank,
.fb_pan_display = s3cfb_pan_display,
.fb_setcolreg = s3cfb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_cursor = soft_cursor,
.fb_ioctl = s3cfb_ioctl,
};


static struct platform_driver s3cfb_driver = {

.probe = s3cfb_probe,
.remove = s3cfb_remove,
.suspend = s3cfb_suspend,
.resume = s3cfb_resume,
.driver = {
.name = "s3c-fb",
.owner = THIS_MODULE,
},
};

int __devinit s3cfb_init(void)

{

/**模块加载函数实现平台驱动的注册**/

return platform_driver_register(&s3cfb_driver);
}
static void __exit s3cfb_cleanup(void)
{
platform_driver_unregister(&s3cfb_driver);
}

module_init(s3cfb_init);
module_exit(s3cfb_cleanup);

EXPORT_SYMBOL(lcdsize);

/**LCD尺寸选择

static int __init setlcdsize(char *str)
{
printk("call setlcdsize %s",str);
if(strcmp(str,"35")==0)
lcdsize = 0;
else if(strcmp(str,"43")==0)
lcdsize = 1;
else if(strcmp(str,"56")==0)
lcdsize = 2;
else if(strcmp(str,"70")==0)
lcdsize = 3;
else if(strcmp(str,"VGA800")==0)
lcdsize = 4;
else
lcdsize = 1;
return 1;
}
__setup("lcdsize=", setlcdsize);



MODULE_AUTHOR("Jinsung Yang");
MODULE_DESCRIPTION("S3C Framebuffer Driver");

MODULE_LICENSE("GPL");

/******************s3cfb_probe主要实现LCD控制寄存器的初始化和平台驱动资源的获取,时钟获取,初始化各种结构体等工作,注册framebuffer

static int __init s3cfb_probe(struct platform_device *pdev)
{
struct resource *res; /*用来保存从LCD平台设备中获取的LCD资源*/
struct fb_info *fbinfo;/*FrameBuffer驱动所对应的fb_info结构体*/
s3cfb_info_t *info;/**该结构其实就是对驱动中所用到的各种变量以及结构的一种封装*/

char driver_name[] = "s3cfb";/*FrameBuffer设备名称*/
int index = 0, ret, size;
/**分配fb_info结构体**/
fbinfo = framebuffer_alloc(sizeof(s3cfb_info_t), &pdev->dev);

if (!fbinfo)
return -ENOMEM;
/*将fbinfo传递给内核中总线设备结构所对应的驱动数据信息*/
platform_set_drvdata(pdev, fbinfo);
/**fb_info中似有成员赋值给s3cfb_info_t**/
info = fbinfo->par;
info->dev = &pdev->dev;
/**获取LCD平台设备所使用的IO端口资源**/
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

if (res == NULL) {
dev_err(&pdev->dev, "failed to get memory registers\n");
ret = -ENXIO;
goto dealloc_fb;
}

size = (res->end - res->start) + 1;
/*为上面LCDIO端口申请IO内存*/
info->mem = request_mem_region(res->start, size, pdev->name);

if (info->mem == NULL) {
dev_err(&pdev->dev, "failed to get memory region\n");
ret = -ENOENT;
goto dealloc_fb;
}
/**将LCD的此段IO地址空间映射成虚拟地址空间,这样才能操作**/
info->io = ioremap(res->start, size);

if (info->io == NULL) {
dev_err(&pdev->dev, "ioremap() of registers failed\n");
ret = -ENXIO;
goto release_mem;
}
/*初始化LCD视频中断控制寄存器0**/
s3cfb_pre_init();
/**TFT背光设置**/
s3cfb_set_backlight_power(1);
/**电源设置**/
s3cfb_set_lcd_power(1);
s3cfb_set_backlight_level(S3CFB_DEFAULT_BACKLIGHT_LEVEL);
/**获取LCD时钟**/
info->clk = clk_get(NULL, "lcd");

if (!info->clk || IS_ERR(info->clk)) {
printk(KERN_INFO "failed to get lcd clock source\n");
ret = -ENOENT;
goto release_io;
}
/**使能时钟**/
clk_enable(info->clk);
printk("S3C_LCD clock got enabled :: %ld.%03ld Mhz\n", PRINT_MHZ(clk_get_rate(info->clk)));
/**0帧数据**/
s3cfb_fimd.vsync_info.count = 0;
/**初始化帧同步信号的等待队列头**/
init_waitqueue_head(&s3cfb_fimd.vsync_info.wait_queue);
/**获取LCD平台设备所使用的中断号*/
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);

if (res == NULL) {
dev_err(&pdev->dev, "failed to get irq\n");
ret = -ENXIO;
goto release_clock;
}
/**申请LCD中断服务**/
ret = request_irq(res->start, s3cfb_irq, 0, "s3c-lcd", pdev);

if (ret != 0) {
printk("Failed to install irq (%d)\n", ret);
goto release_clock;
}

msleep(5);
/**6410支持多种屏幕**/
for (index = 0; index < S3CFB_NUM; index++) {

/**这个s3cfb_info就是一个s3cfb_info_t类型的数组,每一款LCD对应着一个索引*/

/**上面获取了IO内存,映射了IO,获取到了时钟等,这里用他们来填充这个s3cfb_info结构**/

s3cfb_info[index].mem = info->mem;
s3cfb_info[index].io = info->io;
s3cfb_info[index].clk = info->clk;
/**填充各种结构体中的参数,比如填充fb_info中的可变参数结构的成员和不可变参数结构的成员等**/
s3cfb_init_fbinfo(&s3cfb_info[index], driver_name, index);
/* Initialize video memory */帧缓冲设备显示缓冲区的内存分配**/
ret = s3cfb_map_video_memory(&s3cfb_info[index]);

if (ret) {
printk("Failed to allocate video RAM: %d\n", ret);
ret = -ENOMEM;
goto release_irq;
}
/*初始化完fb_info后,开始对LCD各寄存器进行初始化,这个寄存器的配置还真没怎么搞懂啊。感觉好难。。*/
ret = s3cfb_init_registers(&s3cfb_info[index]);
/**检查可变参数**/
ret = s3cfb_check_var(&s3cfb_info[index].fb.var, &s3cfb_info[index].fb);

if (index < 2){
if (fb_alloc_cmap(&s3cfb_info[index].fb.cmap, 256, 0) < 0)
goto dealloc_fb;
} else {
if (fb_alloc_cmap(&s3cfb_info[index].fb.cmap, 16, 0) < 0)
goto dealloc_fb;
}
/**注册帧缓冲设备(FrameBuffer)fb_info到系统当中*/
ret = register_framebuffer(&s3cfb_info[index].fb);

if (ret < 0) {
printk(KERN_ERR "Failed to register framebuffer device: %d\n", ret);
goto free_video_memory;
}

printk(KERN_INFO "fb%d: %s frame buffer device\n", s3cfb_info[index].fb.node, s3cfb_info[index].fb.fix.id);
}

/* create device files *//**每一个设备它都有自己的属性,每一个属性都对应着一个文件**/

/**创建设备属性文件**/

ret = device_create_file(&(pdev->dev), &dev_attr_backlight_power);

if (ret < 0)
printk(KERN_WARNING "s3cfb: failed to add entries\n");

ret = device_create_file(&(pdev->dev), &dev_attr_backlight_level);

if (ret < 0)
printk(KERN_WARNING "s3cfb: failed to add entries\n");

ret = device_create_file(&(pdev->dev), &dev_attr_lcd_power);

if (ret < 0)
printk(KERN_WARNING "s3cfb: failed to add entries\n");
printk("jkq debug VIDCON0 is %x\n",readl(S3C_VIDCON0));
return 0;
/********下面这些是各错误函数**/
free_video_memory:
s3cfb_unmap_video_memory(&s3cfb_info[index]);

release_irq:
free_irq(res->start, &info);

release_clock:
clk_disable(info->clk);
clk_put(info->clk);

release_io:
iounmap(info->io);

release_mem:
release_resource(info->mem);
kfree(info->mem);

dealloc_fb:
framebuffer_release(fbinfo);
return ret;
}

/**********接下来我想对prob函数中所调用的部分函数分析分析,这里面所调用的函数有些还真没弄清楚。。******/

/*初始化LCD视频中断控制寄存器0**/

void s3cfb_pre_init(void)
{
/* initialize the fimd specific */
s3cfb_fimd.vidintcon0 &= ~S3C_VIDINTCON0_FRAMESEL0_MASK;
s3cfb_fimd.vidintcon0 |= S3C_VIDINTCON0_FRAMESEL0_VSYNC;
s3cfb_fimd.vidintcon0 |= S3C_VIDINTCON0_INTFRMEN_ENABLE;
/**详情请看S3C6410数据手册第14章482页。。初始化视频中断以VSYNS开始并使能该寄存器*/
writel(s3cfb_fimd.vidintcon0, S3C_VIDINTCON0);
}

/******下面这三个是控制LCD电源以及背光控制的**/

static void s3cfb_set_lcd_power(int to)
{
s3cfb_fimd.lcd_power = to;

if (s3cfb_fimd.set_lcd_power)
(s3cfb_fimd.set_lcd_power)(to);
}

static void s3cfb_set_backlight_power(int to)
{
s3cfb_fimd.backlight_power = to;

if (s3cfb_fimd.set_backlight_power)
(s3cfb_fimd.set_backlight_power)(to);
}

static void s3cfb_set_backlight_level(int to)
{
s3cfb_fimd.backlight_level = to;

if (s3cfb_fimd.set_brightness)
(s3cfb_fimd.set_brightness)(to);
}
/*********************************************************************************************/

/***该函数在probe中被调用就是用来填充各种结构中的成员变量的它们的具体实现在s3cfb_fimd4x.c中**/

static void s3cfb_init_fbinfo(s3cfb_info_t *finfo, char *drv_name, int index)
{
int i = 0;

if (index == 0)
{
if(lcdsize == 0)
s3cfb_init_hw_35();
else if(lcdsize == 1)
s3cfb_init_hw_43();
else if(lcdsize == 2)
s3cfb_init_hw_56();
else if(lcdsize == 3)
s3cfb_init_hw_70();
else if(lcdsize == 4)
s3cfb_init_hw_vga800();
else//这个是我们的LCD尺寸
s3cfb_init_hw_43();//初始化4.3寸液晶显示器
}
/**如果index != 0则将传进来的驱动的名字kaob到不可变参数数组中的ID数组中*/
strcpy(finfo->fb.fix.id, drv_name);//初始化fb_fix_screeninfo->id
finfo->win_id = index;//将窗口索引传入,一共是5个窗口.
finfo->fb.fix.type = FB_TYPE_PACKED_PIXELS;//填充fb_fix_screeninfo->type,使用默认类型,其余还有VGA
finfo->fb.fix.type_aux = 0;//填充fb_fix_screeninfo->type_aux
finfo->fb.fix.xpanstep = 0;//填充fb_fix_screeninfo->xpanstep
finfo->fb.fix.ypanstep = 1;//填充fb_fix_screeninfo->ypanstep
finfo->fb.fix.ywrapstep = 0;//填充fb_fix_screeninfo->ywrapstep
finfo->fb.fix.accel = FB_ACCEL_NONE;//无硬件加速
/***上面这些在初始化不可变参数结构**/
finfo->fb.fbops = &s3cfb_ops; /**给操作文件结构赋值**/
finfo->fb.flags = FBINFO_FLAG_DEFAULT;

finfo->fb.pseudo_palette = &finfo->pseudo_pal;/**16位颜色表**/
/**给可变参数赋值**/
finfo->fb.var.nonstd = 0;//像素格式,0代表标准像素格式,!0代表非标准像素格式
finfo->fb.var.activate = FB_ACTIVATE_NOW;//该宏在fb.h中有定义。
finfo->fb.var.accel_flags = 0;/* (OBSOLETE) see fb_info.flags ,源码注释是这样的也就是根据fb.flags
的取值觉得这个了*/
finfo->fb.var.vmode = FB_VMODE_NONINTERLACED;

finfo->fb.var.xoffset = s3cfb_fimd.xoffset; //0
finfo->fb.var.yoffset = s3cfb_fimd.yoffset; //0
/* 下面就是设置LCD分辨率了,具体的取值情况还要结合数据手册,不过这些默认值在s3cfb_fimd4x.c文件中已经有了,当然了这个文件从官方下载下来的源代码是没有的,这三星提供的吧*/
if (index == 0) {
finfo->fb.var.height = s3cfb_fimd.height;//屏幕高度
finfo->fb.var.width = s3cfb_fimd.width;//屏幕宽度度

finfo->fb.var.xres = s3cfb_fimd.xres;//水平可视
finfo->fb.var.yres = s3cfb_fimd.yres;//垂直可视

finfo->fb.var.xres_virtual = s3cfb_fimd.xres_virtual;//与之对应的虚拟分辨率-水平
finfo->fb.var.yres_virtual = s3cfb_fimd.yres_virtual;//与之对应的虚拟分辨率-垂直

/********这里用文字表达一下:fb_var_screeninfo中的成员变量xres和yres是指在显示屏上真是显示的频率。而xres_virtual和yres_virtual是虚拟分辨率,它们是指显存的分辨率。举个例子假如LCD垂直分辨率是400,而虚拟分辨率是800,这就是说在显存中是存储着800行要显示的,但是实际上显示器每次只能显示400行,至于具体需要显示那些行还需要fb_var_screeninfo中的另一个变量yoffset,若yoffset=0则从0行开始显示400行,n=20则从显存21行开始显示400行。**********/
} else {
finfo->fb.var.height = s3cfb_fimd.osd_height;
finfo->fb.var.width = s3cfb_fimd.osd_width;

finfo->fb.var.xres = s3cfb_fimd.osd_xres;
finfo->fb.var.yres = s3cfb_fimd.osd_yres;

finfo->fb.var.xres_virtual = s3cfb_fimd.osd_xres_virtual;
finfo->fb.var.yres_virtual = s3cfb_fimd.osd_yres_virtual;
}
/**下面这些就与具体的时序有关了**/
finfo->fb.var.bits_per_pixel = s3cfb_fimd.bpp;/*每一像素的位数*/
finfo->fb.var.pixclock = s3cfb_fimd.pixclock;/**像素时钟、单位(ps)**/
finfo->fb.var.hsync_len = s3cfb_fimd.hsync_len;/**行同步信号宽度,用VCLK计算对应时序图中HSPW*/
finfo->fb.var.left_margin = s3cfb_fimd.left_margin;/*行切换:同步到绘图之间的延迟对应HBPD**/
finfo->fb.var.right_margin = s3cfb_fimd.right_margin;/**行切换:绘图到同步之间的延迟对应HFPD*/
finfo->fb.var.vsync_len = s3cfb_fimd.vsync_len;/**帧同步信号长度对应VSPW*/
finfo->fb.var.upper_margin = s3cfb_fimd.upper_margin;/**帧切换:同步到绘图之间的延迟对应VBPD*/
finfo->fb.var.lower_margin = s3cfb_fimd.lower_margin;/**帧切换:绘图到同步之间的延迟对应VFPD*/
finfo->fb.var.sync = s3cfb_fimd.sync;
finfo->fb.var.grayscale = s3cfb_fimd.cmap_grayscale;/**灰度**/

finfo->fb.fix.smem_len = finfo->fb.var.xres_virtual * finfo->fb.var.yres_virtual * s3cfb_fimd.bytes_per_pixel; /*fb缓冲内存的起始地址(物理地址)**/
finfo->fb.fix.line_length = finfo->fb.var.width * s3cfb_fimd.bytes_per_pixel;/*一行的字节数*/

#if !defined(CONFIG_FB_S3C_EXT_VIRTUAL_SCREEN)

#if defined(CONFIG_FB_S3C_EXT_DOUBLE_BUFFERING)
if (index < 2)
finfo->fb.fix.smem_len *= 2;/***缓冲区长度*/
#else
/*
* Some systems(ex. DirectFB) use FB0 memory as a video memory.
* You can modify the size of multiple.
*
* !WARN: smem_len*5 may break the probe for 1024*768
*/
if (index == 0)
finfo->fb.fix.smem_len *= 5;/***缓冲区长度*/
#endif

#endif
/*初始化色调色板(颜色表)为空*/
for (i = 0; i < 256; i++)
finfo->palette_buffer[i] = S3CFB_PALETTE_BUFF_CLEAR;
}

/*********上面这些的具体实现偶看不下去。。。。没有认真去研究s3cfb_fimd4x.c中都实现了*****

在probe函数中调用了该函数为显存分配内存

static int __init s3cfb_map_video_memory(s3cfb_info_t *fbi)
{
DPRINTK("map_video_memory(fbi=%p)\n", fbi);
/**获取framebuffer缓存的大小**/
fbi->map_size_f1 = PAGE_ALIGN(fbi->fb.fix.smem_len);

/**因为系统采用DMA来搬移显示数据,所以使用dma_alloc_writecombine来分配一段writecombine区域**/

fbi->map_cpu_f1 = dma_alloc_writecombine(fbi->dev, fbi->map_size_f1, &fbi->map_dma_f1, GFP_KERNEL);/*分配内存,分配可供DMA使用的地址,fbi->map_cpu_f1为虚拟地址,fbi->map_dma_f1为物理地址*/
fbi->map_size_f1 = fbi->fb.fix.smem_len; //恢复真实的大小

if (fbi->map_cpu_f1) {
/* prevent initial garbage on screen */
printk("Window[%d] - FB1: map_video_memory: clear %p:%08x\n",
fbi->win_id, fbi->map_cpu_f1, fbi->map_size_f1);

/**使用之前先初始化,以防止缓存中的一些无效数据信息显示到LCD上**/

memset(fbi->map_cpu_f1, 0xf0, fbi->map_size_f1);
/**********DMA搬迁数据*****************/
fbi->screen_dma_f1 = fbi->map_dma_f1;//物理地址
fbi->fb.screen_base = fbi->map_cpu_f1;//虚拟地址
fbi->fb.fix.smem_start = fbi->screen_dma_f1;//物理地址

printk(" FB1: map_video_memory: dma=%08x cpu=%p size=%08x\n",
fbi->map_dma_f1, fbi->map_cpu_f1, fbi->fb.fix.smem_len);
}

if (!fbi->map_cpu_f1)
return -ENOMEM;

#if defined(CONFIG_FB_S3C_EXT_DOUBLE_BUFFERING)
if (fbi->win_id < 2 && fbi->map_cpu_f1) {
fbi->map_size_f2 = (fbi->fb.fix.smem_len / 2);
fbi->map_cpu_f2 = fbi->map_cpu_f1 + fbi->map_size_f2;
fbi->map_dma_f2 = fbi->map_dma_f1 + fbi->map_size_f2;

/* prevent initial garbage on screen */
printk("Window[%d] - FB2: map_video_memory: clear %p:%08x\n",
fbi->win_id, fbi->map_cpu_f2, fbi->map_size_f2);

fbi->screen_dma_f2 = fbi->map_dma_f2;

printk(" FB2: map_video_memory: dma=%08x cpu=%p size=%08x\n",
fbi->map_dma_f2, fbi->map_cpu_f2, fbi->map_size_f2);
}
#endif

if (s3cfb_fimd.map_video_memory)
(s3cfb_fimd.map_video_memory)(fbi);

return 0;
}

/*
* s3cfb_check_var():
* Get the video params out of 'var'. If a value doesn't fit, round it up,
* if it's too big, return -EINVAL.
* 检查fb_info中的可变参数,具体的分析还需要S3C6410数据手册,没啥可说的很明了
*/
static int s3cfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
s3cfb_info_t *fbi = (s3cfb_info_t *) info;

DPRINTK("check_var(var=%p, info=%p)\n", var, info);

switch (var->bits_per_pixel) {
case 8://每像素8BPP具体继续往下看
var->red = s3cfb_rgb_8.red;
var->green = s3cfb_rgb_8.green;
var->blue = s3cfb_rgb_8.blue;
var->transp = s3cfb_rgb_8.transp;
s3cfb_fimd.bytes_per_pixel = 1;
break;

case 16: //16BPP
var->red = s3cfb_rgb_16.red;
var->green = s3cfb_rgb_16.green;
var->blue = s3cfb_rgb_16.blue;
var->transp = s3cfb_rgb_16.transp;
s3cfb_fimd.bytes_per_pixel = 2;
break;

case 24://24BPP
var->red = s3cfb_rgb_24.red;
var->green = s3cfb_rgb_24.green;
var->blue = s3cfb_rgb_24.blue;
var->transp = s3cfb_rgb_24.transp;
s3cfb_fimd.bytes_per_pixel = 4;
break;

case 28://28BPP
var->red = s3cfb_rgb_28.red;
var->green = s3cfb_rgb_28.green;
var->blue = s3cfb_rgb_28.blue;
var->transp = s3cfb_rgb_28.transp;
s3cfb_fimd.bytes_per_pixel = 4;
break;

case 32://32bPP
var->red = s3cfb_rgb_32.red;
var->green = s3cfb_rgb_32.green;
var->blue = s3cfb_rgb_32.blue;
var->transp = s3cfb_rgb_32.transp;
s3cfb_fimd.bytes_per_pixel = 4;
break;
}

/* WIN0 cannot support alpha channel. */
if( (fbi->win_id == 0) && (var->bits_per_pixel == 28) ){
var->transp.length = 0;
}

return 0;
}

/*****为了说明上面这个检查可变参数函数下面这个结构定义在s3cfb.h中三星提供的Z官方源码中木有。。。。

typedef struct {
struct fb_bitfield red;//红
struct fb_bitfield green; //绿
struct fb_bitfield blue;//蓝
struct fb_bitfield transp;//透明度
} s3cfb_rgb_t;
//8BPP显示模式,颜色表长度为8位
const static s3cfb_rgb_t s3cfb_rgb_8 = {
.red = {.offset = 0, .length = 8,},
.green = {.offset = 0, .length = 8,},
.blue = {.offset = 0, .length = 8,},
.transp = {.offset = 0, .length = 0,},
};
//16BPP(RGB565显示模式)
const static s3cfb_rgb_t s3cfb_rgb_16 = {
.red = {.offset = 11, .length = 5,},
.green = {.offset = 5, .length = 6,},
.blue = {.offset = 0, .length = 5,},
.transp = {.offset = 0, .length = 0,},
};
//24BPP(A:8:8:8)显示模式
const static s3cfb_rgb_t s3cfb_rgb_24 = {
.red = {.offset = 16, .length = 8,},
.green = {.offset = 8, .length = 8,},
.blue = {.offset = 0, .length = 8,},
.transp = {.offset = 0, .length = 0,},
};
//28Bpp(A:8:8:8)显示模式
const static s3cfb_rgb_t s3cfb_rgb_28 = {
.red = {.offset = 16, .length = 8,},
.green = {.offset = 8, .length = 8,},
.blue = {.offset = 0, .length = 8,},
.transp = {.offset = 24, .length = 4,},
};
//32Bpp(A:8:8:8)显示模式
const static s3cfb_rgb_t s3cfb_rgb_32 = {
.red = {.offset = 16, .length = 8,},
.green = {.offset = 8, .length = 8,},
.blue = {.offset = 0, .length = 8,},
.transp = {.offset = 24, .length = 8,},
};

/**上面这些我是这样理解的不知道有没有错啊,比如说对应//32Bpp(A:8:8:8)显示模式,颜色表长度为32,也就是32bit,每一个像素占一个字节8bit,对应的RGB888,对应的blue长度为8,偏移为0,对应的green长度为8偏移8,对应的red长度为8,偏移刚好是16,剩下的transp偏移为24,长度为8,这不刚好32位长度么?*/

/***对于 s3cfb_init_registers(配置LCD控制器中的各寄存器)还没研究,稍微看了一下。好难。。。。。。。。。






分享到:
评论

相关推荐

    基于百度地图实现的定位功能.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    加载本地图片,绝对不会出现OOM.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    2015年中国移动电子竞技游戏发展趋势报告(1).zip

    2015年中国移动电子竞技游戏发展趋势报告(1).zip

    CKplayer-v6.8.zip

    ckplayer是一款在网页上播放视频的免费的播放器,功能强大,体积小巧,跨平台,使用起来随心所欲。 CKplayer播放器主要以adobe的flash(所使用的版本是CS5)平台开发,所以在支持flash插件的平台和浏览器上都可以使用,而无需下载其它插件,如果你需要修改完整版里提供的相关的flash源文件,请使用adobe的flash cs5以上版本打开源文件修改。 ckplayer同时也支持

    46.书籍学习平台的设计与实现-Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)论坛

    46.书籍学习平台的设计与实现|Springboot+ Mysql+Java+ B/S结构(可运行源码+数据库+设计文档)论坛,公告,付费专区,免费专区,销售,会员办理,书籍分类 详细设计文档链接:http://t.csdnimg.cn/GSeDN 内容概要: 全套项目源码+详尽文档,一站式解决您的学习与项目需求。 适用人群: 计算机、通信、人工智能、自动化等专业的学生、老师及从业者。 使用场景及目标: 无论是毕设、期末大作业还是课程设计,一键下载,轻松部署,助您轻松完成项目。 项目代码经过调试测试,确保直接运行,节省您的时间和精力。 其他说明: 项目整体具有较高的学习借鉴价值,基础能力强的可以在此基础上修改调整,以实现不同的功能。

    密码学实验报告2.docx

    密码学实验报告2.docx

    各种旋转动画的ImageView(1).zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    S7200基本编程指令.ppt

    S7200基本编程指令.ppt

    基于python+OpenCV的火车票识别源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于python+OpenCV的火车票识别源码+使用文档+全部资料(优秀项目).zip基于python+OpenCV的火车票识别源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    WordPress.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    移动机器人机械臂的设计小论文.doc

    移动机器人机械臂的设计小论文.doc

    基于Python+OpenCV+tinker的指纹识别系统,使用的硬件为AS608源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于Python+OpenCV+tinker的指纹识别系统,使用的硬件为AS608源码+使用文档+全部资料(优秀项目).zip基于Python+OpenCV+tinker的指纹识别系统,使用的硬件为AS608源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    xiuno模板知乎蓝魔改版源码附多个插件.zip

    xiuno模板知乎蓝魔改版源码附多个插件

    2022年 【24页】从孪生到融生,AIGC成为长期方向.zip

    2022年 【24页】从孪生到融生,AIGC成为长期方向.zip

    [信息与通信]使用EMIF将Xilinx_FPGA与TI_DSP平台接口.pdf

    [信息与通信]使用EMIF将Xilinx_FPGA与TI_DSP平台接口.pdf

    基于Opencv+Filterpy实现YOLOV3-SORT车辆跟踪与车流统计算法源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 基于Opencv+Filterpy实现YOLOV3-SORT车辆跟踪与车流统计算法源码+使用文档+全部资料(优秀项目).zip基于Opencv+Filterpy实现YOLOV3-SORT车辆跟踪与车流统计算法源码+使用文档+全部资料(优秀项目).zip基于Opencv+Filterpy实现YOLOV3-SORT车辆跟踪与车流统计算法源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    仿QQ消息列表(ListView)滑动删除效果源码.zip

    android 源码学习. 资料部分来源于合法的互联网渠道收集和整理,供大家学习参考与交流。本人不对所涉及的版权问题或内容负法律责任。如有侵权,请通知本人删除。感谢CSDN官方提供大家交流的平台

    最新招标流程图.pdf

    1.招标投标活动不受地区或者部门的限制。任何单位和个人不得违法限制或者排斥本地区、 本系统以外的法人或者其他组织参加投标,不得以任何方式非法干涉招标投标活动。 2.招标人设有标底,标底必须保密 3.可以不招标的情况之一都可以不招标:①不可替代②采购人自行建设、生产或提供③已通 过招标方式特许的④需要向原中标人采购的,否则影响配套要求的,但是不得超过合同金额 的10%⑤国家规定的其他特殊情况

    C++基于自实现OpenCV图像处理函数的静态车道线检测项目源码+使用文档+全部资料(优秀项目).zip

    【资源说明】 C++基于自实现OpenCV图像处理函数的静态车道线检测项目源码+使用文档+全部资料(优秀项目).zipC++基于自实现OpenCV图像处理函数的静态车道线检测项目源码+使用文档+全部资料(优秀项目).zipC++基于自实现OpenCV图像处理函数的静态车道线检测项目源码+使用文档+全部资料(优秀项目).zip 【备注】 1、该项目是个人高分毕业设计项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(如软件工程、计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    基于单片机的遥控机械臂设计.doc

    基于单片机的遥控机械臂设计.doc

Global site tag (gtag.js) - Google Analytics