S3C2440 (4.3寸)LCD驱动程序之层次分析(十六)
参考:http://www.cnblogs.com/lifexy/p/7604011.html
在上一节LCD层次分析时,得出写个LCD驱动入口函数,需要以下4步:
1)分配一个fb_info结构体:framebuffer_alloc();
2)设置fb_info;
3)设置硬件相关的操作;
4)使能LCD,并注册fb_info:register_framebuffer();
本节需要用到的函数:
函数dma_alloc_writecombine():(分配显存)
void * dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);//分配DMA缓存区给现存
//返回值为:申请到的DMA缓冲区的虚拟地址,若为NULL,表示分配失败,则需要使用dma_free_writecombine()释放内存,避免内存泄漏
//参数如下://*dev:指针,这里填0,表示这个申请的缓冲区里没有内容//size:分配的地址大小(字节单位)//*handle:申请到的物理起始地址//gfp:分配出来的内存参数,标志定义在<linux/gfp.h>,常用标志如下://GFP_ATOMIC 用来从中断处理和进程上下文之外的其它代码中分配内存.从不睡眠//GFP_KERNEL 内核内存的正常分配,可能睡眠//GFP_USER 用来为用户空间页来分配内存;它可能睡眠
分配一段DMA缓存区,分配出来的内存会禁止cache缓存(因为DMA传输不需要CPU)
它和dm_alloc_coherent()函数相似,不过dma_alloc_writecombine()函数是分配出来的内存会禁止cache缓存以及禁止写入缓冲区
---------------------------------------------------------------------------------------
函数dma_free_writecombine():(释放显存)
void dma_free_writecombine(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle);
//cpu_addr:虚拟地址
//handle:物理地址
释放DMA缓冲区,dev和size参数和上面的函数一样
---------------------------------------------------------------------------------------
函数frambuffer_alloc():(申请fb_info结构体)
struct fb_info *framebuffer_alloc(size_t size, struct device *dev)//申请一个fb_info结构体
//size:额外的内存(里面放私有数据private)
//*dev:指针,这里填写NULL,表示这个申请的结构体没有内容
---------------------------------------------------------------------------------------
函数register_frambuffer()和函数frambuffer_release():
int register_framebuffer(struct fb_info *fb_info)//向内核中注册fb_info结构体,若内存不够,注册失败会返回负数
void framebuffer_release(struct fb_info *info)//注销内核中fb_info结构体
---------------------------------------------------------------------------------------
本节需要用到的结构体:
fb_info结构体如下:
struct fb_info {int node;int flags;struct fb_var_screeninfo var; //可变的参数struct fb_fix_screeninfo fix; //固定的参数
… …struct fb_ops *fbops; //操作函数
… …char __iomem *screen_base; //显存虚拟起始地址unsigned long screen_size; //显存虚拟地址长度void *pseudo_palette; /* Fake palette of 16 colors */ //假的16色调色板,里面存放了16色的数据,可以通过8bpp数据来找到调色板里面的16色颜色索引值,模拟出16色颜色来,节省内存,不需要的话就指向一个不用的数组即可
};
其中操作函数fb_info->fbops结构体写法如下:
static struct fb_ops s3c_lcdfb_ops = {.owner = THIS_MODULE,//可以参考\drivers\video\Atmel_lcdfb.c.fb_setcolreg = s3c_lcdfb_setcolreg, //设置调色板fb_info->pseudo_palette,自己构造该函数//下面三个函数是对显存的操作.fb_fillrect = cfb_fillrect, //填充一个矩形,用/driver/video/cfbfillrect.c里的函数即可.fb_copyarea = cfb_copyarea, //拷贝一个区域,用/driver/video/cfbcopyarea.c里的函数即可.fb_imageblit = cfb_imageblit, //图形填充,用/driver/video/imageblit.c里的函数即可
};
固定的参数fb_info->fix 结构体如下:
struct fb_fix_screeninfo {char id[16]; //id名字unsigned long smem_start; //framebuffer物理起始地址__u32 smem_len; //framebuffer长度,字节为单位__u32 type; //lcd类型,默认值为0即可__u32 type_aux; //附加类型,为0__u32 visual; //画面设备,常见参数如下
// FB_VISUAL_MONO01 0 单色,0:白色,1:黑色
// FB_VISUAL_MONO10 1 单色,1:黑色,1:白色
// FB_VISUAL_TRUECOLOR 2 真彩(TFT:真彩)
// FB_VISUAL_PSEUDOCOLOR 3 伪彩
// FB_VISUAL_DIRECTCOLOR 4 直彩__u16 xpanstep; /* 如果没有硬件panning就赋值为0 */__u16 ypanstep; /* 如果没有硬件panning就赋值为0 */__u16 ywrapstep; /* 如果没有硬件panning就赋值为0 */__u32 line_length; /* 一行的字节数,例:(RGB565)240*320,那么这里就等于240*16/8 *//* 以下成员都可以不需要 */unsigned long mmio_start; /*内存映射IO的起始地址,用于应用层直接访问寄存器,可以不需要 */__u32 mmio_len; /* 内存映射IO的长度,可以不需要 */__u32 accel; /* Indicate to driver which *//* specific chip/card we have */__u16 reserved[3]; /* Reserved for future compatibility */
};
可变的参数fb_info->var结构体如下:
struct fb_var_screeninfo {__u32 xres; /* 可见屏幕一行有多少个像素点 */__u32 yres; /* 可见屏幕一列有多少个像素点 */__u32 xres_virtual; /* 虚拟屏幕一行有多少个像素点 */__u32 yres_virtual; /* 虚拟屏幕一列有多少个像素点 */__u32 xoffset; /* 虚拟到可见屏幕之间的行偏移,若可见和虚拟的分频率一样,就直接设为0 */__u32 yoffset; /* 虚拟到可见屏幕之间的列偏移 */__u32 bits_per_pixel; /* 每个像素的位数即BPP,比如:RGB565,则填入16 */__u32 grayscale; /* 非0时,指的是灰度,真彩直接填0即可 */struct fb_bitfield red; //fb缓存的R位域,fb_bitfield结构体成员如下:
// __u32 offset; 区域偏移值,比如RGB565中的R,就在第11位
// __u32 length; 区域长度,比如RGB565的R,共有5位
// __u32 msb_right; msb_right==0,表示数据左边最大,msb_right!=0,表示数据右边最大
};struct fb_bitfield green; /* fb缓存的G位域 */struct fb_bitfield blue; /* fb缓存的B位域 *//* 以下参数都可以不填,默认为0 */struct fb_bitfield transp; /* 透明度,不需要填0即可 */ __u32 nonstd; /* !=0表示非标准像素格式 */__u32 activate; /* 设为0即可 */__u32 height; /* 外设高度(单位mm),一般不需要填 */__u32 width; /* 外设宽度(单位mm),一般不需要填 */__u32 accel_flags; /* 过时的参数,不需要填 *//* 除了pixclock本身外,其它的都以像素时钟为单位 */__u32 pixclock; /* 像素时钟(皮秒) */__u32 left_margin; /* 行切换,从同步到绘图之间的延迟 */__u32 right_margin; /* 行切换,从绘图到同步之间的延迟 */__u32 upper_margin; /* 帧切换,从同步到绘图之间的延迟 */__u32 lower_margin; /* 帧切换,从绘图到同步之间的延迟 */__u32 hsync_len; /* 水平同步的长度 */__u32 vsync_len; /* 垂直同步的长度 */__u32 sync; /* see FB_SYNC_* */__u32 vmode; /* see FB_VMODE_* */__u32 rotate; /* angle we rotate counter clockwise */__u32 reserved[5]; /* 保留 */
};
1、写驱动程序:
(写驱动可以参考自带的LCD平台驱动drivers/video/s3c2410fb.c)
(LCD控制寄存器设置:参考之前的LCD裸机驱动:(硬件设置)https://blog.csdn.net/xiaodingqq/article/details/80724190)
1.1 步骤如下:
在驱动init入口函数中:
(1)分配一个fb_info结构体
(2)设置fb_info
(2.1)设置固定的参数fb_info->fix
(2.2)设置可变的参数fb_info->var
(2.3)设置操作函数fb_info->fbops
(2.4)设置fb_info其它的成员
(3)设置硬件相关的操作
(3.1)配置LCD引脚
(3.2)根据LCD手册设置LCD控制器
(3.3)分配显存(framebuffer),把地址告诉LCD控制器和fb_info
(4)开启LCD,并注册fb_info:register_framebuffer()
(4.1)直接在init函数中开启LCD(后面讲到电源管理,再来优化)
控制LCDCON5允许PWREN信号,
然后控制LCDCON1输出PWREN信号,
输出GPB0高电平来开背光,
(4.2)注册fb_info
在驱动exit出口函数中:
(1)卸载内核中的fb_info
(2)控制LCDCON1关闭PWREN信号,关背光灯,iounmap注销地址
(3)释放DMA缓存地址dma_free_writecombine()
(4)释放注册的fb_inifo
1.2具体的代码如下:
#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/interrupt.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.h>
#include <asm/arch/regs-lcd.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/fb.h>static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red, //设置调色板unsigned int green, unsigned int blue,unsigned 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;unsigned long reserved[9]; //保留9个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, //填充一个矩形.fb_copyarea = cfb_copyarea, //拷贝一个区域.fb_imageblit = cfb_imageblit, //图形填充
};static struct fb_info *s3c_lcd;
static volatile unsigned long *gpbcon;
static volatile unsigned long *gpbdat;
static volatile unsigned long *gpccon;
static volatile unsigned long *gpdcon;
static volatile unsigned long *gpgcon;
static volatile struct lcd_regs* lcd_regs;
static u32 pseudo_palette[16]; //假的调色板,调色板数组,被fb_info->pseudo_palette调用/* from pxafb.c */
static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{chan &= 0xffff;chan >>= 16 - bf->length;return chan << bf->offset;
}static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red, //设置调色板unsigned int green, unsigned int blue,unsigned int transp, struct fb_info *info)
{unsigned int val;if (regno > 16) //regno哪一个调色板return 1;/* 用read,green,blue三原色构造出val */val = chan_to_field(red, &info->var.red);val |= chan_to_field(green, &info->var.green);val |= chan_to_field(blue, &info->var.blue);//((u32 *)(info->pseudo_palette))[regno] = val;pseudo_palette[regno] = val; //放到调色板数组中return 0;
}static int lcd_init(void)
{/* 1. 分配一个fb_info *///第一个参数大小:size表示分配额外的空间(里面放私有数据private)s3c_lcd = framebuffer_alloc(0, NULL); //不分配额外的空间/* 2. 设置 *//* 2.1 设备固定的参数fix */strcpy(s3c_lcd->fix.id, "mylcd");//名字ids3c_lcd->fix.smem_len = 480*272*16/8; //显存的长度(需要看LCD手册)分辨率resolution:480*272,RGB(Bit):565,一个像素16位s3c_lcd->fix.type = FB_TYPE_PACKED_PIXELS; //在fb.h,使用默认值(值为0)s3c_lcd->fix.visual = FB_VISUAL_TRUECOLOR; /* visual视觉的 TFTLCD:真彩色 */s3c_lcd->fix.line_length = 480*2; //一行480个像素,一个像素16位(2个字节)/* 2.2 设置可变的参数var */s3c_lcd->var.xres = 480; //x方向的分辨率s3c_lcd->var.yres = 272; //y方向的分辨率s3c_lcd->var.xres_virtual = 480; //电脑桌面点击右键,设置分辨率(虚拟分辨率)s3c_lcd->var.yres_virtual = 272; //虚拟分辨率s3c_lcd->var.bits_per_pixel = 16; //每个像素用多少位/* RGB:565 */s3c_lcd->var.red.offset = 11; //红色的偏移值从bit11开始s3c_lcd->var.red.length = 5; //红色的长度为5位s3c_lcd->var.green.offset = 5; //绿色的偏移值从bit5开始s3c_lcd->var.green.length = 6; //绿色的长度为6位s3c_lcd->var.blue.offset = 0; //蓝色的偏移值从bit0开始s3c_lcd->var.blue.length = 5; //蓝色的长度为5位s3c_lcd->var.activate = FB_ACTIVATE_NOW; //使用默认值/* 2.3 设置操作函数fbops */s3c_lcd->fbops = &s3c_lcdfb_ops;/* 2.4 其他的设置 */s3c_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); //映射8个字节gpbdat = gpbcon+1; //指针加1相当于加4gpccon = ioremap(0x56000020, 4); //一页一页地映射的,所以size写4或者1024都可以gpdcon = ioremap(0x56000030, 4);gpgcon = ioremap(0x56000060, 4);//参考以前的裸机程序lcddrv.c*gpccon = 0xaaaaaaaa; /* GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND */*gpdcon = 0xaaaaaaaa; /* GPIO管脚用于VD[23:8] */*gpbcon &= ~(3); /* GPB0(KEYBOARD)设置为输出引脚 */*gpbcon |= 1;*gpbdat &= ~1; /* 输出低电平,背光先不开启 */*gpgcon |= (3<<8); /* GPG4用作LCD_PWREN *//* 3.2 根据LCD手册设置LCD控制器,比如VCLK的频率等 *///映射所有的lcdconX控制器lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));/* bit[17:8]: VCLK = HCLK / [(CLKVAL+1) x 2] ,具体可看LCD手册* 10MHz(100ns) = 100MHz / [(CLKVAL+1) x 2]* CLKVAL = 4* bit[6:5]:0b11,TFT LCD* bit[4:1]:0b1100 16bpp for TFT (每个像素用16位来表示)* bit[0] :0 = Disable the video output and the LCD control signal. */lcd_regs->lcdcon1 = (4<<8) | (3<<5) | (0x0c<<1); /* 垂直方向的时间参数* bit[31:24]:VBPD,VSYNC之后再过多长时间才能发出第1行数据* LCD手册 tvb=2* 所以VBPD=1* bit[23:14]:多少行,272行,所以LINEVAL=272-1=271* bit[13:6] :VFPD,发出最后一行数据之后,再过多长时间才发出VSYNC* LCD手册 tvf=2,所以VFPD=2-1=1* bit[5:0] :VSPW,VSYC信号的脉冲宽度,LCD手册 tvp=10,所以VSPW=10-1=9*/lcd_regs->lcdcon2 = (1<<24) | (271<<14) | (1<<6) | (9);/* 水平方向的时间参数* bit[25:19]:HBPD,HSYNC之后再过多长时间才能发出第1个像素的数据* LCD手册 thb=2* 所以HBPD=1* bit[18:8]: 多少列,480列,所以LINEVAL=480-1=479* bit[7:0] : HFPD,发出最后一行里,最后一个像素之后,再过多长时间才发出HSYNC* LCD手册 thf=2,所以HFPD=2-1=1*/lcd_regs->lcdcon3 = (1<<19) | (479<<8) | (1);/* 水平方向的同步信号* bit[7:0] : HSPW,HSYC信号的脉冲宽度,LCD手册 thp=41,所以HSPW=41-1=40*/lcd_regs->lcdcon4 = 40;/* 信号的极性 * bit[11]:1=565 format* bit[10]:0 = The video data is fetched at VCLK falling edge 在下降沿取数据* bit[9]:1 = HSYNC信号要反转,即低电平有效(水平方向的同步信号,在2440与LCD手册相反,所以要反转)* bit[8]:1 = VSYNC信号要反转,即低电平有效* bit[6]:0 = VDEN不用反转(数据引脚VD0~VD23)* bit[3]:0 = PWREN输出低电平* bit[1]:0 = BSWAP* bit[0]:1 = HWSWP 看2440手册 P413*/lcd_regs->lcdcon5 = (1<<11) | (0<<10) | (1<<9) | (1<<8) | (1<<0);/* 3.3 分配显存(frambuffer,在SDRAM内存划分出来的),并把地址告诉LCD控制器 *///第3个参数存放物理地址,返回值为这块内存的虚拟地址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) & ~(3<<30); //第0位和最高位忽略,保存缓冲起始地址A[30:1]lcd_regs->lcdsaddr2 = ((s3c_lcd->fix.smem_start + s3c_lcd->fix.smem_len) >> 1) & 0x1fffff; //结束地址=开始地址+长度,只关心21位,保存缓冲结束地址A[21:1]lcd_regs->lcdsaddr3 = (480*16/16); /* 一行的长度(单位:半字,就是2个字节) *///s3c_lcd->fix.smem_start = xxx; //显存的物理地址/* 启动LCD */lcd_regs->lcdcon1 |= (1<<0); /* 使能LCD控制器 */lcd_regs->lcdcon5 |= (1<<3); /* 使能LCD本身 */*gpbdat |= 1; /* 原来输出低电平,现在输出高电平,使能背光灯 *//* 4. 注册 */register_framebuffer(s3c_lcd);return 0;
}static void lcd_exit(void)
{unregister_framebuffer(s3c_lcd);lcd_regs->lcdcon1 &= ~(1<<0); /* 关闭LCD本身,省电 */*gpbdat &= ~1; /* 关闭背光灯 */dma_free_writecombine(NULL, s3c_lcd->fix.smem_len, s3c_lcd->screen_base, s3c_lcd->fix.smem_start);//释放显存,第三个参数cpu地址,就是虚拟地址,第四个参数,handle物理地址iounmap(lcd_regs);iounmap(gpbcon);iounmap(gpccon);iounmap(gpdcon);iounmap(gpgcon);framebuffer_release(s3c_lcd); //释放掉fb_info的sc3_lcd结构体
}module_init(lcd_init);
module_exit(lcd_exit);
MODULE_LICENSE("GPL");
2、重新编译内核,去掉原来的LCD驱动程序
在内核代码目录下,输入命令make menuconfig,进入menu菜单重新设置内核参数:
进入-> Device Drivers-> Graphics support<M> S3C2410 LCD framebuffer support
(上面“<*>s3c2410 LCD framebuffer support”是之前自带的驱动程序,这里去掉后以<M>模块方式编译进内核)
(<M>模块方式编译进内核)
然后make uImage编译内核(如果生成的是zImage,而不是uImage,可以点击这里)
编译好的uImage 在 arch/arm/boot/uImage
make modules编译模块(编译好的3个模块在drivers/video)
cp arch/arm/boot/uImage /work/nfsroot
cp drivers/video cfb*.ko /work/nfsroot
为什么要编译模块?
因为LCD驱动相关的文件也没有编进内核,而fb_ops里的成员fb_fillrect(),fb_copyarea(),fb_imageblit()用的都是drivers/video下面的3个文件所以需要这3个的.ko模块。
3、使用新的uImage来启动开发板
(3.1) 启动开发板,进入uboot的菜单界面,然后输入q退出菜单,进入命令行。
(3.2) 打开tftpd32.exe软件,选择需要传输文件的目录,以及PC机(服务器)的ip地址。
(3.3) 在uboot的命令行,输入命令tftp 30000000 uImage(把在PC机的uImage传到地址30000000上(SDRAM))。
(3.4) 输入bootm 30000000,开发板从地址30000000开始启动内核。
4、挂载驱动
(4.1) 把编译好的LCD驱动模块和drivers/video里的3个.ko模块放入nfs文件系统(/work/nfsroot)中,
(4.2) 使用nfs网络文件系统挂载,输入命令:
mount -t nfs -o intr,nolock,rsize=1024,wsize=1024 192.168.1.3:/work/nfsroot /mnt
(如果nfs挂载后,不能读取,可以点击这里)
(4.3) 先装载3个/drivers/video下编译好的模块(cfbcopyvarea.ko、cfbfillrect.ko、cfbimgblt.ko),再来装载LCD驱动模块(lcd.ko)。
(4.4) 挂载LCD驱动后,可以通过ls -l /dev/fb*命令查看已挂载的LCD设备节点。
5、测试运行
echo hello > /dev/tty1
ls -l > /dev/tty1
6、优化。(使用上节的键盘驱动在LCD终端打印命令行)
(5.1)vi /etc/inittab (修改inittab,inittab:配置文件,用于启动init进程时,读取inittab)
添加tty1::askfirst:-/bin/sh (将sh进程(命令行)输出到tty1里,也就是LCD输出信息)
(5.2)然后重启,insmod装载/drivers/video下编译好的模块,再来insmod装载LCD驱动模块,tty1设备便有了,就能看到信息。
(5.3)最后insmod上一节的键盘驱动buttons.ko后,按下"Enter"按键,便能在LCD终端上操作linux了。
(5.4)如果按下Enter键,它就启动了一个进程号770的-sh进程,如下图发现这个-sh的描述符指向tty1:
S3C2440 (4.3寸)LCD驱动程序之层次分析(十六)相关推荐
- Linux内核 LCD 驱动程序框架
Linux 内核 LCD 驱动程序框架 1. framebuffer 简介 1.1 什么是 framebuffer 1.2 framebuffer的作用 2. framebuffer 驱动的框架 3. ...
- 树莓派触摸屏连接方法(微雪7寸LCD)
微雪 7寸LCD 触摸屏 显示器 适用 树莓派 BB BLACK 电脑 HDMI高清,购买地址如下: https://detail.tmall.com/item.htm?spm=a220o.10008 ...
- 嵌入式驱动编写-LCD驱动程序
如何来写LCD的驱动程序,首先 看芯片开发手册和原理图 根据原理图,找到s3c2440的GPIO控制管脚,gpb gpc gpd gpg管脚控制 需要设置寄存器 以及设置LCD控制寄存器 查看 ...
- linux驱动LCD 驱动程序代码编写
转自 在编写代码之前我们先来看一看原理图 引脚说明: VCLK:发出lcd时钟信号,每来一个时钟,就会在屏幕上显示一个像素 --GPC1 :配置为lcd引脚 VLINE:发出lcd行扫描信 ...
- LCD驱动程序——代码编写(二)
转自http://liu1227787871.blog.163.com/blog/static/205363197201242393031250/ 在编写代码之前我们先来看一看原理图 引脚说明: VC ...
- linux lcd驱动调试 echo dev/fb0,LCD驱动程序 - osc_msmij2gf的个人空间 - OSCHINA - 中文开源技术交流社区...
LCD驱动程序 假设 app: open("/dev/fb0", ...) 主设备号: 29, 次设备号: 0 kernel: fb_open int fbidx = iminor ...
- lcd图片转二进制工具_辽宁2.8寸LCD屏价格,测距仪LCD显示屏_思迈微
首页 > 新闻中心 发布时间:2020-11-15 08:27:09 导读:思迈微为您提供辽宁寸LCD屏价格,测距仪LCD显示屏的相关知识与详情: 以上便是对LED点阵式显示屏的软硬件系统.组成 ...
- LCD笔记(7)LCD驱动程序框架_配置时钟
1. 硬件相关的操作 LCD驱动程序的核心就是: 分配fb_info 设置fb_info 注册fb_info 硬件相关的设置 硬件相关的设置又可以分为3部分: 引脚设置 时钟设置 LCD控制器设置 本 ...
- [nRF51822] 1、一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO
最近用nRF51822写了个天马4线SPI的1.77寸LCD彩屏驱动,效果如下: 屏幕的规格资料为:http://pan.baidu.com/s/1gdfkr5L 屏幕的驱动资料为:http://pa ...
最新文章
- 深度学习指数的使用——np.exp(-4)和1e-4的区别
- 数据是互联网下半场产品人突围之道
- jquery标签选择器应用示例
- php中target用法,Yii使用DbTarget实现日志功能的示例代码
- 在竞争激烈的ToB公司,这个创始团队拒绝一夜暴富,坚持做好产品
- Delphi/C#之父:Anders Hejlsberg
- python做的大型游戏_Python实现数据量较大的生命游戏
- 犯病的chorme(谷歌浏览器)之css加载失败
- NodeJS写模块和引入模块的例子
- 适用于苹果Mac的 5 个最佳 SSH 客户端软件
- 类/对象/构造函数/析构函数
- js 表单打开新窗口
- 翻译: 深入神经网络概览Dive into Deep Learning
- 十次方:区块链需要服务器吗?
- 为什么会有这么多中间表?
- 优秀的网站加速插件 – WP rocket详细设置教程
- 数组方法的增删等19种操作:unshift 、shift,push、pop、splice等等...!
- 【屌丝之作】3D遥控坦克大战
- Mac Elasticsearch 7.9.3 安装指南
- Hive(11):Hive的函数之内置函数
热门文章
- C#之禁用任务管理器(对注册表项的访问被拒绝)
- 计算机病毒学课本,计算机病毒实验教程
- 实验一 /*被动扫描,利用搜索引擎或相关网站*/
- 如何用python写一个文件管理程序
- Python界面编程第九课:Pyside2 (Qt For Python)创建数字时钟
- 关于 “exported needs to be explicitly specified for <activity>.” 问题的解决。
- 当年的三国java游戏_三国卡牌类手游塞班 分享问几年前玩的一个三国
- qHD、HD、FHD、QHD、UHD的区别
- 网页打印非常优秀的插件 Print.js
- IDEA软件安装与配置