S5PV210之LCD畫圖、字符串、顯示圖…

        這個週末又獻給了S5PV210。以前在學習裸機的時候並沒意識發博客記錄學習過程。當遇到自己特別感興趣又需要學習的知識時,就會有很強的感覺去記錄自己學習道路上的每一處風景。這兩天終於學會了操作LCD,底層自己編寫。下面是研究開發板的收穫,爲以後打下基礎。本文不具體講解LCD基礎知識,直接上實戰代碼。
        先上效果圖:1、畫斜線和圓;2、顯示字符(串);3、在顯存上顯示圖片。圖片後面貼出自己的所有400多行代碼,僅供學習者在編程LCD時參考。說明:畫斜線和圓的算法均爲移植。
        PS:由於博客會自動調整編程代碼格式,所以本文不具體細調代碼格式。

 S5PV210之LCD畫圖、字符串、顯示圖片編程實戰

S5PV210之LCD畫圖、字符串、顯示圖片編程實戰

S5PV210之LCD畫圖、字符串、顯示圖片編程實戰

/  ******************************************************************************** /
#include "main.h"
#include "ascii.h"     //字符取模後存的二進制位信息
#include "800480.h"//圖片取模後存的二進制位信息,利用Image2Lcd圖片取模軟件

#define GPF0CON         (*(volatile unsigned long *)0xE0200120)
#define GPF1CON         (*(volatile unsigned long *)0xE0200140)
#define GPF2CON         (*(volatile unsigned long *)0xE0200160)
#define GPF3CON         (*(volatile unsigned long *)0xE0200180)

#define GPD0CON        (*(volatile unsigned long *)0xE02000A0)
#define GPD0DAT         (*(volatile unsigned long *)0xE02000A4)

#define CLK_SRC1         (*(volatile unsigned long *)0xe0100204)
#define CLK_DIV1          (*(volatile unsigned long *)0xe0100304)
#define DISPLAY_CONTROL       (*(volatile unsigned long *)0xe0107008)

#define VIDCON0           (*(volatile unsigned long *)0xF8000000)
#define VIDCON1           (*(volatile unsigned long *)0xF8000004)
#define VIDTCON2         (*(volatile unsigned long *)0xF8000018)
#define WINCON0          (*(volatile unsigned long *)0xF8000020)
#define WINCON2          (*(volatile unsigned long *)0xF8000028)
#define SHADOWCON   (*(volatile unsigned long *)0xF8000034)
#define VIDOSD0A         (*(volatile unsigned long *)0xF8000040)
#define VIDOSD0B          (*(volatile unsigned long *)0xF8000044)
#define VIDOSD0C          (*(volatile unsigned long *)0xF8000048)

#define VIDW00ADD0B0    (*(volatile unsigned long *)0xF80000A0)
#define VIDW00ADD1B0    (*(volatile unsigned long *)0xF80000D0)

#define VIDTCON0              (*(volatile unsigned long *)0xF8000010)
#define VIDTCON1              (*(volatile unsigned long *)0xF8000014)

#define HSPW (40) // 1~40 DCLK
#define HBPD (10 - 1) // 46
#define HFPD (240 - 1) // 16 210 354
#define VSPW (20) // 1~20 DCLK
#define VBPD (10 - 1) // 23
#define VFPD (30 - 1) // 7 22 147

// FB地址
#define FB_ADDR (0x23000000)        //顯存地址設置,可爲0x25000000
#define ROW (480)
#define COL (800)
#define HOZVAL (COL-1)
#define LINeval_r(ROW-1)

#define XSIZE COL
#define YSIZE ROW

u32 *pfb = (u32 *)FB_ADDR;    //顯存地址與屏幕像素相綁定
// 常用顏色定義
#define BLUE 0x0000FF
#define RED 0xFF0000
#define GREEN 0x00FF00
#define WHITE 0xFFFFFF

#define LeftTopX     0
#define LeftTopY     0
#define RightBotX   799
#define RightBotY   479

