要在ARM上实现LCD绘图,可以按照以下步骤进行:
硬件初始化:初始化LCD控制器和相关引脚,配置时钟、分辨率和颜色深度等。
内存映射:将LCD显示区域映射到ARM的内存地址空间中,可以通过ARM的内存映射机制来实现。
绘图函数:实现绘制基本图形的函数,如点、线、矩形、圆等。可以通过计算像素坐标和调用ARM的内存写入指令来实现。
图像显示:通过调用绘图函数绘制图像,然后将图像数据写入映射的内存地址中,刷新LCD控制器以显示图像。
不同的LCD控制器和ARM芯片可能会有一些细节上的差异,因此具体的实现步骤可能会有所不同。此外,还可以结合相关的图形库或操作系统提供的绘图函数来简化开发过程。
这里采用的是手动绘制+内存映射。
空心圆:
int draw_circle(int color, int x, int y, int r)
{
int a, b, num;
a = 0;
b = r;
//1.打开液晶屏
int fd_lcd;
fd_lcd = open("/dev/fb0", O_RDWR);
if(fd_lcd == -1 )
{
perror("open lcd "); //perror()会根据错误码返回出错的原因
return -1;
}
printf("fd_lcd = %d\n", fd_lcd);
//2. 显存映射,在应用程序中得到显存的首地址
int *lcd_base=NULL; //int---每个像素点占用内存是4B
lcd_base = (int *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED,
fd_lcd, 0);
if(lcd_base == NULL)
return -2;
3.通过显存的首地址,将颜色数据写入显存
while(2 * b * b >= r * r) // 1/8圆即可
{
draw_point(x + a, y - b,color,lcd_base); // 0~1
draw_point(x - a, y - b,color,lcd_base); // 0~7
draw_point(x - a, y + b,color,lcd_base); // 4~5
draw_point(x + a, y + b,color,lcd_base); // 4~3
draw_point(x + b, y + a,color,lcd_base); // 2~3
draw_point(x + b, y - a,color,lcd_base); // 2~1
draw_point(x - b, y - a,color,lcd_base); // 6~7
draw_point(x - b, y + a,color,lcd_base); // 6~5
a++;
num = (a * a + b * b) - r*r;
if(num > 0)
{
b--;
a--;
}
}
//4.解除显存映射
munmap(lcd_base, 800*480*4);
//5.关闭液晶屏
close(fd_lcd);
return 0;
}
实心圆
int draw_circle(int color, int Xpos, int Ypos, int Radius)
{
//1.打开液晶屏
int fd_lcd;
fd_lcd = open("/dev/fb0", O_RDWR);
if(fd_lcd == -1 )
{
perror("open lcd "); //perror()会根据错误码返回出错的原因
return -1;
}
printf("fd_lcd = %d\n", fd_lcd);
//2. 显存映射,在应用程序中得到显存的首地址
int *lcd_base=NULL; //int---每个像素点占用内存是4B
lcd_base = (int *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED,
fd_lcd, 0);
if(lcd_base == NULL)
return -2;
int x,y,r=Radius;
for(y=Ypos - r;y<Ypos +r;y++)
{
for(x=Xpos - r;x<Xpos+r;x++)
{
if(((x-Xpos)*(x-Xpos)+(y-Ypos)*(y-Ypos)) <= r*r)
{
draw_point(x, y,color,lcd_base);
}
}
}
//4.解除显存映射
munmap(lcd_base, 800*480*4);
//5.关闭液晶屏
close(fd_lcd);
return 0;
}
任意区域矩形
int lcd_color(int color, int sx, int sy, int ex, int ey)
{
//1.打开液晶屏
int fd_lcd;
fd_lcd = open("/dev/fb0", O_RDWR);
if(fd_lcd == -1 )
{
perror("open lcd "); //perror()会根据错误码返回出错的原因
return -1;
}
printf("fd_lcd =%d\n", fd_lcd);
//2. 显存映射,在应用程序中得到显存的首地址
int *lcd_base=NULL; //int---每个像素点占用内存是4B
lcd_base = (int *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED,
fd_lcd, 0);
if(lcd_base == NULL)
return -2;
//3.通过显存的首地址,将颜色数据写入显存
for(int y=sy;y<ey; y++)
for(int x=sx;x<ex;x++)
*(lcd_base + 800*y+x) = color;
//4.解除显存映射
munmap(lcd_base, 800*480*4);
//5.关闭液晶屏
close(fd_lcd);
return 0;
}
三角形
int triangle(int x1,int y1,int x2,int y2,int x3,int y3,int col)
{
//1.打开液晶屏
int fd_lcd;
fd_lcd = open("/dev/fb0", O_RDWR);
if(fd_lcd == -1 )
{
perror("open lcd "); //perror()会根据错误码返回出错的原因
return -1;
}
printf("fd_lcd =%d\n", fd_lcd);
//2. 显存映射,在应用程序中得到显存的首地址
int *lcd_base=NULL; //int---每个像素点占用内存是4B
lcd_base = (int *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED,
fd_lcd, 0);
if(lcd_base == NULL)
return -2;
//flag:代表本三角形在本直线的左边(0)还是右边(1)(左边右边是抽象概念)
int i,j,flag1=0,flag2=0,flag3=0;
float A1,B1,C1,A2,B2,C2,A3,B3,C3;
//1号点与2号点的直线方程的A,B,C
A1 = y2 - y1;
B1 = x1 - x2;
C1 = x2*y1 - x1*y2;
//2号点与3号点的直线方程的A,B,C
A2 = y2 - y3;
B2 = x3 - x2;
C2 = x2*y3 - x3*y2;
//1号点与3号点的直线方程的A,B,C
A3 = y3 - y1;
B3 = x1 - x3;
C3 = x3*y1 - x1*y3;
//判断第三个点与直线的相对位置
if(x3*A1+y3*B1+C1 > 0) flag1=1;
if(x1*A2+y1*B2+C2 > 0) flag2=1;
if(x2*A3+y2*B3+C3 > 0) flag3=1;
for(i=0;i<480;i++){
for(j=0;j<800;j++){
if(flag1 == 1){
if(flag2 == 1){
if(j*A1+i*B1+C1 > 0 && j*A2+i*B2+C2 > 0 && j*A3+i*B3+C3 < 0)
{
draw_point(j,i,col,lcd_base);
}
}
else{
if(flag3 == 1){
if(j*A1+i*B1+C1 > 0 && j*A2+i*B2+C2 < 0 && j*A3+i*B3+C3 > 0)
{
draw_point(j,i,col,lcd_base);
}
}
else{
if(j*A1+i*B1+C1 > 0 && j*A2+i*B2+C2 < 0 && j*A3+i*B3+C3 < 0)
{
draw_point(j,i,col,lcd_base);
}
}
}
}
else{
if(flag2 == 0){
if(j*A1+i*B1+C1 < 0 && j*A2+i*B2+C2 < 0 && j*A3+i*B3+C3 > 0)
{
draw_point(j,i,col,lcd_base);
}
}
else{
if(flag3 == 1){
if(j*A1+i*B1+C1 < 0 && j*A2+i*B2+C2 > 0 && j*A3+i*B3+C3 > 0)
{
draw_point(j,i,col,lcd_base);
}
}
else{
if(j*A1+i*B1+C1 < 0 && j*A2+i*B2+C2 > 0 && j*A3+i*B3+C3 < 0)
{
draw_point(j,i,col,lcd_base);
}
}
}
}
}
}
//4.解除显存映射
munmap(lcd_base, 800*480*4);
//5.关闭液晶屏
close(fd_lcd);
return 0;
}
五角星
void five_Pointed(int x,int y,int R,unsigned int col,int yDegree)
{
struct Vertex
{
int x;
int y;
};
struct Vertex RVertex[5], rVertex[5]; //外围5个顶点的坐标与内部五个顶点的坐标
double rad = 3.1415926 / 180; //每度的弧度值
double r = R * sin(18 * rad) / cos(36 * rad); //五角星短轴的长度
for (int k = 0; k < 5; k++) //求取坐标
{
RVertex[k].x = (int)(x - (R * cos((90 + k * 72 + yDegree) *rad)));
RVertex[k].y = (int)(y - (R * sin((90 + k * 72 + yDegree) * rad)));
rVertex[k].x = (int)(x - (r * cos((90 + 36 + k * 72 + yDegree) *rad)));
rVertex[k].y = (int)(y - (r * sin((90 + 36 + k * 72 + yDegree) * rad)));
}
triangle(RVertex[1].x,RVertex[1].y,RVertex[3].x,RVertex[3].y,rVertex[4].x,rVertex[4].y,col);
triangle(RVertex[2].x,RVertex[2].y,RVertex[4].x,RVertex[4].y,rVertex[0].x,rVertex[0].y,col);
triangle(RVertex[3].x,RVertex[3].y,RVertex[0].x,RVertex[0].y,rVertex[1].x,rVertex[1].y,col);
}
各国旗帜
int lcd_flag(COUNTRY countryname)
{
//1.打开液晶屏
int fd_lcd;
fd_lcd = open("/dev/fb0", O_RDWR);
if(fd_lcd == -1 )
{
perror("open lcd "); //perror()会根据错误码返回出错的原因
return -1;
}
printf("fd_lcd =%d\n", fd_lcd);
//2. 显存映射,在应用程序中得到显存的首地址
int *lcd_base=NULL; //int---每个像素点占用内存是4B
lcd_base = (int *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED,
fd_lcd, 0);
if(lcd_base == NULL)
return -2;
switch(countryname)
{
case GERMANY:
lcd_color(BLACK, 0, 0, 800, 160);
lcd_color(RED, 0, 160, 800, 320);
lcd_color(YELLOW, 0, 320,800, 480);
break;
case FRANCE:
lcd_color(BLUE, 0, 0, 240, 480);
lcd_color(WHITE, 240, 0, 560, 480);
lcd_color(RED, 560, 0, 800, 480);
break;
case ITALI:
lcd_color(GREEN, 0, 0, 240, 480);
lcd_color(WHITE, 240, 0, 560, 480);
lcd_color(RED, 560, 0, 800, 480);
break;
case SWISS:
lcd_color(RED,0,0,800,480);
lcd_color(WHITE,240,160,480,240);
lcd_color(WHITE,320,80,400,320);
break;
case JAPAN:
lcd_color(WHITE,0,0,800,480);
draw_circle(RED,400,240,80);
break;
case CHINA:
lcd_color(RED,0,0,800,480);
five_Pointed(110,150,70,YELLOW,0);
five_Pointed(200,60,40,YELLOW,20);
five_Pointed(270,130,40,YELLOW,40);
five_Pointed(270,230,40,YELLOW,0);
five_Pointed(200,290,40,YELLOW,40);
break;
default:break;
}
//4.解除显存映射
munmap(lcd_base, 800*480*4);
//5.关闭液晶屏
close(fd_lcd);
return 0;
}
main.c
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> // 包含 close 函数所需的头文件
#include "lcd.h"
int main(void)
{
unsigned char state=0;
while (1)
{
switch (state)
{
case 0:
lcd_color(RED,0,0,800,480);
break;
case 1:
lcd_color(GREEN,0,0,800,480);
break;
case 2:
lcd_color(BLUE,0,0,800,480);
break;
case 3:
lcd_color(YELLOW,0,0,800,480);
break;
case 4:
lcd_color(PURPLE,0,0,800,480);
break;
case 5:
lcd_color(BLACK,0,0,800,480);
break;
case 6:
lcd_color(WHITE,0,0,800,480);
break;
case 7:
lcd_flag(FRANCE);
break;
case 8:
lcd_flag(GERMANY);
break;
case 9:
lcd_flag(ITALI);
break;
case 10:
lcd_flag(SWISS);
break;
case 11:
lcd_flag(JAPAN);
break;
case 12:
lcd_flag(CHINA);
break;
default:
break;
}
if(++state>12)
{state=0;}
sleep(3);
}
// lcd_flag(GERMANY);
return 0;
}
lcd.h
#define RED 0x00FF0000
#define GREEN 0x0000FF00
#define YELLOW 0x00FFFF00
#define BLUE 0x000000FF
#define BLACK 0x00000000
#define WHITE 0x00FFFFFF
#define PURPLE 0x00800080
typedef enum {
GERMANY,
FRANCE,
ITALI,
SWISS,
JAPAN,
CHINA
} COUNTRY;
int lcd_color(int color, int sx, int sy, int ex, int ey);
int lcd_flag(COUNTRY countryname);