Linux幀緩沖注冊OLED驅動(上)
1.幀緩沖Framebuff
在 linux 系統中 LCD 這類設備稱為幀緩沖設備,英文 frameBuffer 設備。
frameBuffer 是出現在 2.2.xx 內核當中的一種驅動程序接口。
幀緩沖( framebuffer)是 Linux 系統為顯示設備提供的一個接口,它將顯示緩沖區抽象,屏蔽圖像硬件的底層差異,允許上層應用程序在圖形模式下直接對顯示緩沖區進行讀寫操作。用戶不必關心物理顯示緩沖區的具體位置及存放方式,這些都由幀緩沖設備驅動本身來完成。
用戶可以將 Framebuffer 看成是顯示內存的一個映像, 將其映射到進程地址空間之后,就可以直接進行讀寫操作,而寫操作可以立即反應在屏幕上。
幀緩沖驅動是字符類設備的一種,主設備號為29,生成的設備節點為/dev/fb*。
使用幀緩沖完成屏幕驅動注冊,應用層只需調用open函數打開失敗,再通過ioctl函數獲取屏幕的參數信息,再調用mmap函數將屏幕顯存地址映射到進程空間,接下來對地址的寫入即是對屏幕的刷。
2.幀緩沖Framebuff應用編程
幀緩沖應用層編程步驟
打開LCD設備open(“/dev/fb0”,2);
獲取固定參數和可變參數ioctl;
將屏幕緩沖區映射到進程空間mmap;
實現屏幕最核心函數畫點函數;
2.1 幀緩沖Framebuff設備節點
通過幀緩沖完成屏幕驅動注冊,會在/dev下生成設備節點,主設備號為29,注冊的一個設備驅動為/dev/fb0,第二個為/dev/fb1,依此類推,最大可以注冊32個設備。
2.2 固定參數
通過ioctl函數,命令參數為FBIOGET_FSCREENINFO,固定參數結構體為struct fb_fix_screeninfo。在固定參數可獲得的屏幕信息有:smem_len屏幕緩沖區大小、line_length一行的字節數。
#define FBIOGET_FSCREENINFO 0x4602 /*獲取屏幕固定參數*/
/*固定參數結構體*/
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem 屏幕物理地址 */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem 屏幕緩沖區大小*/
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes 一行的字節數 */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 capabilities; /* see FB_CAP_* */
__u16 reserved[2]; /* Reserved for future compatibility */
};
2.3 可變參數
??通過ioctl函數,命令參數為FBIOGET_VSCREENINFO,固定參數結構體為struct fb_fix_screeninfo。在固定參數可獲得的屏幕信息有:屏幕寬度xres、屏幕高度yres、顏色位數bits_per_pixel。
#define FBIOGET_VSCREENINFO 0x4600 /*獲取屏幕可變參數*/
/*可變參數結構體*/
struct fb_var_screeninfo {
__u32 xres; /* visible resolution屏幕寬度 */
__u32 yres; /*屏幕高度*/
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what 顏色位數 */
__u32 grayscale; /* 0 = color, 1 = grayscale, */
/* >1 = FOURCC */
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 colorspace; /* colorspace for FOURCC-based modes */
__u32 reserved[4]; /* Reserved for future compatibility */
};
2.4 將屏幕緩沖區映射到進空間
#include
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
函數功能: 將文件映射到進程空間
形參: addr --映射的虛擬地址,一般填NULL,有系統自行分配
???length --要映射的空間大小
???prot --PROT_READ可讀;PROT_WRITE可寫
???flags --MAP_SHARED可讀寫,讀寫內容同步到文件;MAP_PRIVATE修改的內容不會同步到文件
???fd --文件描述符
???offset --一般填0,表示映射整個文件
返回值: 成功返回映射的地址
???失敗返回-1
int munmap(void *addr, size_t length);
形參: addr --mamp函數返回值
???length --映射空間大小
2.5 幀緩沖獲取固定參數和可變參數示例
int main()
{
/*1.打開設備*/
int fd=open("/dev/fb0", 2);
if(fd<0)
{
printf("打開設備失敗n");
}
/*2.獲取固定參數*/
memset(&fb_fix,0, sizeof(fb_fix));
ioctl(fd,FBIOGET_FSCREENINFO,&fb_fix);
printf("屏幕緩存大小:%dn",fb_fix.smem_len);
printf("一行的字節數:%dn",fb_fix.line_length);
/*3.獲取屏幕可變參數*/
memset(&fb_var,0, sizeof(fb_var));
ioctl(fd,FBIOGET_VSCREENINFO,&fb_var);
printf("屏幕尺寸:%d*%dn",fb_var.xres,fb_var.yres);
printf("顏色位數:%dn",fb_var.bits_per_pixel);
/*4.將屏幕緩沖區映射到進程空間*/
lcd_p=mmap(NULL,fb_fix.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
if(lcd_p==(void *)-1)
{
printf("內存映射失敗n");
return 0;
}
memset(lcd_p,0xff,fb_fix.smem_len);//將屏幕清空為白色
//取消映射
munmap(lcd_p,fb_fix.smem_len);
return 0;
}
/*畫點函數實現*/
static inline void LCD_DrawPoint(int x,int y,int c)
{
//獲取要繪制的點的地址
unsigned int *p= (unsigned int *)(lcd_p+y*fb_fix.line_length+x*fb_var.bits_per_pixel/8);
*p=c;//寫入顏色值
}
-
OLED
+關注
關注
119文章
6200瀏覽量
224216 -
Linux
+關注
關注
87文章
11304瀏覽量
209524
發布評論請先 登錄
相關推薦
評論