// 初始化LCD
static void lcd_init(void)
{
// 配置引腳用於LCD功能
GPF0CON = 0x22222222;
GPF1CON = 0x22222222;
GPF2CON = 0x22222222;
GPF3CON = 0x22222222;

// 打開背光 GPD0_0(PWMTOUT0)
GPD0CON &= ~(0xf<<0);
GPD0CON |= (1<<0); // output mode
GPD0DAT &= ~(1<<0); // output 0 to enable backlight

// 10: RGB=FIMD I80=FIMD ITU=FIMD
DISPLAY_CONTROL = 2<<0;

// bit[26~28]:使用RGB接口
// bit[18]:RGB 並行
// bit[2]:選擇時鐘源爲HCLK_DSYS=166MHz
VIDCON0 &= ~( (3<<26)|(1<<18)|(1<<2) );

// bit[1]:使能lcd控制器
// bit[0]:當前幀結束後使能lcd控制器
VIDCON0 |= ( (1<<0)|(1<<1) );

// bit[6]:選擇需要分頻
// bit[6~13]:分頻係數爲5,即VCLK = 166M/(4+1) = 33M
VIDCON0 |= 4<<6 | 1<<4;


// H43-HSD043I9W1.pdf(p13) 時序圖:VSYNC和HSYNC都是低脈衝
// s5pv210芯片手冊(p1207) 時序圖:VSYNC和HSYNC都是高脈衝有效,所以需要反轉
VIDCON1 |= 1<<5 | 1<<6;

// 設置時序
VIDTCON0 = VBPD<<16 | VFPD<<8 | VSPW<<0;
VIDTCON1 = HBPD<<16 | HFPD<<8 | HSPW<<0;
// 設置長寬(物理屏幕)
VIDTCON2 = (LINEVAL << 11) | (HOZVAL << 0);

// 設置window0
// bit[0]:使能
// bit[2~5]:24bpp(RGB888)
WINCON0 |= 1<<0;
WINCON0 &= ~(0xf << 2);
WINCON0 |= (0xB<<2) | (1<<15);
// 設置window0的上下左右
// 設置的是顯存空間的大小
VIDOSD0A = (LeftTopX<<11) | (LeftTopY << 0);
VIDOSD0B = (RightBotX<<11) | (RightBotY << 0);
VIDOSD0C = (LINEVAL + 1) * (HOZVAL + 1);
// 設置fb的地址
VIDW00ADD0B0 = FB_ADDR;
VIDW00ADD1B0 = (((HOZVAL + 1)*4 + 0) * (LINEVAL + 1)) & (0xffffff);

// 使能channel 0傳輸數據
SHADOWCON = 0x1;
}

// 在像素點(x, y)處填充爲color顏色
static inline void lcd_draw_pixel(u32 x, u32 y, u32 color)
{
*(pfb + COL * y + x) = color;
}

