编写程序
一、框架讲解
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200517005319933.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
- 第一层:测试菜单层:
lcd_test.c
- 第二层:根据目的划分三个C文件:
framebuffer.c
、geometry.c
、font.c
- 第三层:LCD参数设置:
lcd.c
,考虑到拓展性,如果需要用到不同尺寸的lcd时,需要修改太多东西,所以在这一层下分了一个小层,用来放各种尺寸lcd的参数设置文件如lcd_4_3.c
,通过在lcd.c
调用对应的文件。 - 第四层:LCD控制器设置:
lcd_controller.c
,考虑到拓展性,如果用到不同芯片驱动的lcd时,需要修改太多东西,所以在这一层下分了一个小层,用来放各种芯片的lcd控制器设置文件如s3c2440_lcd_controller.c
,通过在lcd_controller.c
调用对应的文件。
二、设置文件编写
1、lcd.c文件编写
#include "lcd.h"
#include "lcd_controller.h"
#define LCD_NUM 10
static p_lcd_params p_array_lcd[LCD_NUM];
static p_lcd_params p_g_selected_lcd;
int register_lcd(p_lcd_params plcd)
{
int i;
for (i = 0; i < LCD_NUM; i++){
if(!p_array_lcd[i]){
p_array_lcd[i] = plcd;
return i;
}
}
return -1;
}
int select_lcd(char *name)
{
int i;
for (i = 0; i < LCD_NUM; i++){
if ((p_array_lcd[i]) && !(strcmp(p_array_lcd[i]->name, name))){
p_g_selected_lcd = p_array_lcd[i];
return i;
}
}
return -1;
}
void get_lcd_params(unsigned int *fb_base, int *xres, int *yres, int *bpp)
{
*fb_base = p_g_selected_lcd->frm_base;
*xres = p_g_selected_lcd->xres;
*yres = p_g_selected_lcd->yres;
*bpp = p_g_selected_lcd->bpp;
}
void lcd_enable(void)
{
lcd_controller_enable();
}
void lcd_disable(void)
{
lcd_controller_disable();
}
int lcd_init(void)
{
lcd_4_3_add();
lcd_controller_add();
select_lcd("lcd_4.3");
select_lcd_controller("s3c2440_lcdcon");
lcd_controller_init(p_g_selected_lcd);
}
2、lcd_4_3.c文件编写
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200514172147310.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
#include "lcd.h"
#define LCD_FB_BASE 0x33c00000
lcd_params lcd_4_3_params = {
.name = "lcd_4.3",
.pin_pol = {
.clk = NORMAL,
.hsync = INVERT,
.vsync = INVERT,
.rgb = NORMAL,
.de = NORMAL,
.pwren = NORMAL,
},
.time_seq = {
.thp = 41,
.thb = 2,
.thf = 2,
.tvp = 10,
.tvb = 2,
.tvf = 2,
.vclk= 9,
},
.xres = 480,
.yres = 272,
.bpp = 8,
.frm_base = LCD_FB_BASE,
};
void lcd_4_3_add(void)
{
register_lcd(&lcd_4_3_params);
}
3、lcd_controller.c文件编写
#include "lcd_controller.h"
#define LCD_CONTROLLER_NUM 10
static p_lcd_controller p_array_lcd_controller[LCD_CONTROLLER_NUM];
static p_lcd_controller p_g_selected_lcd_controller;
int register_lcd_controller(p_lcd_controller plcdcon)
{
int i;
for (i = 0; i < LCD_CONTROLLER_NUM; i++){
if(!p_array_lcd_controller[i]){
p_array_lcd_controller[i] = plcdcon;
return i;
}
}
return -1;
}
int select_lcd_controller(char *name)
{
int i;
for (i = 0; i < LCD_CONTROLLER_NUM; i++){
if((p_array_lcd_controller[i]) && !(strcmp(p_array_lcd_controller[i]->name, name))){
p_g_selected_lcd_controller = p_array_lcd_controller[i];
return i;
}
}
return -1;
}
void lcd_controller_add(void)
{
s3c2440_lcd_controller_add();
}
int lcd_controller_init(p_lcd_params plcdparams)
{
if (p_g_selected_lcd_controller){
p_g_selected_lcd_controller->init(plcdparams);
p_g_selected_lcd_controller->init_palette();
return 0;
}
return -1;
}
void lcd_controller_enable(void)
{
if (p_g_selected_lcd_controller)
p_g_selected_lcd_controller->enable();
}
void lcd_controller_disable(void)
{
if (p_g_selected_lcd_controller)
p_g_selected_lcd_controller->disable();
}
4、s3c2440_lcd_controller.c文件编写
4.1 寄存器配置
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200513003128621.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
int CLKVAL = (double)VCLK/HCLK/2-1 + 0.5;
int BPP = plcparams->bpp == 8 ? 0xb :\
plcparams->bpp == 16 ? 0xc : 0xd;
LCDCON1 = (CLKVAL<<8) | (0x3<<5) | (BPP<<1);
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200513003304612.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
LCDCON2 = ((plcparams->time_seq.tvb - 1)<<24) | \
((plcparams->yres - 1)<<14) | \
((plcparams->time_seq.tvf - 1)<<6) | \
((plcparams->time_seq.tvp - 1)<<0);、
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200513003935994.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
LCDCON3 = ((plcparams->time_seq.thb - 1)<<19) | \
((plcparams->xres - 1)<<8) | \
((plcparams->time_seq.thf - 1)<<0);
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200513004411907.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
LCDCON4 = ((plcparams->time_seq.thp - 1)<<0);
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200514164923964.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
pixeplace = plcparams->bpp == 24 ? (0) : |\
plcparams->bpp == 18 ? (1) : |\
(1<<1);
LCDCON5 = (plcparams->pin_pol.clk << 10) |\
(plcparams->pin_pol.hsync << 9) |\
(plcparams->pin_pol.vsync << 8) |\
(plcparams->pin_pol.rgb << 7) |\
(plcparams->pin_pol.de << 6) |\
(plcparams->pin_pol.pwren << 5) |\
(1<<11) | pixeplace;
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200514161738468.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
addr = plcparams->frm_base + plcparams->xres * plcparams->yres * plcparams->bpp;
addr >>=1;
addr &=0x1fffff;
LCDSADDR2 = addr;
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200514161841238.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjgxMzIzMg==,size_16,color_FFFFFF,t_70)
addr = plcparams->frm_base & ~(1<<31);
LCDSADDR1 = (addr >> 1);
4.2 完整代码
#include "lcd.h"
#include "lcd_controller.h"
#include "../s3c2440_soc.h"
#define HCLK 100
void jz2440_lcd_pin_init(void)
{
GPBCON &= ~0x3;
GPBCON |= 0x01;
GPCCON = 0xaaaaaaaa;
GPDCON = 0xaaaaaaaa;
GPGCON |= (3<<8);
}
void s3c2440_lcd_controller_init(p_lcd_params plcparams)
{
int pixeplace;
unsigned int addr;
jz2440_lcd_pin_init();
int CLKVAL = (float)HCLK/plcparams->time_seq.vclk/2-1+0.5;
int BPP = plcparams->bpp == 8 ? 0xb :\
plcparams->bpp == 16 ? 0xc :\
0xd;
LCDCON1 = (CLKVAL << 8) | (3 << 5) | (BPP << 1);
LCDCON2 = ((plcparams->time_seq.tvb - 1) << 24) |\
((plcparams->yres - 1) << 14) |\
((plcparams->time_seq.tvf - 1) << 6) |\
((plcparams->time_seq.tvp - 1) << 0);
LCDCON3 = ((plcparams->time_seq.thb - 1) << 19) |\
((plcparams->xres - 1) << 8) |\
((plcparams->time_seq.thf - 1) << 0);
LCDCON4 = ((plcparams->time_seq.thp - 1)<<0);
pixeplace = plcparams->bpp == 32 ? (0) : \
plcparams->bpp == 16 ? (1) : \
(1<<1);
LCDCON5 = (plcparams->pin_pol.clk << 10) |\
(plcparams->pin_pol.hsync << 9) |\
(plcparams->pin_pol.vsync << 8) |\
(plcparams->pin_pol.rgb << 7) |\
(plcparams->pin_pol.de << 6) |\
(plcparams->pin_pol.pwren << 5) |\
(1<<11) | pixeplace;
addr = plcparams->frm_base & ~(1<<31);
LCDSADDR1 = (addr >> 1);
addr = plcparams->frm_base + plcparams->xres * plcparams->yres * plcparams->bpp/8;
addr >>=1;
addr &=0x1fffff;
LCDSADDR2 = addr;
}
void s3c2440_lcd_controller_enable(void)
{
GPBDAT |= (1<<0);
LCDCON5 |= (1<<3);
LCDCON1 |= (1<<0);
}
void s3c2440_lcd_controller_disable(void)
{
GPBDAT &= ~(1<<0);
LCDCON5 &= ~(1<<3);
LCDCON1 &= ~(1<<0);
}
void s3c2440_lcd_controller_init_palette(void)
{
volatile unsigned int *palette_base = (volatile unsigned int *)0x4D000400;
int i;
int bit = LCDCON1 & (1<<0);
if (bit)
LCDCON1 &= ~(1<<0);
for (i = 0; i < 256; i++)
{
*palette_base++ = i;
}
if (bit)
LCDCON1 |= (1<<0);
}
struct lcd_controller s3c2440_lcd_controller = {
.name = "s3c2440_lcdcon",
.init = s3c2440_lcd_controller_init,
.enable = s3c2440_lcd_controller_enable,
.disable = s3c2440_lcd_controller_disable,
.init_palette = s3c2440_lcd_controller_init_palette,
};
void s3c2440_lcd_controller_add(void)
{
register_lcd_controller(&s3c2440_lcd_controller);
}
三、目的函数编写
1、画点framebuffer.c文件编写
#include "lcd.h"
#include "framebuffer.h"
static unsigned int fb_base;
static int xres, yres, bpp;
void fb_get_lcd_params(void)
{
get_lcd_params(&fb_base, &xres, &yres, &bpp);
}
unsigned short convert32bppto16bpp(unsigned int rgb)
{
int r = (rgb>>16) & 0xff;
int g = (rgb>>8) & 0xff;
int b = rgb & 0xff;
r = r >> 3;
g = g >> 2;
b = b >> 3;
return ((r<<11) | (g<<5) | b);
}
void draw_piont(int x, int y, unsigned int color)
{
unsigned char *pc;
unsigned short *pw;
unsigned int *pdw;
unsigned int pixel_base = fb_base + (xres * bpp / 8) * y + (x * bpp / 8);
switch (bpp)
{
case 8:
pc = (unsigned char *)pixel_base;
*pc = color;
break;
case 16:
pw = (unsigned short *)pixel_base;
*pw = convert32bppto16bpp(color);
break;
case 32:
pdw = (unsigned int *)pixel_base;
*pdw = color;
break;
}
}
2、画线、圈geometry.c文件编写
#include "framebuffer.h"
#include "geometry.h"
void draw_circle(int x, int y, int r, int color)
{
int a, b, num;
a = 0;
b = r;
while(22 * b * b >= r * r)
{
draw_piont(x + a, y - b,color);
draw_piont(x - a, y - b,color);
draw_piont(x - a, y + b,color);
draw_piont(x + a, y + b,color);
draw_piont(x + b, y + a,color);
draw_piont(x + b, y - a,color);
draw_piont(x - b, y - a,color);
draw_piont(x - b, y + a,color);
a++;
num = (a * a + b * b) - r*r;
if(num > 0)
{
b--;
a--;
}
}
}
void draw_line(int x1,int y1,int x2,int y2,int color)
{
int dx,dy,e;
dx=x2-x1;
dy=y2-y1;
if(dx>=0)
{
if(dy >= 0)
{
if(dx>=dy)
{
e=dy-dx/2;
while(x1<=x2)
{
draw_piont(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else
{
e=dx-dy/2;
while(y1<=y2)
{
draw_piont(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else
{
dy=-dy;
if(dx>=dy)
{
e=dy-dx/2;
while(x1<=x2)
{
draw_piont(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1+=1;
e+=dy;
}
}
else
{
e=dx-dy/2;
while(y1>=y2)
{
draw_piont(x1,y1,color);
if(e>0){x1+=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
else
{
dx=-dx;
if(dy >= 0)
{
if(dx>=dy)
{
e=dy-dx/2;
while(x1>=x2)
{
draw_piont(x1,y1,color);
if(e>0){y1+=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else
{
e=dx-dy/2;
while(y1<=y2)
{
draw_piont(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1+=1;
e+=dx;
}
}
}
else
{
dy=-dy;
if(dx>=dy)
{
e=dy-dx/2;
while(x1>=x2)
{
draw_piont(x1,y1,color);
if(e>0){y1-=1;e-=dx;}
x1-=1;
e+=dy;
}
}
else
{
e=dx-dy/2;
while(y1>=y2)
{
draw_piont(x1,y1,color);
if(e>0){x1-=1;e-=dy;}
y1-=1;
e+=dx;
}
}
}
}
}
3、写字font.c文件编写
#include "font.h"
#include "framebuffer.h"
extern const unsigned char fontdata_8x16[];
static unsigned int fb_base;
static int xres, yres, bpp;
void font_init(void)
{
get_lcd_params(&fb_base, &xres, &yres, &bpp);
}
void fb_print_char(int x, int y, char c, unsigned int color)
{
int i, j;
unsigned char *dots = &fontdata_8x16[c * 16];
unsigned char data;
int bit;
for (j = y; j < y+16; j++){
data = *dots++;
bit = 7;
for (i = x; i < x+8; i++){
if (data & (1 << bit))
draw_piont(i, j, color);
bit--;
}
}
}
void fb_print_string(int x, int y, char *str, unsigned int color)
{
int i, j;
i = 0;
while (str[i]){
if (str[i] == '\n')
y = y + 16;
else if (str[i] == '\r')
x = 0;
else{
fb_print_char(x, y, str[i], color);
x = x + 8;
if (x >= xres){
x = 0;
y = y + 16;
}
}
i++;
}
}
四、测试函数编写
#include "geometry.h"
#include "font.h"
void lcd_test(void)
{
unsigned int fb_base;
int xres;
int yres;
int bpp;
int x, y;
unsigned short *p;
unsigned int *p2;
unsigned char *p0;
lcd_init();
lcd_enable();
get_lcd_params(&fb_base, &xres, &yres, &bpp);
fb_get_lcd_params();
font_init();
if (bpp == 8){
p0 = (unsigned char *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p0++ = 12;
p0 = (unsigned char *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p0++ = 47;
p0 = (unsigned char *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p0++ = 88;
p0 = (unsigned char *)fb_base;
for (x = 0; x < xres; x++)
for (y = 0; y < yres; y++)
*p0++ = 0;
}
else if (bpp == 16){
p = (unsigned short *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p++ = 0xf800;
p = (unsigned short *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p++ = 0x7e0;
p = (unsigned short *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p++ = 0x1f;
p = (unsigned short *)fb_base;
for (x = 0; x < xres; x++)
for (y = 0; y < yres; y++)
*p++ = 0;
}
else if (bpp == 32){
p2 = (unsigned int *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p2++ = 0xff0000;
p2 = (unsigned int *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p2++ = 0x00ff00;
p2 = (unsigned int *)fb_base;
for (x = 0; x < xres ; x++)
for (y = 0; y < yres; y++)
*p2++ = 0x0000ff;
p2 = (unsigned int *)fb_base;
for (x = 0; x < xres; x++)
for (y = 0; y < yres; y++)
*p2++ = 0;
}
draw_line(0, 0, xres - 1, 0, 0xff11);
draw_line(xres - 1, 0, xres - 1, yres - 1, 0xffff);
draw_line(0, yres - 1, xres - 1, yres - 1, 0xff00);
draw_line(0, 0, 0, yres - 1, 0xff00ef);
draw_line(0, 0, xres - 1, yres - 1, 0xff45);
draw_line(xres - 1, 0, 0, yres - 1, 0xff07);
draw_circle(xres/2, yres/2, yres/4, 0xff);
fb_print_string(10, 10, "www.100ask.net\n\r100ask.taobao.com", 0xff);
}