对STM32F407的OV2640的(LCD)进行显示操作的学习
(注:此操作函数的使用必须全部基于OV2640的源代码上进行)
一、在LCD上显示自己想要显示的
1、(在指定位置显示一个字符)使用函数:
LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode);
(1)x,y:起始坐标;
(2)num:要显示的字符;
(3)size:字体大小 12/16/24;
(4)mode:叠加方式(1)还是非叠加方式(0);
(5)函数源代码:
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
{
u8 temp,t1,t;
u16 y0=y;
u8 csize=(size/8+((size%8)?1:0))*(size/2); //得到字体一个字符对应点阵集所占的字节数
num=num-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
for(t=0;t<csize;t++)
{
if(size==12)temp=asc2_1206[num][t]; //调用1206 字体
else if(size==16)temp=asc2_1608[num][t]; //调用1608字体
else if(size==24)temp=asc2_2412[num][t]; //调用2412字体
else return; //没有的字库
for(t1=0;t1<8;t1++)
{
if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR);
else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR);
temp<<=1;
y++;
if(y>=lcddev.height)return; //超区域了
if((y-y0)==size)
{
y=y0;
x++;
if(x>=lcddev.width)return; //超区域了
break;
}
}
}
}
2、(在指定位置显示一个数字(高位为0,还是显示))使用函数:
LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode);
(1)x,y:起点坐标
(2)num:要显示的数值(0~999999999);
(3)len:长度(即想要显示的位数)
(4)size:字体大小 12/16/24
(5)mode:
[7]:0,不填充;1,填充0;
[6:1]:保留;
[0]:0,非叠加显示;1,叠加显示
(6)源代码
void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)
{
u8 t,temp;
u8 enshow=0;
for(t=0;t<len;t++)
{
temp=(num/LCD_Pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
if(mode&0X80)LCD_ShowChar(x+(size/2)*t,y,'0',size,mode&0X01);
else LCD_ShowChar(x+(size/2)*t,y,' ',size,mode&0X01);
continue;
}else enshow=1;
}
LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,mode&0X01);
}
}
3、(在指定位置显示一个字符串)使用函数:
LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p);
eg:LCD_ShowString(130,130,200,16,16,“xxxxxxxx”);
(1)x,y:起点坐标;
(2)width,height:区域大小
(3)size:字体大小
(4)*p:字符串起始地址
(5)源代码:
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)
{
u8 x0=x;
width+=x;
height+=y;
while((*p<='~')&&(*p>=' '))//判断是不是非法字符
{
if(x>=width){x=x0;y+=size;}
if(y>=height)break;//退出
LCD_ShowChar(x,y,*p,size,0);
x+=size/2;
p++;
}
}
4、(想要清屏)使用函数:
LCD_Clear(u16 color);
(1)color:要清屏的填充色;
(2)源代码:
void LCD_Clear(u16 color)
{
u32 index=0;
u32 totalpoint=lcddev.width;
totalpoint*=lcddev.height; //得到总点数
if((lcddev.id==0X6804)&&(lcddev.dir==1))//6804横屏的时候特殊处理
{
lcddev.dir=0;
lcddev.setxcmd=0X2A;
lcddev.setycmd=0X2B;
LCD_SetCursor(0x00,0x0000); //设置光标位置
lcddev.dir=1;
lcddev.setxcmd=0X2B;
lcddev.setycmd=0X2A;
}else LCD_SetCursor(0x00,0x0000); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
for(index=0;index<totalpoint;index++)
{
LCD->LCD_RAM=color;
}
}
5、(在指定区域内显示(填充)单个颜色)使用函数:
LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color);
(1)(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为(ex-sx+1)*(ey-sy+1);
(2)color:要填充的颜色
(3)源代码:
void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
{
u16 i,j;
u16 xlen=0;
u16 temp;
if((lcddev.id==0X6804)&&(lcddev.dir==1)) //6804横屏的时候特殊处理
{
temp=sx;
sx=sy;
sy=lcddev.width-ex-1;
ex=ey;
ey=lcddev.width-temp-1;
lcddev.dir=0;
lcddev.setxcmd=0X2A;
lcddev.setycmd=0X2B;
LCD_Fill(sx,sy,ex,ey,color);
lcddev.dir=1;
lcddev.setxcmd=0X2B;
lcddev.setycmd=0X2A;
}else
{
xlen=ex-sx+1;
for(i=sy;i<=ey;i++)
{
LCD_SetCursor(sx,i); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
for(j=0;j<xlen;j++)LCD->LCD_RAM=color; //显示颜色
}
}
}
6、(在指定区域内填充指定颜色块)使用函数:
LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color);
(1)(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)**(ey-sy+1);
(2)color:要填充的颜色
(3)源代码:
void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
{
u16 height,width;
u16 i,j;
width=ex-sx+1; //得到填充的高度
height=ey-sy+1; //高度
for(i=0;i<height;i++)
{
LCD_SetCursor(sx,sy+i); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
for(j=0;j<width;j++)LCD->LCD_RAM=color[i*width+j];//写入数据
}
}
7、(画线)使用函数:
LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2);
(1)x1,y1:起点坐标;
(2)x2,y2:终点坐标;
(3)源代码:
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
delta_x=x2-x1; //计算坐标增量
delta_y=y2-y1;
uRow=x1;
uCol=y1;
if(delta_x>0)incx=1; //设置单步方向
else if(delta_x==0)incx=0;//垂直线
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;
else if(delta_y==0)incy=0;//水平线
else{incy=-1;delta_y=-delta_y;}
if( delta_x>delta_y)distance=delta_x; //选择基本增量坐标轴
else distance=delta_y;
for(t=0;t<=distance+1;t++ )//画线输出
{
LCD_DrawPoint(uRow,uCol);//画点
xerr+=delta_x ;
yerr+=delta_y ;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
8、(画矩形)使用函数:
LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2);
(1)(x1,y1),(x2,y2):矩形的对角坐标;
(2)源代码:
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
{
LCD_DrawLine(x1,y1,x2,y1);
LCD_DrawLine(x1,y1,x1,y2);
LCD_DrawLine(x1,y2,x2,y2);
LCD_DrawLine(x2,y1,x2,y2);
}
9、(在指定位置画一个指定大小的圆)使用函数:
LCD_Draw_Circle(u16 x0,u16 y0,u8 r);
(1)(x,y):中心点
(2)r:半径
(3)源代码:
void LCD_Draw_Circle(u16 x0,u16 y0,u8 r)
{
int a,b;
int di;
a=0;b=r;
di=3-(r<<1); //判断下个点位置的标志
while(a<=b)
{
LCD_DrawPoint(x0+a,y0-b); //5
LCD_DrawPoint(x0+b,y0-a); //0
LCD_DrawPoint(x0+b,y0+a); //4
LCD_DrawPoint(x0+a,y0+b); //6
LCD_DrawPoint(x0-a,y0+b); //1
LCD_DrawPoint(x0-b,y0+a);
LCD_DrawPoint(x0-a,y0-b); //2
LCD_DrawPoint(x0-b,y0-a); //7
a++;
//使用Bresenham算法画圆
if(di<0)di +=4*a+6;
else
{
di+=10+4*(a-b);
b--;
}
}
}
10、(画点)使用函数:
LCD_DrawPoint(u16 x,u16 y)
(1)x,y:坐标
(2)POINT COLOR:此点的颜色
(3)源代码:
void LCD_DrawPoint(u16 x,u16 y)
{
LCD_SetCursor(x,y); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
LCD->LCD_RAM=POINT_COLOR;
}
11、(快速画点)使用函数:
LCD_Fast_DrawPoint(u16 x,u16 y,u16 color);
(1)x,y:坐标;
(2)color:颜色;
(3)源代码:
void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color)
{
if(lcddev.id==0X9341||lcddev.id==0X5310)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);
}else if(lcddev.id==0X5510)
{
LCD_WR_REG(lcddev.setxcmd);LCD_WR_DATA(x>>8);
LCD_WR_REG(lcddev.setxcmd+1);LCD_WR_DATA(x&0XFF);
LCD_WR_REG(lcddev.setycmd);LCD_WR_DATA(y>>8);
LCD_WR_REG(lcddev.setycmd+1);LCD_WR_DATA(y&0XFF);
}else if(lcddev.id==0X1963)
{
if(lcddev.dir==0)x=lcddev.width-1-x;
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);
LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);
LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);
}else if(lcddev.id==0X6804)
{
if(lcddev.dir==1)x=lcddev.width-1-x;//横屏时处理
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(x>>8);LCD_WR_DATA(x&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(y>>8);LCD_WR_DATA(y&0XFF);
}else
{
if(lcddev.dir==1)x=lcddev.width-1-x;//横屏其实就是调转x,y坐标
LCD_WriteReg(lcddev.setxcmd,x);
LCD_WriteReg(lcddev.setycmd,y);
}
LCD->LCD_REG=lcddev.wramcmd;
LCD->LCD_RAM=color;
}
12、在指定位置显示数字,(高位为0,则不显示)使用函数:
LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size);
(1)x,y:起点坐标;
(2)len:数字的位数;
(3)size:数字的大小;
(4)color:颜色;
(5)num:数值(0~4294967295);
(6)源代码:
void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
{
u8 t,temp;
u8 enshow=0;
for(t=0;t<len;t++)
{
temp=(num/LCD_Pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
LCD_ShowChar(x+(size/2)*t,y,' ',size,0);
continue;
}else enshow=1;
}
LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,0);
}
}
(7)函数使用例子:
对OV2640的芯片地址(厂家地址)进行读取并显示(源代码):
SCCB_Init(); //初始化SCCB接口
u16 reg;
reg=SCCB_RD_Reg(OV2640_SENSOR_MIDH); //读取厂家ID高八位
reg|=SCCB_RD_Reg(OV2640_SENSOR_MIDL); //读取厂家ID低八位
reg=SCCB_RD_Reg(OV2640_SENSOR_PIDH); //读取厂家ID高八位
reg<<=8;
reg|=SCCB_RD_Reg(OV2640_SENSOR_PIDL); //读取厂家ID低八位
//依次显示厂家ID
LCD_ShowNum(10,20,reg,4,16);//在LCD上显示reg
LCD_ShowNum(20,40,reg,5,16);
LCD_ShowNum(30,60,reg,6,16);
LCD_ShowNum(40,80,reg,5,16);
LCD_ShowNum(50,100,reg,6,16);
LCD_ShowNum(60,120,reg,7,16);
LCD_ShowNum(70,140,reg,8,16);
LCD_ShowNum(80,240,reg,9,16);
13、对LDC上的点进行人一颜色填充操作:
(1)源代码:
LCD_SetCursor(0,0);//设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
for(int i = 1;i<=600;i++)
{
LCD->LCD_RAM = BRRED ;
}
for(int a = 601;a<=1100;a++)
{
//LCD_WriteRAM(BLACK);
LCD->LCD_RAM = BLACK;
}
for(int b = 1101;b<=3000;b++)
{
LCD->LCD_RAM = LBBLUE;
}