// 把整個屏幕全部填充成一個顏色color
static void lcd_draw_background(u32 color)
{
u32 i, j;
for (j=0; j
{
for (i=0; i
{
lcd_draw_pixel(i, j, color);
}
}
}

static void delay(void)
{
volatile u32 i, j;
for (i=0; i<4000; i++)
for (j=0; j<1000; j++);
}

// 繪製橫線,起始座標爲(x1, y)到(x2, y),顏色是color
static void lcd_draw_hline(u32 x1, u32 x2, u32 y, u32 color)
{
u32 x;
for (x = x1; x
{
lcd_draw_pixel(x, y, color);
}
}

// 繪製豎線,起始座標爲(x, y1)到(x, y2),顏色是color
static void lcd_draw_vline(u32 x, u32 y1, u32 y2, u32 color)
{
u32 y;
for (y = y1; y
{
lcd_draw_pixel(x, y, color);
}
}

// glib庫中的畫線函數,可以畫斜線,線兩端分別是(x1, y1)和(x2, y2)
void glib_line(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2, unsigned int color)
{
int dx,dy,e;
dx=x2-x1; 
dy=y2-y1;
    
if(dx>=0)
{
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 1/8 octant
{
e=dy-dx/2;  
while(x1<=x2)
{
lcd_draw_pixel(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else // 2/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
lcd_draw_pixel(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else   // dy<0
{
dy=-dy;   // dy=abs(dy)

if(dx>=dy) // 8/8 octant
{
e=dy-dx/2;
while(x1<=x2)
{
lcd_draw_pixel(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else // 7/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
lcd_draw_pixel(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
else //dx<0
{
dx=-dx; //dx=abs(dx)
if(dy >= 0) // dy>=0
{
if(dx>=dy) // 4/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
lcd_draw_pixel(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else // 3/8 octant
{
e=dx-dy/2;
while(y1<=y2)
{
lcd_draw_pixel(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else   // dy<0
{
dy=-dy;   // dy=abs(dy)

if(dx>=dy) // 5/8 octant
{
e=dy-dx/2;
while(x1>=x2)
{
lcd_draw_pixel(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else // 6/8 octant
{
e=dx-dy/2;
while(y1>=y2)
{
lcd_draw_pixel(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
}

//畫圓函數,圓心座標是(centerX, centerY),半徑是radius,圓的顏色是color
void draw_circular(unsigned int centerX, unsigned int centerY, unsigned int radius, unsigned int color)
{
int x,y ;
int tempX,tempY;;
    int SquareOfR = radius*radius;

for(y=0; y
{
for(x=0; x
{
if(y<=centerY && x<=centerX)
{
tempY=centerY-y;
tempX=centerX-x;                        
}
else if(y<=centerY&& x>=centerX)
{
tempY=centerY-y;
tempX=x-centerX;                        
}
else if(y>=centerY&& x<=centerX)
{
tempY=y-centerY;
tempX=centerX-x;                        
}
else
{
tempY = y-centerY;
tempX = x-centerX;
}
if ((tempY*tempY+tempX*tempX)<=SquareOfR)
lcd_draw_pixel(x, y, color);
}
}
}

// 寫字
// 寫字的左上角座標(x, y),字的顏色是color,字的字模信息存儲在data中
static void show_8_16(unsigned int x, unsigned int y, unsigned int color, unsigned char *data)  
{  
// count記錄當前正在繪製的像素的次序
    int i, j, count = 0;  
 
    for (j=y; j<(y+16); j++)  
    {  
        for (i=x; i<(x+8); i++)  
        {  
            if (i
            {  
        // 在座標(i, j)這個像素處判斷是0還是1,如果是1寫color;如果是0直接跳過
            if (data[count/8] & (1<<(count%8)))   
                 lcd_draw_pixel(i, j, color);
            }  
            count++;  
        }  
    }  

// 寫字符串
// 字符串起始座標左上角爲(x, y),字符串文字顏色是color,字符串內容爲str
void draw_ascii_ok(unsigned int x, unsigned int y, unsigned int color, unsigned char *str)
{
int i;  
unsigned char *ch;
       for (i=0; str[i]!='\0'; i++)  
      {  
         ch = (unsigned char *)ascii_8_16[(unsigned char)str[i]-0x20];
         show_8_16(x, y, color, ch); 
         x += 8;
         if (x >= XSIZE) //判斷是否超出屏幕範圍
           {
                 x -= XSIZE; // 回車
                 y += 16; // 換行
            }
      }  
}

//畫圖片,圖像數據存在指針指向的數組裏面
void lcd_draw_picture(const unsigned char *pData)
{
u32 x,y,color,p=0;
for (y=0;y<480;y++)
{
for(x=0;x<800;x++)
{
color= (pData[p+2]<<0)|(pData[p+1]<<8)|(pData[p+0]<<16);
lcd_draw_pixel(x,y,color);
p+=3;
}
}
}

void lcd_test(void)
{
lcd_init();
//顯示圖片
lcd_draw_picture(gImage_800480);
/ *
//測試寫英文字母
lcd_draw_background(WHITE);
draw_ascii_ok(0, 0, RED, "ABCDabcd1234!@#$%");
* /
/ *
// 測試畫斜線
lcd_draw_background(WHITE); // 如果沒有加這一行,背景色是花花綠綠的
glib_line(0, 479, 799, 0, RED);
draw_circular(399, 239, 50, GREEN);
*/
/ *
// 測試畫橫線、豎線
lcd_draw_background(WHITE);
lcd_draw_hline(350, 450, 240, RED);
lcd_draw_vline(400, 190, 290, GREEN);
* /

/ *
// 測試繪製背景色,成功
while (1)
{
lcd_draw_background(RED);
delay();
lcd_draw_background(GREEN);
delay();
lcd_draw_background(BLUE);
delay();
}
* /
}

/ ******************************************************************** /
//建立main.c文件,調用上面的功能函數
#include "main.h"
int main(void)
{
lcd_test();
return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章