LCD螢屏簡單概述

?如上圖所示,每個像素點都是由紅綠藍混色而成,目前市面上主流的螢屏每一個原色的色階都是采用8位元來表示,所以每個像素點可以表示大約1600萬中顏色,LCD螢屏由背光層,偏光層,電極層,液晶層,濾光片等組成,液晶是一種介于固體和液體之間的有機化合物,本身不會發光,而是作為一種可透光的物體,通過控制其偏轉角度的大小,來控制透出光線的多少,通過控制不同原色透出光線的多少來表示出不同的顏色(需要通過濾光片),
如何操作LCD
?linux下一切皆檔案,同樣對于外部設備也是通過讀寫對應的檔案來操作設備,對于LCD的操作有如下步驟:
??1.打卡LCD對應的設備檔案;
??2.寫入RGB顏色值;
??3.關閉檔案,
實驗程式
#define LCD_PATH "/dev/fb0"
int main(int argc, char const *argv[])
{
// 打開lcd設備檔案 /dev/fb0 --》 由驅動工程師完成
int fd = open(LCD_PATH , O_WRONLY);
if (fd < 0 )
{
perror("open lcd error");
return -1 ;
}
// 寫入顏色值
int color = 0x698b22 ;
int i ;
for ( i = 0; i < 800*480; i++)
{
write(fd , &color , sizeof(int));
}
// 關閉檔案
close(fd);
return 0;
}
?由上程式可知,write向LCD設備寫入RGB的值來控制LCD的顯示,但是write函式需要進行一系列的系統呼叫才能將資料寫入到設備檔案,這會消耗大量的時間,實驗現象也能看出螢屏從上而下,甚至從左到右的變化,實在是太慢了,使用系統呼叫mmap可以將檔案映射至記憶體(行程空間),如此可以把對檔案的操作轉為對記憶體的操作,這點對于大檔案或者頻繁訪問的檔案尤其有用,提高了I/O效率,
mmap
mmap ( 建立記憶體映射 )
頭檔案:
#include <unistd.h>
#include <sys/mman.h>
定義函式:
void *mmap(void *start, size_t length, int prot,
int flags, int fd, off_t offsize);
引數分析:
start --> 指向欲對應的記憶體起始地址, 通常設為 NULL, 代表讓系統自動選定地址
length --> 需要申請記憶體區域的大小
prot --> 代表映射區域的保護方式有下列組合
PROT_EXEC 映射區域可被執行
PROT_READ 映射區域可被讀取
PROT_WRITE 映射區域可被寫入
PROT_NONE 映射區域不能存取
flags -->會影響映射區域的各種特性
MAP_FIXED 如果引數 start 所指的地址無法成功建立映射時, 則放棄映射, 不對地址做修正.通常不鼓勵用此旗標.
MAP_SHARED 對應射區域的寫入資料會復制回檔案內, 而且允許其他映射該檔案的行程共享.
MAP_PRIVATE 對應射區域的寫入操作會產生一個映射檔案的復制, 即私人的"寫入時復制" (copyon write)對此區域作的任何修改都不會寫回原來的檔案內容.
MAP_ANONYMOUS 建立匿名映射. 此時會忽略引數 fd, 不涉及檔案, 而且映射區域無法和其他行程共享.
MAP_DENYWRITE 只允許對應射區域的寫入操作, 其他對檔案直接寫入的操作將會被拒絕.
MAP_LOCKED 將映射區域鎖定住, 這表示該區域不會被置換(swap:交換空間).
fd --> 需要映射的檔案的檔案描述符
offsize --> 偏移量, 一般設定為零,表示不需要偏移 檔案與記憶體是一一對應的
回傳值:
若映射成功則回傳映射區的記憶體起始地址,
否則回傳 MAP_FAILED(-1), 錯誤原因存于 errno 中.
實驗程式
#define LCD_W 800
#define LCD_H 480
#define LCD_SIZE LCD_W*LCD_H*4
#define LCD_PATH "/dev/fb0"
int main(int argc, char const *argv[])
{
int fd = open(LCD_PATH , O_RDWR);
if (fd < 0 )
{
perror("open lcd error");
return -1 ;
}
// 記憶體映射
int * lcd_p = (int *)mmap(NULL , // 指向欲對應的記憶體起始地址, 通常設為 NULL, 代表讓系統自動選定地址
LCD_SIZE, // 顯示幕的大小
PROT_READ | PROT_WRITE, // 配置記憶體區可讀, 可寫
MAP_SHARED, // 設定記憶體區為共享*(對記憶體的任何操作都會被復制到檔案中)
fd, // 需要映射的檔案
0); // 偏移量
if (NULL == lcd_p)
{
perror("mmap error ");
return -1 ;
}
// 寫入顏色值
int color = 0xFF3030 ;
int i ;
for ( i = 0; i < 800*480; i++)
{
*(lcd_p+i) = color ;
}
close(fd);
return 0;
}
?將此程式編譯到開發板上運行時,肉眼看不到螢屏變化的程序,建立記憶體映射能夠大大提高I/O的效率,
實驗程式
?以下程式是一個"跑馬燈程式",將螢屏分成了不同顏色的八塊,并按順時針"跑動",
#define LCD_W 800
#define LCD_H 480
#define LCD_SIZE LCD_W*LCD_H*4
#define CYAN 0x00FFFF
#define PPuff 0xFFDAB9
#define RED 0xFF0000
#define YELLOW 0XFFFF00
#define BLUE 0x0000FF
#define INRED 0xEE6363
#define SNOW 0xFFFAFA
#define PURPLE 0xA020F0
#define LCD_PATH "/dev/fb0"
int color[8] = {CYAN, PPuff, RED, YELLOW, BLUE, INRED, SNOW, PURPLE};
bool draw_point(int *address, int color, int x, int y) //畫點函式:x,y用來表示坐標值
{
if (NULL == address)
{
printf("draw_point msg:%s\n", strerror(errno));
return false;
}
*(address + (x + (y*800))) = color;
return true;
}
bool draw_line(int *address, int color, int len, int x, int y) //畫線函式:以坐標(x,y)為起點,畫一條長度為len的橫線
{
if (NULL == address)
{
printf("draw_line msg:%s\n", strerror(errno));
return false;
}
while (len--)
{
draw_point(address, color, x, y);
address++;
}
return true;
}
bool draw_surface(int *address, int color, int high, int len, int x, int y)//畫面函式:以坐標(x,y)為起點,畫一個長為len,高high的面
{
if (NULL == address)
{
printf("draw_surface msg:%s\n", strerror(errno));
return false;
}
while (high--)
{
draw_line(address, color, len, x, y);
address = address + LCD_W;
}
return true;
}
int main(int argc, char const *argv[])
{
int fd = open(LCD_PATH , O_RDWR);
if (fd < 0 )
{
perror("open lcd error");
return -1 ;
}
// 記憶體映射
int * lcd_p = (int *)mmap(NULL , // 指向欲對應的記憶體起始地址, 通常設為 NULL, 代表讓系統自動選定地址
LCD_SIZE, // 顯示幕的大小
PROT_READ | PROT_WRITE, // 配置記憶體區可讀, 可寫
MAP_SHARED, // 設定記憶體區為共享*(對記憶體的任何操作都會被復制到檔案中)
fd, // 需要映射的檔案
0); // 偏移量
if (NULL == lcd_p)
{
perror("mmap error ");
return -1 ;
}
int div_wide = 800 / 4;
int div_high = 480 / 2;
int i = 0;
int j = 0 ;
// 將螢屏分為八塊,寫入不同顏色值,并讓其順時針“跑”起來
while (1)
{
draw_surface(lcd_p, color[i++], div_high, div_wide, 0, 0);j++;
if (7 <= i)
{
i = i % 8;
}
draw_surface(lcd_p, color[i++], div_high, div_wide, div_wide, 0);j++;
if (7 <= i)
{
i = i % 8;
}
draw_surface(lcd_p, color[i++], div_high, div_wide, div_wide*2, 0);j++;
if (7 <= i)
{
i = i % 8;
}
draw_surface(lcd_p, color[i++], div_high, div_wide, div_wide*3, 0);j++;
if (7 <= i)
{
i = i % 8;
}
draw_surface(lcd_p, color[i++], div_high, div_wide, div_wide*3, div_high);j++;
if (7 <= i)
{
i = i % 8;
}
draw_surface(lcd_p, color[i++], div_high, div_wide, div_wide*2, div_high);j++;
if (7 <= i)
{
i = i % 8;
}
draw_surface(lcd_p, color[i++], div_high, div_wide, div_wide, div_high );j++;
if (7 <= i)
{
i = i % 8;
}
draw_surface(lcd_p, color[i], div_high, div_wide, 0, div_high);j++;
if (7 <= i)
{
i = i % 8;
}
if (64 == j)//防止i,j無限增長
{
j = 0;
i = 0;
}
usleep(160000);
}
close(fd);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/237402.html
標籤:其他
