/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* 液晶屏驅動程序參考wiki技術網站提供的開源源碼,僅供學習使用? ? ? ? ? */
/*---------------------------------------------------------------------*/
/************************************************************************************************
本例程基于AI8051U為主控芯片的實驗箱進行編寫測試.
使用Keil C251編譯器,Memory Model推薦設置XSmall模式,默認定義變量在edata,單時鐘存取訪問速度快。
edata建議保留1K給堆棧使用,空間不夠時可將大數組、不常用變量加xdata關鍵字定義到xdata空間。
本實驗測試使用的是2.4寸320*240 ILI9341 I8080接口驅動的并口彩屏。
主循環修改判斷條件參數可修改測試模式:0:觸摸測試, 1:顯示測試
下載時, 選擇時鐘 40MHz (用戶可自行修改頻率).
************************************************************************************************/
//=========================================電源接線================================================//
//VDD接DC 3.3V電源
//GND接地
//=======================================液晶屏數據線接線==========================================//
//本模塊數據總線類型為8位并口
// LCD_D0~D7? ? ?接? ? ? ?P20~P27? ? ? ? //液晶屏8位數據線
//=======================================液晶屏控制線接線==========================================//
// LCD_RS? ? ? ? 接? ? ? ? P45? ? ? ? ? ?//數據/命令選擇控制信號
// LCD_RD? ? ? ? 接? ? ? ? P37? ? ? ? ? ?//讀控制信號
// LCD_RST? ? ? ?接? ? ? ? P47? ? ? ? ? ?//復位信號
// LCD_WR? ? ? ? 接? ? ? ? P36? ? ? ? ? ?//寫控制信號
// LCD_CS? ? ? ? 接? ? ? ? P05/P53? ? ? ?//片選控制信號
//================================================================================================//
//不使用觸摸或者模塊本身不帶觸摸,則可不連接
//觸摸屏使用的數據總線類型為SPI
//? T_CS? ? ? ? ?接? ? ? ? P15? ? ? ? ? //觸摸屏片選控制信號
//? T_CLK? ? ? ? 接? ? ? ? P32? ? ? ? ? //觸摸屏SPI時鐘信號
//? T_DO? ? ? ? ?接? ? ? ? P33? ? ? ? ? //觸摸屏SPI讀信號
//? T_DIN? ? ? ? 接? ? ? ? P34? ? ? ? ? //觸摸屏SPI寫信號
//? T_IRQ? ? ? ? 接? ? ? ? P14? ? ? ? ? //觸摸屏響應檢查信號
//================================================================================================//
// 本實驗使用的2.4寸320*240的并口彩屏,由沖哥淘寶店提供:http://e.tb.cn/h.gIlbVqAOj8YXlwo?tk=vFIr3RGTy2n
//**************************************************************************************************/
#include "sys.h"
#include "lcd.h"
#include "gui.h"
#include "test.h"
#include "touch.h"
//主函數
void main(void)
{?
WTST = 0;? //設置程序指令延時參數,賦值為0可將CPU執行指令的速度設置為最快
EAXFR = 1; //擴展寄存器(XFR)訪問使能
CKCON = 0; //提高訪問XRAM速度
? ? //液晶屏初始化
LCD_Init();
? ? //循環進行各項測試? ??
while(1)
{
#if 1? ? ? ? ? ?//0:觸摸測試, 1:顯示測試
main_test();? ? ? ? //測試主界面
Test_Read();? ? ? ? //讀ID和顏色值測試
Test_Color();? ? ? ?//簡單刷屏填充測試
Test_FillRec();? ? ?//GUI矩形繪圖測試
Test_Circle();? ? ? //GUI畫圓測試
Test_Triangle();? ? //GUI三角形填充測試
English_Font_test();//英文字體示例測試
Chinese_Font_test();//中文字體示例測試
Pic_test();? ? ? ? ?//圖片顯示示例測試
Rotate_Test();? ? ? //屏幕旋轉測試
#else
//需要觸摸校準時,使用下面觸摸校準測試項
Touch_Adjust();? ? ?//觸摸校準
//不使用觸摸或者模塊本身不帶觸摸,請屏蔽下面觸摸屏測試
Touch_Test();? ? ? ?//觸摸屏手寫測試
#endif
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//////////////////////GUI_Draw.C/////////////////////////////////////
/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* 液晶屏驅動程序參考wiki技術網站提供的開源源碼,僅供學習使用? ? ? ? ? */
/*---------------------------------------------------------------------*/
//=========================================電源接線================================================//
//VDD接DC 3.3V電源
//GND接地
//=======================================液晶屏數據線接線==========================================//
//本模塊數據總線類型為8位并口
// LCD_D0~D7? ? ?接? ? ? ?P20~P27? ? ? ? //液晶屏8位數據線
//=======================================液晶屏控制線接線==========================================//
// LCD_RS? ? ? ? 接? ? ? ? P45? ? ? ? ? ?//數據/命令選擇控制信號
// LCD_RD? ? ? ? 接? ? ? ? P37? ? ? ? ? ?//讀控制信號
// LCD_RST? ? ? ?接? ? ? ? P47? ? ? ? ? ?//復位信號
// LCD_WR? ? ? ? 接? ? ? ? P36? ? ? ? ? ?//寫控制信號
// LCD_CS? ? ? ? 接? ? ? ? P05/P53? ? ? ?//片選控制信號
//================================================================================================//
//不使用觸摸或者模塊本身不帶觸摸,則可不連接
//觸摸屏使用的數據總線類型為SPI
//? T_CS? ? ? ? ?接? ? ? ? P15? ? ? ? ? //觸摸屏片選控制信號
//? T_CLK? ? ? ? 接? ? ? ? P32? ? ? ? ? //觸摸屏SPI時鐘信號
//? T_DO? ? ? ? ?接? ? ? ? P33? ? ? ? ? //觸摸屏SPI讀信號
//? T_DIN? ? ? ? 接? ? ? ? P34? ? ? ? ? //觸摸屏SPI寫信號
//? T_IRQ? ? ? ? 接? ? ? ? P14? ? ? ? ? //觸摸屏響應檢查信號
//================================================================================================//
// 本實驗使用的2.4寸320*240的并口彩屏,由沖哥淘寶店提供:http://e.tb.cn/h.gIlbVqAOj8YXlwo?tk=vFIr3RGTy2n
//**************************************************************************************************/
#include "lcd.h"
#include "font.h"?
#include "sys.h"
#include "gui.h"
#include "string.h"
/*******************************************************************
* @name? ? ? ?:void GUI_DrawPoint(u16 x,u16 y,u16 color)
* @date? ? ? ?:2018-08-09?
* @function? ?:draw a point in LCD screen
* @parameters :x:the x coordinate of the point
y:the y coordinate of the point
color:the color value of the point
* @retvalue? ?:None
********************************************************************/
void GUI_DrawPoint(u16 x,u16 y,u16 color)
{
LCD_SetCursor(x,y);//設置光標位置?
LCD_WR_DATA_16Bit(color);?
}
/*******************************************************************
* @name? ? ? ?:void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
* @date? ? ? ?:2018-08-09?
* @function? ?:fill the specified area
* @parameters :sx:the beginning x coordinate of the specified area
sy:the beginning y coordinate of the specified area
ex:the ending x coordinate of the specified area
ey:the ending y coordinate of the specified area
color:the filled color value
* @retvalue? ?:None
********************************************************************/
void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
{? ? ??
u16 i,j;? ? ? ? ? ??
u16 width=ex-sx+1;? ? ? ? ?//得到填充的寬度
u16 height=ey-sy+1;? ? ? ? //高度
LCD_SetWindows(sx,sy,ex,ey);//設置顯示窗口
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
LCD_WR_DATA_16Bit(color);? ? //寫入數據? ? ??
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢復窗口設置為全屏
}
/*******************************************************************
* @name? ? ? ?:void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
* @date? ? ? ?:2018-08-09?
* @function? ?:Draw a line between two points
* @parameters :x1:the beginning x coordinate of the line
y1:the beginning y coordinate of the line
x2:the ending x coordinate of the line
y2:the ending y coordinate of the line
* @retvalue? ?:None
********************************************************************/
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;?
}?
}??
}?
/*****************************************************************************
* @name? ? ? ?:void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
* @date? ? ? ?:2018-08-09?
* @function? ?:Draw a rectangle
* @parameters :x1:the beginning x coordinate of the rectangle
y1:the beginning y coordinate of the rectangle
x2:the ending x coordinate of the rectangle
y2:the ending y coordinate of the rectangle
* @retvalue? ?:None
******************************************************************************/
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);
}??
/*****************************************************************************
* @name? ? ? ?:void LCD_DrawFillRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
* @date? ? ? ?:2018-08-09?
* @function? ?:Filled a rectangle
* @parameters :x1:the beginning x coordinate of the filled rectangle
y1:the beginning y coordinate of the filled rectangle
x2:the ending x coordinate of the filled rectangle
y2:the ending y coordinate of the filled rectangle
* @retvalue? ?:None
******************************************************************************/??
void LCD_DrawFillRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
{
LCD_Fill(x1,y1,x2,y2,POINT_COLOR);
}
/*****************************************************************************
* @name? ? ? ?:void _draw_circle_8(int xc, int yc, int x, int y, u16 c)
* @date? ? ? ?:2018-08-09?
* @function? ?:8 symmetry circle drawing algorithm (internal call)
* @parameters :xc:the x coordinate of the Circular center?
yc:the y coordinate of the Circular center?
x:the x coordinate relative to the Circular center?
y:the y coordinate relative to the Circular center?
c:the color value of the circle
* @retvalue? ?:None
******************************************************************************/??
void _draw_circle_8(int xc, int yc, int x, int y, u16 c)
{
GUI_DrawPoint(xc + x, yc + y, c);
? ? GUI_DrawPoint(xc - x, yc + y, c);
? ? GUI_DrawPoint(xc + x, yc - y, c);
? ? GUI_DrawPoint(xc - x, yc - y, c);
? ? GUI_DrawPoint(xc + y, yc + x, c);
? ? GUI_DrawPoint(xc - y, yc + x, c);
? ? GUI_DrawPoint(xc + y, yc - x, c);
? ? GUI_DrawPoint(xc - y, yc - x, c);
}
/*****************************************************************************
* @name? ? ? ?:void gui_circle(int xc, int yc,u16 c,int r, int fill)
* @date? ? ? ?:2018-08-09?
* @function? ?:Draw a circle of specified size at a specified location
* @parameters :xc:the x coordinate of the Circular center?
yc:the y coordinate of the Circular center?
r:Circular radius
fill:1-filling,0-no filling
* @retvalue? ?:None
******************************************************************************/??
void gui_circle(int xc, int yc,u16 c,int r, int fill)
{
int x = 0, y = r, yi, d;
? ? d = 3 - 2 * r;
? ? if (fill)?
{
// 如果填充(畫實心圓)
while (x <= y) {
for (yi = x; yi <= y; yi++)
_draw_circle_8(xc, yc, x, yi, c);
? ? ? ? ? ? if (d < 0) {
d = d + 4 * x + 6;
} else {
d = d + 4 * (x - y) + 10;
y--;
}
x++;
}
} else?
{
// 如果不填充(畫空心圓)
while (x <= y) {
_draw_circle_8(xc, yc, x, y, c);
if (d < 0) {
d = d + 4 * x + 6;
} else {
d = d + 4 * (x - y) + 10;
y--;
}
x++;
}
}
}
/*****************************************************************************
* @name? ? ? ?:void Draw_Triangel(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2)
* @date? ? ? ?:2018-08-09?
* @function? ?:Draw a triangle at a specified position
* @parameters :x0:the beginning x coordinate of the triangular edge?
y0:the beginning y coordinate of the triangular edge?
x1:the vertex x coordinate of the triangular
y1:the vertex y coordinate of the triangular
x2:the ending x coordinate of the triangular edge?
y2:the ending y coordinate of the triangular edge?
* @retvalue? ?:None
******************************************************************************/?
void Draw_Triangel(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2)
{
LCD_DrawLine(x0,y0,x1,y1);
LCD_DrawLine(x1,y1,x2,y2);
LCD_DrawLine(x2,y2,x0,y0);
}
static void _swap(u16 *a, u16 *b)
{
u16 tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
/*****************************************************************************
* @name? ? ? ?:void Fill_Triangel(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2)
* @date? ? ? ?:2018-08-09?
* @function? ?:filling a triangle at a specified position
* @parameters :x0:the beginning x coordinate of the triangular edge?
y0:the beginning y coordinate of the triangular edge?
x1:the vertex x coordinate of the triangular
y1:the vertex y coordinate of the triangular
x2:the ending x coordinate of the triangular edge?
y2:the ending y coordinate of the triangular edge?
* @retvalue? ?:None
******************************************************************************/?
void Fill_Triangel(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2)
{
u16 a, b, y, last;
int dx01, dy01, dx02, dy02, dx12, dy12;
long sa = 0;
long sb = 0;
if (y0 > y1)?
{
_swap(&y0,&y1);?
_swap(&x0,&x1);
}
if (y1 > y2)?
{
_swap(&y2,&y1);?
_swap(&x2,&x1);
}
if (y0 > y1)?
{
_swap(&y0,&y1);?
_swap(&x0,&x1);
}
if(y0 == y2)?
{?
a = b = x0;
if(x1 < a)
{
a = x1;
}
else if(x1 > b)
{
b = x1;
}
if(x2 < a)
{
a = x2;
}
else if(x2 > b)
{
b = x2;
}
LCD_Fill(a,y0,b,y0,POINT_COLOR);
return;
}
dx01 = x1 - x0;
dy01 = y1 - y0;
dx02 = x2 - x0;
dy02 = y2 - y0;
dx12 = x2 - x1;
dy12 = y2 - y1;
if(y1 == y2)
{
last = y1;?
}
else
{
last = y1-1;?
}
for(y=y0; y<=last; y++)?
{
a = x0 + sa / dy01;
b = x0 + sb / dy02;
sa += dx01;
sb += dx02;
if(a > b)
{
_swap(&a,&b);
}
LCD_Fill(a,y,b,y,POINT_COLOR);
}
sa = dx12 * (y - y1);
sb = dx02 * (y - y0);
for(; y<=y2; y++)?
{
a = x1 + sa / dy12;
b = x0 + sb / dy02;
sa += dx12;
sb += dx02;
if(a > b)
{
_swap(&a,&b);
}
LCD_Fill(a,y,b,y,POINT_COLOR);
}
}
/*****************************************************************************
* @name? ? ? ?:void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
* @date? ? ? ?:2018-08-09?
* @function? ?:Display a single English character
* @parameters :x:the beginning x coordinate of the Character display position
y:the beginning y coordinate of the Character display position
fc:the color value of display character
bc:the background color of display character
num:the ascii code of display character(0~94)
size:the size of display character
mode:0-no overlying,1-overlying
* @retvalue? ?:None
******************************************************************************/?
void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
{??
u8 temp;
u8 pos,t;
u16 colortemp=POINT_COLOR;? ? ??
? ? num=num-' ';//得到偏移后的值
LCD_SetWindows(x,y,x+size/2-1,y+size-1);//設置單個文字顯示窗口
if(!mode) //非疊加方式
{
for(pos=0;pos<size;pos++)
{
if(size==12)temp=asc2_1206[num].dat[pos];//調用1206字體
else temp=asc2_1608[num].dat[pos];? ? ? ? ?//調用1608字體
for(t=0;t<size/2;t++)
{? ? ? ? ? ? ? ? ?
if(temp&0x01)LCD_WR_DATA_16Bit(fc);?
else LCD_WR_DATA_16Bit(bc);?
temp>>=1;?
}
}? ??
}else//疊加方式
{
for(pos=0;pos<size;pos++)
{
if(size==12)temp=asc2_1206[num].dat[pos];//調用1206字體
else temp=asc2_1608[num].dat[pos];? ? ? ? ?//調用1608字體
for(t=0;t<size/2;t++)
{? ?
POINT_COLOR=fc;? ? ? ? ? ? ??
if(temp&0x01)LCD_DrawPoint(x+t,y+pos);//畫一個點? ??
temp>>=1;?
}
}
}
POINT_COLOR=colortemp;? ??
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢復窗口為全屏? ? ? ? ? ? ? ? ? ? ??
}
/*****************************************************************************
* @name? ? ? ?:void LCD_ShowString(u16 x,u16 y,u8 size,u8 *p,u8 mode)
* @date? ? ? ?:2018-08-09?
* @function? ?:Display English string
* @parameters :x:the beginning x coordinate of the English string
y:the beginning y coordinate of the English string
p:the start address of the English string
size:the size of display character
mode:0-no overlying,1-overlying
* @retvalue? ?:None
******************************************************************************/? ? ? ? ?
void LCD_ShowString(u16 x,u16 y,u8 size,u8 *p,u8 mode)
{? ? ? ? ?
while((*p<='~')&&(*p>=' '))//判斷是不是非法字符!
{? ?
if(x>(lcddev.width-1)||y>(lcddev.height-1))?
return;? ? ?
LCD_ShowChar(x,y,POINT_COLOR,BACK_COLOR,*p,size,mode);
x+=size/2;
p++;
}??
}?
/*****************************************************************************
* @name? ? ? ?:u32 mypow(u8 m,u8 n)
* @date? ? ? ?:2018-08-09?
* @function? ?:get the nth power of m (internal call)
* @parameters :m:the multiplier
n:the power
* @retvalue? ?:the nth power of m
******************************************************************************/?
u32 mypow(u8 m,u8 n)
{
u32 result=1;? ? ?
while(n--)result*=m;? ??
return result;
}
/*****************************************************************************
* @name? ? ? ?:void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
* @date? ? ? ?:2018-08-09?
* @function? ?:Display number
* @parameters :x:the beginning x coordinate of the number
y:the beginning y coordinate of the number
num:the number(0~4294967295)
len:the length of the display number
size:the size of display number
* @retvalue? ?:None
******************************************************************************/? ? ? ? ? ? ? ?
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/mypow(10,(u8)(len-t-1)))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
LCD_ShowChar(x+(size/2)*t,y,POINT_COLOR,BACK_COLOR,' ',size,0);
continue;
}else enshow=1;?
}
LCD_ShowChar(x+(size/2)*t,y,POINT_COLOR,BACK_COLOR,(u8)(temp+'0'),size,0);?
}
}?
/*****************************************************************************
* @name? ? ? ?:void GUI_DrawFont16(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode)
* @date? ? ? ?:2018-08-09?
* @function? ?:Display a single 16x16 Chinese character
* @parameters :x:the beginning x coordinate of the Chinese character
y:the beginning y coordinate of the Chinese character
fc:the color value of Chinese character
bc:the background color of Chinese character
s:the start address of the Chinese character
mode:0-no overlying,1-overlying
* @retvalue? ?:None
******************************************************************************/?
void GUI_DrawFont16(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode)
{
u8 i,j;
u16 k;
u16 HZnum;
u16 x0=x;
HZnum=sizeof(tfont16)/sizeof(typFNT_GB16);? ? //自動統計漢字數目
for (k=0;k<HZnum;k++)?
{
if ((tfont16[k].txt[0]==*(s))&&(tfont16[k].txt[1]==*(s+1)))
{
LCD_SetWindows(x,y,x+16-1,y+16-1);
for(i=0;i<16*2;i++)
{
for(j=0;j<8;j++)
{? ??
if(!mode) //非疊加方式
{
if(tfont16[k].dat[i]&(0x80>>j))? ? LCD_WR_DATA_16Bit(fc);
else LCD_WR_DATA_16Bit(bc);
}
else
{
POINT_COLOR=fc;
if(tfont16[k].dat[i]&(0x80>>j))? ? LCD_DrawPoint(x,y);//畫一個點
x++;
if((x-x0)==16)
{
x=x0;
y++;
break;
}
}
}
}
}? ? ? ? ? ? ? ? ? ? ??
continue;? //查找到對應點陣字庫立即退出,防止多個漢字重復取模帶來影響
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢復窗口為全屏??
}?
/*****************************************************************************
* @name? ? ? ?:void GUI_DrawFont24(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode)
* @date? ? ? ?:2018-08-09?
* @function? ?:Display a single 24x24 Chinese character
* @parameters :x:the beginning x coordinate of the Chinese character
y:the beginning y coordinate of the Chinese character
fc:the color value of Chinese character
bc:the background color of Chinese character
s:the start address of the Chinese character
mode:0-no overlying,1-overlying
* @retvalue? ?:None
******************************************************************************/?
void GUI_DrawFont24(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode)
{
u8 i,j;
u16 k;
u16 HZnum;
u16 x0=x;
HZnum=sizeof(tfont24)/sizeof(typFNT_GB24);? ? //自動統計漢字數目
? ? for (k=0;k<HZnum;k++)?
{
if ((tfont24[k].txt[0]==*(s))&&(tfont24[k].txt[1]==*(s+1)))
{
LCD_SetWindows(x,y,x+24-1,y+24-1);
for(i=0;i<24*3;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非疊加方式
{
if(tfont24[k].dat[i]&(0x80>>j))? ? LCD_WR_DATA_16Bit(fc);
else LCD_WR_DATA_16Bit(bc);
}
else
{
POINT_COLOR=fc;
if(tfont24[k].dat[i]&(0x80>>j))? ? LCD_DrawPoint(x,y);//畫一個點
x++;
if((x-x0)==24)
{
x=x0;
y++;
break;
}
}
}
}
}? ? ? ? ? ? ? ? ? ? ??
continue;? //查找到對應點陣字庫立即退出,防止多個漢字重復取模帶來影響
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢復窗口為全屏??
}
/*****************************************************************************
* @name? ? ? ?:void GUI_DrawFont32(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode)
* @date? ? ? ?:2018-08-09?
* @function? ?:Display a single 32x32 Chinese character
* @parameters :x:the beginning x coordinate of the Chinese character
y:the beginning y coordinate of the Chinese character
fc:the color value of Chinese character
bc:the background color of Chinese character
s:the start address of the Chinese character
mode:0-no overlying,1-overlying
* @retvalue? ?:None
******************************************************************************/?
void GUI_DrawFont32(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode)
{
u8 i,j;
u16 k;
u16 HZnum;
u16 x0=x;
HZnum=sizeof(tfont32)/sizeof(typFNT_GB32);? ? //自動統計漢字數目
for (k=0;k<HZnum;k++)?
{
if ((tfont32[k].txt[0]==*(s))&&(tfont32[k].txt[1]==*(s+1)))
{
LCD_SetWindows(x,y,x+32-1,y+32-1);
for(i=0;i<32*4;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非疊加方式
{
if(tfont32[k].dat[i]&(0x80>>j))? ? LCD_WR_DATA_16Bit(fc);
else LCD_WR_DATA_16Bit(bc);
}
else
{
POINT_COLOR=fc;
if(tfont32[k].dat[i]&(0x80>>j))? ? LCD_DrawPoint(x,y);//畫一個點
x++;
if((x-x0)==32)
{
x=x0;
y++;
break;
}
}
}
}
}? ? ? ? ? ? ? ? ? ? ??
continue;? //查找到對應點陣字庫立即退出,防止多個漢字重復取模帶來影響
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢復窗口為全屏??
}?
/*****************************************************************************
* @name? ? ? ?:void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
* @date? ? ? ?:2018-08-09?
* @function? ?:Display Chinese and English strings
* @parameters :x:the beginning x coordinate of the Chinese and English strings
y:the beginning y coordinate of the Chinese and English strings
fc:the color value of Chinese and English strings
bc:the background color of Chinese and English strings
str:the start address of the Chinese and English strings
size:the size of Chinese and English strings
mode:0-no overlying,1-overlying
* @retvalue? ?:None
******************************************************************************/? ? ? ? ? ? ? ? ??
void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
{? ? ? ? ? ? ? ? ? ??
u16 x0=x;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
u8 bHz=0;? ? ?//字符或者中文?
while(*str!=0)//數據未結束
{?
if(!bHz)
{
if(x>(lcddev.width-size/2)||y>(lcddev.height-size))?
return;?
if(*str>0x80)bHz=1;//中文?
else? ? ? ? ? ? ? //字符
{? ? ? ? ??
if(*str==0x0D)//換行符號
{? ? ? ? ?
y+=size;
x=x0;
str++;?
}??
else
{
if(size>16)//字庫中沒有集成12X24 16X32的英文字體,用8X16代替
{??
LCD_ShowChar(x,y,fc,bc,*str,16,mode);
x+=8; //字符,為全字的一半?
}
else
{
LCD_ShowChar(x,y,fc,bc,*str,size,mode);
x+=size/2; //字符,為全字的一半?
}
}?
str++;?
}
}
else//中文?
{? ?
if(x>(lcddev.width-size)||y>(lcddev.height-size))?
return;??
bHz=0;//有漢字庫? ??
if(size==32)
GUI_DrawFont32(x,y,fc,bc,str,mode);? ? ? ? ?
else if(size==24)
GUI_DrawFont24(x,y,fc,bc,str,mode);? ??
else
GUI_DrawFont16(x,y,fc,bc,str,mode);
str+=2;?
x+=size;//下一個漢字偏移? ? ? ??
}? ? ? ? ? ? ? ? ? ? ? ? ?
}? ?
}
/*****************************************************************************
* @name? ? ? ?:void Gui_StrCenter(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
* @date? ? ? ?:2018-08-09?
* @function? ?:Centered display of English and Chinese strings
* @parameters :x:the beginning x coordinate of the Chinese and English strings
y:the beginning y coordinate of the Chinese and English strings
fc:the color value of Chinese and English strings
bc:the background color of Chinese and English strings
str:the start address of the Chinese and English strings
size:the size of Chinese and English strings
mode:0-no overlying,1-overlying
* @retvalue? ?:None
******************************************************************************/?
void Gui_StrCenter(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode)
{
u16 len=strlen((const char *)str);
u16 x1=(lcddev.width-len*8)/2;
Show_Str(x+x1,y,fc,bc,str,size,mode);
}?
/*****************************************************************************
* @name? ? ? ?:void Gui_Drawbmp16(u16 x,u16 y,const unsigned char *p)
* @date? ? ? ?:2018-08-09?
* @function? ?:Display a 16-bit BMP image
* @parameters :x:the beginning x coordinate of the BMP image
y:the beginning y coordinate of the BMP image
p:the start address of image array
* @retvalue? ?:None
******************************************************************************/?
void Gui_Drawbmp16(u16 x,u16 y,const unsigned char *p) //顯示40*40 QQ圖片
{
int i;?
unsigned char picH,picL;?
LCD_SetWindows(x,y,x+40-1,y+40-1);//窗口設置
for(i=0;i<40*40;i++)
{? ??
picL=*(p+i*2);? ? //數據低位在前
picH=*(p+i*2+1);? ? ? ? ? ? ? ??
LCD_WR_DATA_16Bit(picH<<8|picL);? ? ? ? ? ? ? ? ? ? ? ? ??
}? ??
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢復顯示窗口為全屏? ??
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////LCD.C/////////////////////////////////////
/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* 液晶屏驅動程序參考wiki技術網站提供的開源源碼,僅供學習使用? ? ? ? ? */
/*---------------------------------------------------------------------*/
//=========================================電源接線================================================//
//VDD接DC 3.3V電源
//GND接地
//=======================================液晶屏數據線接線==========================================//
//本模塊數據總線類型為8位并口
// LCD_D0~D7? ? ?接? ? ? ?P20~P27? ? ? ? //液晶屏8位數據線
//=======================================液晶屏控制線接線==========================================//
// LCD_RS? ? ? ? 接? ? ? ? P45? ? ? ? ? ?//數據/命令選擇控制信號
// LCD_RD? ? ? ? 接? ? ? ? P37? ? ? ? ? ?//讀控制信號
// LCD_RST? ? ? ?接? ? ? ? P47? ? ? ? ? ?//復位信號
// LCD_WR? ? ? ? 接? ? ? ? P36? ? ? ? ? ?//寫控制信號
// LCD_CS? ? ? ? 接? ? ? ? P05/P53? ? ? ?//片選控制信號
//================================================================================================//
//不使用觸摸或者模塊本身不帶觸摸,則可不連接
//觸摸屏使用的數據總線類型為SPI
//? T_CS? ? ? ? ?接? ? ? ? P15? ? ? ? ? //觸摸屏片選控制信號
//? T_CLK? ? ? ? 接? ? ? ? P32? ? ? ? ? //觸摸屏SPI時鐘信號
//? T_DO? ? ? ? ?接? ? ? ? P33? ? ? ? ? //觸摸屏SPI讀信號
//? T_DIN? ? ? ? 接? ? ? ? P34? ? ? ? ? //觸摸屏SPI寫信號
//? T_IRQ? ? ? ? 接? ? ? ? P14? ? ? ? ? //觸摸屏響應檢查信號
//================================================================================================//
// 本實驗使用的2.4寸320*240的并口彩屏,由沖哥淘寶店提供:http://e.tb.cn/h.gIlbVqAOj8YXlwo?tk=vFIr3RGTy2n
//**************************************************************************************************/
#include "sys.h"
#include "lcd.h"
//LCD的畫筆顏色和背景色? ? ? ?
u16 POINT_COLOR=0x0000;? ? //畫筆顏色
u16 BACK_COLOR=0xFFFF;? //背景色?
//管理LCD重要參數
//默認為豎屏
_lcd_dev lcddev;
/*****************************************************************************
* @name? ? ? ?:void LCM_Config(void)
* @date? ? ? ?:2018-11-13?
* @function? ?:Config LCM
* @parameters :None
* @retvalue? ?:None
******************************************************************************/? ??
void LCM_Config(void)
{
LCMIFCFG = 0x00;? ? //bit7 1:Enable Interrupt, bit1 0:8bit mode; bit0 0:8080,1:6800
LCMIFCFG2 = 0x25;? ? //RS:P45,E:P37,RW:P36; Setup Time=1,HOLD Time=1
LCMIFSTA = 0x00;
EA = 1;
}
/*****************************************************************************
* @name? ? ? ?:void LCM_Interrupt(void)
* @date? ? ? ?:2018-11-13?
* @function? ?:None
* @parameters :None
* @retvalue? ?:
******************************************************************************/?
void LCM_Interrupt(void) interrupt 13
{
LCMIFSTA = 0x00;
LCD_CS=1;
}
/*****************************************************************************
* @name? ? ? ?:void LCD_WR_REG(u16 Reg)? ??
* @date? ? ? ?:2018-08-09?
* @function? ?:Write an 16-bit command to the LCD screen
* @parameters :data:Command value to be written
* @retvalue? ?:None
******************************************************************************/
void LCD_WR_REG(u16 Reg)? ? ?
{
LCMIFDATL = Reg;
LCD_CS=0;
LCMIFCR = 0x84;? ? ? ? //Enable interface, write command out
while(!LCMIFSTA);
LCMIFSTA = 0x00;
LCD_CS=1;
}?
/*****************************************************************************
* @name? ? ? ?:void LCD_WR_DATA(u16 Data)
* @date? ? ? ?:2018-08-09?
* @function? ?:Write an 16-bit data to the LCD screen
* @parameters :data:data value to be written
* @retvalue? ?:None
******************************************************************************/
void LCD_WR_DATA(u16 Data)
{
LCMIFDATL = Data;
LCD_CS=0;
LCMIFCR = 0x85;? ? ? ? //Enable interface, write data out
while(!LCMIFSTA);
LCMIFSTA = 0x00;
LCD_CS=1;
}
/*****************************************************************************
* @name? ? ? ?:u16 LCD_RD_DATA(void)
* @date? ? ? ?:2018-11-13?
* @function? ?:Read an 16-bit value from the LCD screen
* @parameters :None
* @retvalue? ?:read value
******************************************************************************/
u16 LCD_RD_DATA(void)
{
u16 d;
//LCM Read
LCD_CS = 0;
LCMIFCR = 0x87;? ? ? ? //Enable interface, Read data
while(!LCMIFSTA);
LCMIFSTA = 0x00;
LCD_CS=1;
d = LCMIFDATL;
? ? return (d);
}
/*****************************************************************************
* @name? ? ? ?:void LCD_WR_DATA_16Bit(u16 Data)
* @date? ? ? ?:2018-08-09?
* @function? ?:Write an 16-bit command to the LCD screen
* @parameters :Data:Data to be written
* @retvalue? ?:None
******************************************************************************/? ? ?
void LCD_WR_DATA_16Bit(u16 Data)
{
LCD_WR_DATA((u8)(Data>>8));
LCD_WR_DATA((u8)Data);
}
u16 Color_To_565(u8 r, u8 g, u8 b)
{
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
}
/*****************************************************************************
* @name? ? ? ?:u16 Lcd_ReadData_16Bit(void)
* @date? ? ? ?:2018-11-13?
* @function? ?:Read an 16-bit value from the LCD screen
* @parameters :None
* @retvalue? ?:read value
******************************************************************************/? ??
u16 Lcd_RD_DATA_16Bit(void)
{
u16 r,g,b;
? ? //dummy data
r = LCD_RD_DATA();
//dummy data
r = LCD_RD_DATA();
//8bit:red data
//16bit:red and green data
r = LCD_RD_DATA();
//8bit:green data
//16bit:blue data
g = LCD_RD_DATA();
? ? b = LCD_RD_DATA();
? ? return Color_To_565((u8)r, (u8)g, (u8)b);
}
/*****************************************************************************
* @name? ? ? ?:void LCD_WriteReg(u16 LCD_Reg, u16 LCD_RegValue)
* @date? ? ? ?:2018-08-09?
* @function? ?:Write data into registers
* @parameters :LCD_Reg:Register address
LCD_RegValue:Data to be written
* @retvalue? ?:None
******************************************************************************/
void LCD_WriteReg(u16 LCD_Reg, u16 LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
}
/*****************************************************************************
* @name? ? ? ?:u16 LCD_ReadReg(u16 LCD_Reg)
* @date? ? ? ?:2018-11-13?
* @function? ?:read value from specially registers
* @parameters :LCD_Reg:Register address
* @retvalue? ?:read value
******************************************************************************/
void LCD_ReadReg(u16 LCD_Reg,u8 *Rval,int n)
{
LCD_WR_REG((u8)LCD_Reg);
while(n--)
{? ? ? ??
*(Rval++) = LCD_RD_DATA();
}
}
/*****************************************************************************
* @name? ? ? ?:void LCD_WriteRAM_Prepare(void)
* @date? ? ? ?:2018-08-09?
* @function? ?:Write GRAM
* @parameters :None
* @retvalue? ?:None
******************************************************************************/? ??
void LCD_WriteRAM_Prepare(void)
{
LCD_WR_REG(lcddev.wramcmd);? ? ??
}
/*****************************************************************************
* @name? ? ? ?:void LCD_ReadRAM_Prepare(void)
* @date? ? ? ?:2018-11-13?
* @function? ?:Read GRAM
* @parameters :None
* @retvalue? ?:None
******************************************************************************/? ? ?
void LCD_ReadRAM_Prepare(void)
{
LCD_WR_REG(lcddev.rramcmd);
}
/*****************************************************************************
* @name? ? ? ?:void LCD_Clear(u16 Color)
* @date? ? ? ?:2018-08-09?
* @function? ?:Full screen filled LCD screen
* @parameters :color:Filled color
* @retvalue? ?:None
******************************************************************************/? ??
void LCD_Clear(u16 Color)
{
u16 i,j;
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);? ??
for(i=0;i<lcddev.width;i++)
{
for (j=0;j<lcddev.height;j++)
{
LCD_WR_DATA_16Bit(Color);
}
}
}
/*****************************************************************************
* @name? ? ? ?:void LCD_DrawPoint(u16 x,u16 y)
* @date? ? ? ?:2018-08-09?
* @function? ?:Write a pixel data at a specified location
* @parameters :x:the x coordinate of the pixel
y:the y coordinate of the pixel
* @retvalue? ?:None
******************************************************************************/? ??
void LCD_DrawPoint(u16 x,u16 y)
{
LCD_SetWindows(x,y,x,y);//設置光標位置?
LCD_WR_DATA_16Bit(POINT_COLOR);? ? ? ? ?
}? ? ??
/*****************************************************************************
* @name? ? ? ?:u16 LCD_ReadPoint(u16 x,u16 y)
* @date? ? ? ?:2018-11-13?
* @function? ?:Read a pixel color value at a specified location
* @parameters :x:the x coordinate of the pixel
y:the y coordinate of the pixel
* @retvalue? ?:the read color value
******************************************************************************/? ??
u16 LCD_ReadPoint(u16 x,u16 y)
{
u16 color;
if(x>=lcddev.width||y>=lcddev.height)
{
return 0;? ? //超過了范圍,直接返回? ??
}
LCD_SetCursor(x,y);//設置光標位置?
LCD_ReadRAM_Prepare();
color = Lcd_RD_DATA_16Bit();
return color;
}
/*****************************************************************************
* @name? ? ? ?:void LCD_Set_GPIO(void)
* @date? ? ? ?:2018-11-13?
* @function? ?:Set the gpio to push-pull mode
* @parameters :None
* @retvalue? ?:None
******************************************************************************/? ??
void LCD_Set_GPIO(void)
{
//P2口設置成準雙向口
P2M0=0x00;
P2M1=0x00;
? ? //P0.4口設置成高阻輸入,P0.5推挽輸出
P0M0=0x20;
P0M1=0x10;
? ? //P1.4口設置成高阻輸入
P1M0=0x00;
P1M1=0x10;
//? ? //P6口設置成高阻輸入(8bit)
//? ? P6M0=0x00;
//? ? P6M1=0xff;
? ? //P3.3口設置成高阻輸入
//P3.7,P3.6,P3.4,P3.2口設置成推挽輸出
P3M0=0xd4;
P3M1=0x08;
? ? //P4.7,P4.5口設置成推挽輸出
P4M0=0xa0;
P4M1=0x00;
? ? //P5.3口設置成推挽輸出
P5M0=0x08;
P5M1=0x00;
}
/*****************************************************************************
* @name? ? ? ?:void LCDReset(void)
* @date? ? ? ?:2018-08-09?
* @function? ?:Reset LCD screen
* @parameters :None
* @retvalue? ?:None
******************************************************************************/? ??
void LCDReset(void)
{
delay_ms(50);? ??
LCD_RESET=0;
delay_ms(50);
LCD_RESET=1;
delay_ms(50);
}
/*****************************************************************************
* @name? ? ? ?:void LCD_Init(void)
* @date? ? ? ?:2018-08-09?
* @function? ?:Initialization LCD screen
* @parameters :None
* @retvalue? ?:None
******************************************************************************/? ? ? ? ??
void LCD_Init(void)
{
LCD_Set_GPIO();
LCM_Config();
LCDReset(); //初始化之前復位
//*************2.4inch ILI9341初始化**********//
LCD_WR_REG(0xCF);??
LCD_WR_DATA(0x00);?
LCD_WR_DATA(0xD9); //0xC1?
LCD_WR_DATA(0X30);?
LCD_WR_REG(0xED);??
LCD_WR_DATA(0x64);?
LCD_WR_DATA(0x03);?
LCD_WR_DATA(0X12);?
LCD_WR_DATA(0X81);?
LCD_WR_REG(0xE8);??
LCD_WR_DATA(0x85);?
LCD_WR_DATA(0x10);?
LCD_WR_DATA(0x7A);?
LCD_WR_REG(0xCB);??
LCD_WR_DATA(0x39);?
LCD_WR_DATA(0x2C);?
LCD_WR_DATA(0x00);?
LCD_WR_DATA(0x34);?
LCD_WR_DATA(0x02);?
LCD_WR_REG(0xF7);??
LCD_WR_DATA(0x20);?
LCD_WR_REG(0xEA);??
LCD_WR_DATA(0x00);?
LCD_WR_DATA(0x00);?
LCD_WR_REG(0xC0);? ? //Power control?
LCD_WR_DATA(0x1B);? ?//VRH[5:0]?
LCD_WR_REG(0xC1);? ? //Power control?
LCD_WR_DATA(0x12);? ?//SAP[2:0];BT[3:0] 0x01
LCD_WR_REG(0xC5);? ? //VCM control?
LCD_WR_DATA(0x08);? ? ? //30
LCD_WR_DATA(0x26);? ? ? //30
LCD_WR_REG(0xC7);? ? //VCM control2?
LCD_WR_DATA(0XB7);?
LCD_WR_REG(0x36);? ? // Memory Access Control?
LCD_WR_DATA(0x08);
LCD_WR_REG(0x3A);? ?
LCD_WR_DATA(0x55);?
LCD_WR_REG(0xB1);? ?
LCD_WR_DATA(0x00);? ?
LCD_WR_DATA(0x1A);?
LCD_WR_REG(0xB6);? ? // Display Function Control?
LCD_WR_DATA(0x0A);?
LCD_WR_DATA(0xA2);?
LCD_WR_REG(0xF2);? ? // 3Gamma Function Disable?
LCD_WR_DATA(0x00);?
LCD_WR_REG(0x26);? ? //Gamma curve selected?
LCD_WR_DATA(0x01);?
LCD_WR_REG(0xE0);? ? //Set Gamma?
LCD_WR_DATA(0x0F);?
LCD_WR_DATA(0x1D);?
LCD_WR_DATA(0x1A);?
LCD_WR_DATA(0x0A);?
LCD_WR_DATA(0x0D);?
LCD_WR_DATA(0x07);?
LCD_WR_DATA(0x49);?
LCD_WR_DATA(0X66);?
LCD_WR_DATA(0x3B);?
LCD_WR_DATA(0x07);?
LCD_WR_DATA(0x11);?
LCD_WR_DATA(0x01);?
LCD_WR_DATA(0x09);?
LCD_WR_DATA(0x05);?
LCD_WR_DATA(0x04);? ? ? ? ??
LCD_WR_REG(0XE1);? ? //Set Gamma?
LCD_WR_DATA(0x00);?
LCD_WR_DATA(0x18);?
LCD_WR_DATA(0x1D);?
LCD_WR_DATA(0x02);?
LCD_WR_DATA(0x0F);?
LCD_WR_DATA(0x04);?
LCD_WR_DATA(0x36);?
LCD_WR_DATA(0x13);?
LCD_WR_DATA(0x4C);?
LCD_WR_DATA(0x07);?
LCD_WR_DATA(0x13);?
LCD_WR_DATA(0x0F);?
LCD_WR_DATA(0x2E);?
LCD_WR_DATA(0x2F);?
LCD_WR_DATA(0x05);?
LCD_WR_REG(0x2B);?
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x3f);
LCD_WR_REG(0x2A);?
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xef);? ? ?
LCD_WR_REG(0x11); //Exit Sleep
delay_ms(120);
LCD_WR_REG(0x29); //display on? ??
? ? //設置LCD屬性參數
LCD_direction(USE_HORIZONTAL);//設置LCD顯示方向?
//? ? LCD_BL=1;//點亮背光? ? ?
}
/*****************************************************************************
* @name? ? ? ?:void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
* @date? ? ? ?:2018-08-09?
* @function? ?:Setting LCD display window
* @parameters :xStar:the bebinning x coordinate of the LCD display window
yStar:the bebinning y coordinate of the LCD display window
xEnd:the endning x coordinate of the LCD display window
yEnd:the endning y coordinate of the LCD display window
* @retvalue? ?:None
******************************************************************************/?
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{
LCD_WR_REG(lcddev.setxcmd);? ??
LCD_WR_DATA(xStar>>8);
LCD_WR_DATA(0x00FF&xStar);? ? ? ??
LCD_WR_DATA(xEnd>>8);
LCD_WR_DATA(0x00FF&xEnd);
? ? LCD_WR_REG(lcddev.setycmd);? ??
LCD_WR_DATA(yStar>>8);
LCD_WR_DATA(0x00FF&yStar);? ? ? ??
LCD_WR_DATA(yEnd>>8);
LCD_WR_DATA(0x00FF&yEnd);? ??
? ? LCD_WriteRAM_Prepare();? ? //開始寫入GRAM
}
/*****************************************************************************
* @name? ? ? ?:void LCD_SetCursor(u16 Xpos, u16 Ypos)
* @date? ? ? ?:2018-08-09?
* @function? ?:Set coordinate value
* @parameters :Xpos:the? x coordinate of the pixel
Ypos:the? y coordinate of the pixel
* @retvalue? ?:None
******************************************************************************/?
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
LCD_SetWindows(Xpos,Ypos,Xpos,Ypos);? ??
}
/*****************************************************************************
* @name? ? ? ?:void LCD_direction(u8 direction)
* @date? ? ? ?:2018-08-09?
* @function? ?:Setting the display direction of LCD screen
* @parameters :direction:0-0 degree
1-90 degree
2-180 degree
3-270 degree
* @retvalue? ?:None
******************************************************************************/?
void LCD_direction(u8 direction)
{
lcddev.setxcmd=0x2A;
lcddev.setycmd=0x2B;
lcddev.wramcmd=0x2C;
lcddev.rramcmd=0x2E;
switch(direction){
case 0:
lcddev.width=LCD_W;
lcddev.height=LCD_H;
LCD_WriteReg(0x36,(1<<3));
break;
case 1:
lcddev.width=LCD_H;
lcddev.height=LCD_W;
LCD_WriteReg(0x36,(1<<3)|(1<<5)|(1<<6));
break;
case 2:
lcddev.width=LCD_W;
lcddev.height=LCD_H;? ??
LCD_WriteReg(0x36,(1<<3)|(1<<4)|(1<<6)|(1<<7));
break;
case 3:
lcddev.width=LCD_H;
lcddev.height=LCD_W;
LCD_WriteReg(0x36,(1<<3)|(1<<7)|(1<<5)|(1<<4));
break;
default:break;
}
}
/*****************************************************************************
* @name? ? ? ?:u16 LCD_Read_ID(void)
* @date? ? ? ?:2018-11-13?
* @function? ?:Read ID
* @parameters :None
* @retvalue? ?:ID value
******************************************************************************/?
u16 LCD_Read_ID(void)
{
u8 val[5] = {0};
LCD_ReadReg(0xD3,val,5);
return (val[3]<<8)|val[4];
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////TOUCH.C/////////////////////////////////////
/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* 液晶屏驅動程序參考wiki技術網站提供的開源源碼,僅供學習使用? ? ? ? ? */
/*---------------------------------------------------------------------*/
//=========================================電源接線================================================//
//VDD接DC 3.3V電源
//GND接地
//=======================================液晶屏數據線接線==========================================//
//本模塊數據總線類型為8位并口
// LCD_D0~D7? ? ?接? ? ? ?P20~P27? ? ? ? //液晶屏8位數據線
//=======================================液晶屏控制線接線==========================================//
// LCD_RS? ? ? ? 接? ? ? ? P45? ? ? ? ? ?//數據/命令選擇控制信號
// LCD_RD? ? ? ? 接? ? ? ? P37? ? ? ? ? ?//讀控制信號
// LCD_RST? ? ? ?接? ? ? ? P47? ? ? ? ? ?//復位信號
// LCD_WR? ? ? ? 接? ? ? ? P36? ? ? ? ? ?//寫控制信號
// LCD_CS? ? ? ? 接? ? ? ? P05/P53? ? ? ?//片選控制信號
//================================================================================================//
//不使用觸摸或者模塊本身不帶觸摸,則可不連接
//觸摸屏使用的數據總線類型為SPI
//? T_CS? ? ? ? ?接? ? ? ? P15? ? ? ? ? //觸摸屏片選控制信號
//? T_CLK? ? ? ? 接? ? ? ? P32? ? ? ? ? //觸摸屏SPI時鐘信號
//? T_DO? ? ? ? ?接? ? ? ? P33? ? ? ? ? //觸摸屏SPI讀信號
//? T_DIN? ? ? ? 接? ? ? ? P34? ? ? ? ? //觸摸屏SPI寫信號
//? T_IRQ? ? ? ? 接? ? ? ? P14? ? ? ? ? //觸摸屏響應檢查信號
//================================================================================================//
// 本實驗使用的2.4寸320*240的并口彩屏,由沖哥淘寶店提供:http://e.tb.cn/h.gIlbVqAOj8YXlwo?tk=vFIr3RGTy2n
//**************************************************************************************************/
#include "sys.h"
#include "touch.h"
#include "lcd.h"
#include "gui.h"
//***因觸摸屏批次不同等原因,默認的校準參數值可能會引起觸摸識別不準,建議校準后再使用,不建議使用固定的默認校準參數
u16 vx=15621,vy=11221;? //比例因子,此值除以1000之后表示多少個AD值代表一個像素點?
u16 chx=3890,chy=340;//默認像素點坐標為0時的AD起始值?
//***因觸摸屏批次不同等原因,默認的校準參數值可能會引起觸摸識別不準,建議校準后再使用,不建議使用固定的默認校準參數
struct tp_pix_? tp_pixad,tp_pixlcd;? ? ?//當前觸控坐標的AD值,前觸控坐標的像素值? ?
//返回觸摸按下的狀態
u8 tpstate(void)
{
return Penirq;
}
//SPI開始
void spistar(void)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
{
TCS=1;
DCLK=1;
DIN=1;
DCLK=1;
}
//SPI寫數據
void WriteCharTo7843(unsigned char num)? ? ? ? ??
{
unsigned char count=0;
DCLK=0;
for(count=0;count<8;count++)
{
num<<=1;
DIN=CY;
DCLK=0; _nop_();_nop_();_nop_();? ? ? ? ? ? ? ? //上升沿有效
DCLK=1; _nop_();_nop_();_nop_();
}
}
//SPI 讀數據
u16 ReadFromCharFrom7843()? ? ? ? ? ? ?
{
u8 count=0;
u16 Num=0;
for(count=0;count<12;count++)
{
Num<<=1;? ? ? ??
DCLK=1; _nop_();_nop_();_nop_();? ?//下降沿有效
DCLK=0; _nop_();_nop_();_nop_();
if(DOUT)
{
Num|=1;
}
}
? ? return(Num);
}
//從7846/7843/XPT2046/UH7843/UH7846讀取adc值? ? ??
//0x90=y? ?0xd0-x
u16 ADS_Read_AD(unsigned char CMD)? ? ? ? ??
{
u16 l;
TCS=0;
WriteCharTo7843(CMD);? ? ? ? //送控制字即用差分方式讀X坐標 詳細請見有關資料
DCLK=1; _nop_();_nop_();_nop_();_nop_();
DCLK=0; _nop_();_nop_();_nop_();_nop_();
l=ReadFromCharFrom7843();
TCS=1;
return l;
}
//讀取一個坐標值
//連續讀取READ_TIMES次數據,對這些數據升序排列,
//然后去掉最低和最高LOST_VAL個數,取平均值?
#define READ_TIMES 15 //讀取次數
#define LOST_VAL 5? ? ? //丟棄值
u16 ADS_Read_XY(u8 xy)
{
u16 i, j;
u16 buf[READ_TIMES];
u16 sum=0;
u16 temp;
for(i=0;i<READ_TIMES;i++)
{? ? ? ? ? ? ? ? ?
buf[i]=ADS_Read_AD(xy);? ? ? ??
}? ? ? ? ? ? ? ? ? ??
for(i=0;i<READ_TIMES-1; i++)//排序
{
for(j=i+1;j<READ_TIMES;j++)
{
if(buf[i]>buf[j])//升序排列
{
temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}? ? ??
sum=0;
for(i=LOST_VAL;i<READ_TIMES-LOST_VAL;i++)sum+=buf[i];
temp=sum/(READ_TIMES-2*LOST_VAL);
return temp;? ?
}
//帶濾波的坐標讀取
//最小值不能少于100.
u8 Read_ADS(u16 *x,u16 *y)
{
u16 xtemp,ytemp;? ? ? ? ? ? ? ? ? ? ? ? ? ??
xtemp=ADS_Read_XY(CMD_RDX);
ytemp=ADS_Read_XY(CMD_RDY);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
if(xtemp<100||ytemp<100)return 0;//讀數失敗
*x=xtemp;
*y=ytemp;
return 1;//讀數成功
}
//2次讀取ADS7846,連續讀取2次有效的AD值,且這兩次的偏差不能超過
//50,滿足條件,則認為讀數正確,否則讀數錯誤.? ? ? ?
//該函數能大大提高準確度
#define ERR_RANGE 20 //誤差范圍?
u8 Read_ADS2(u16 *x,u16 *y)?
{
u16 x1,y1;
u16 x2,y2;
u8 flag;? ??
flag=Read_ADS(&x1,&y1);? ?
if(flag==0)return(0);
flag=Read_ADS(&x2,&y2);? ??
if(flag==0)return(0);? ?
if(((x2<=x1&&x1<x2+ERR_RANGE)||(x1<=x2&&x2<x1+ERR_RANGE))//前后兩次采樣在+-ERR_RANGE內
&&((y2<=y1&&y1<y2+ERR_RANGE)||(y1<=y2&&y2<y1+ERR_RANGE)))
{
*x=(x1+x2)>>1;
*y=(y1+y2)>>1;? ? ? ??
return 1;
}else return 0;? ? ??
}
//精確讀取一次坐標,校準的時候用的? ? ? ?
u8 Read_TP_Once(void)
{
u8 re=0;
u16 x1,y1;
while(re==0)
{
while(!Read_ADS2(&tp_pixad.x,&tp_pixad.y));
delay_ms(10);
while(!Read_ADS2(&x1,&y1));
if(tp_pixad.x==x1&&tp_pixad.y==y1)
{
re=1;?
}
}?
return re;
}
//畫一個校準用的輔助觸摸區域
void Drow_Touch_Point(u16 x,u16 y)
{
POINT_COLOR=RED;
LCD_DrawLine(x-12,y,x+13,y);//橫線
LCD_DrawLine(x,y-12,x,y+13);//豎線
LCD_DrawPoint(x+1,y+1);
LCD_DrawPoint(x-1,y+1);
LCD_DrawPoint(x+1,y-1);
LCD_DrawPoint(x-1,y-1);
gui_circle(x,y,POINT_COLOR,6,0);//畫中心圈
}
//畫一個大點(2*2的點)? ? ? ? ? ?
//x,y:坐標
//color:顏色
void TP_Draw_Big_Point(u16 x,u16 y,u16 color)
{? ? ? ?
POINT_COLOR=color;
LCD_DrawPoint(x,y);//中心點?
LCD_DrawPoint(x+1,y);
LCD_DrawPoint(x,y+1);
LCD_DrawPoint(x+1,y+1);? ? ? ? ? ? ? ?
}
//轉換結果
//根據觸摸屏的校準參數來決定轉換后的結果,保存在tp_pixlcd.x,tp_pixlcd.y中
u8 Convert_Pos(void)
{? ??
#if USE_HORIZONTAL==1
u16 temp;?
#endif? ? ??
u8 l=0;
if(Read_ADS2(&tp_pixad.x,&tp_pixad.y))
{
l=1;
tp_pixlcd.x=tp_pixad.x>chx?((u32)tp_pixad.x-(u32)chx)*1000/vx:((u32)chx-(u32)tp_pixad.x)*1000/vx;
tp_pixlcd.y=tp_pixad.y>chy?((u32)tp_pixad.y-(u32)chy)*1000/vy:((u32)chy-(u32)tp_pixad.y)*1000/vy;
#if USE_HORIZONTAL==0
tp_pixlcd.y=lcddev.height-1-tp_pixlcd.y; //Y坐標鏡像?
#elif USE_HORIZONTAL==1
temp=tp_pixlcd.x;
tp_pixlcd.x=tp_pixlcd.y;
tp_pixlcd.y=lcddev.height-temp;
tp_pixlcd.x=lcddev.width-1-tp_pixlcd.x;
#endif?
}
return l;
}
//觸摸屏校準代碼
//得到四個校準參數
#define tp_pianyi 50? ?//校準坐標偏移量? ??
#define tp_xiaozhun 1000? ?//校準精度
void Touch_Adjust(void)
{? ??
float vx1,vx2,vy1,vy2;? //比例因子,此值除以1000之后表示多少個AD值代表一個像素點
u16 chx1,chx2,chy1,chy2;//默認像素點坐標為0時的AD起始值
u16 lx,ly;? ? ? ? ? ? ? ? ?
struct tp_pixu32_ p[4];
u8? cnt=0;? ? ?
cnt=0;? ? ? ? ? ? ? ??
? ? TCS=1;
DCLK=1;
DIN=1;
DCLK=1;
POINT_COLOR=BLUE;
BACK_COLOR =WHITE;
LCD_Clear(WHITE);//清屏? ?
POINT_COLOR=RED;//紅色?
LCD_Clear(WHITE);//清屏?
Drow_Touch_Point(tp_pianyi,tp_pianyi);//畫點1?
while(1)
{
if(Penirq==0)//按鍵按下了
{
if(Read_TP_Once())//得到單次按鍵值
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
p[cnt].x=tp_pixad.x;
p[cnt].y=tp_pixad.y;
cnt++;?
}? ? ? ? ? ? ?
switch(cnt)
{? ? ? ? ? ? ? ?
case 1:
LCD_Clear(WHITE);//清屏?
while(!Penirq);? //等待松手
Drow_Touch_Point(lcddev.width-tp_pianyi-1,tp_pianyi);//畫點2
break;
case 2:
LCD_Clear(WHITE);//清屏?
while(!Penirq);? //等待松手
Drow_Touch_Point(tp_pianyi,lcddev.height-tp_pianyi-1);//畫點3
break;
case 3:
LCD_Clear(WHITE);//清屏?
while(!Penirq);? //等待松手
Drow_Touch_Point(lcddev.width-tp_pianyi-1,lcddev.height-tp_pianyi-1);//畫點4
break;
case 4:? ? ?//全部四個點已經得到
LCD_Clear(WHITE);//清屏?
while(!Penirq);? //等待松手
#if USE_HORIZONTAL==1
vx1=p[1].y>p[0].y?(p[1].y-p[0].y+1)*1000/(lcddev.width-tp_pianyi-tp_pianyi):(p[0].y-p[1].y-1)*1000/(lcddev.width-tp_pianyi-tp_pianyi);
chx1=p[1].y>p[0].y?p[0].y-(vx1*tp_pianyi)/1000:p[1].y-(vx1*tp_pianyi)/1000;
vy1=p[2].x>p[0].x?(p[2].x-p[0].x-1)*1000/(lcddev.height-tp_pianyi-tp_pianyi):(p[0].x-p[2].x-1)*1000/(lcddev.height-tp_pianyi-tp_pianyi);
chy1=p[2].x>p[0].x?p[2].x+(vy1*tp_pianyi)/1000:p[0].x+(vy1*tp_pianyi)/1000;?
vx2=p[3].y>p[2].y?(p[3].y-p[2].y+1)*1000/(lcddev.width-tp_pianyi-tp_pianyi):(p[2].y-p[3].y-1)*1000/(lcddev.width-tp_pianyi-tp_pianyi);
chx2=p[3].y>p[2].y?p[2].y-(vx2*tp_pianyi)/1000:p[3].y-(vx2*tp_pianyi)/1000;
vy2=p[3].x>p[1].x?(p[3].x-p[1].x-1)*1000/(lcddev.height-tp_pianyi-tp_pianyi):(p[1].x-p[3].x-1)*1000/(lcddev.height-tp_pianyi-tp_pianyi);
chy2=p[3].x>p[1].x?p[3].x+(vy2*tp_pianyi)/1000:p[1].x+(vy2*tp_pianyi)/1000;?
#elif USE_HORIZONTAL==0
vx1=p[1].x>p[0].x?(p[1].x-p[0].x+1)*1000/(lcddev.width-tp_pianyi-tp_pianyi):(p[0].x-p[1].x-1)*1000/(lcddev.width-tp_pianyi-tp_pianyi);
chx1=p[1].x>p[0].x?p[1].x+(vx1*tp_pianyi)/1000:p[0].x+(vx1*tp_pianyi)/1000;
vy1=p[2].y>p[0].y?(p[2].y-p[0].y-1)*1000/(lcddev.height-tp_pianyi-tp_pianyi):(p[0].y-p[2].y-1)*1000/(lcddev.height-tp_pianyi-tp_pianyi);
chy1=p[2].y>p[0].y?p[0].y-(vy1*tp_pianyi)/1000:p[2].y-(vy1*tp_pianyi)/1000;?
vx2=p[3].x>p[2].x?(p[3].x-p[2].x+1)*1000/(lcddev.width-tp_pianyi-tp_pianyi):(p[2].x-p[3].x-1)*1000/(lcddev.width-tp_pianyi-tp_pianyi);
chx2=p[3].x>p[2].x?p[3].x+(vx2*tp_pianyi)/1000:p[2].x+(vx2*tp_pianyi)/1000;
vy2=p[3].y>p[1].y?(p[3].y-p[1].y-1)*1000/(lcddev.height-tp_pianyi-tp_pianyi):(p[1].y-p[3].y-1)*1000/(lcddev.height-tp_pianyi-tp_pianyi);
chy2=p[3].y>p[1].y?p[1].y-(vy2*tp_pianyi)/1000:p[3].y-(vy2*tp_pianyi)/1000;?
#endif
? ? ? ? ? ? ? ? ? ? if((vx1>vx2&&vx1>vx2+tp_xiaozhun)||(vx1<vx2&&vx1<vx2-tp_xiaozhun)||(vy1>vy2&&vy1>vy2+tp_xiaozhun)||(vy1<vy2&&vy1<vy2-tp_xiaozhun))
{
cnt=0;
LCD_Clear(WHITE);//清屏?
Drow_Touch_Point(tp_pianyi,tp_pianyi);//畫點1?
continue;
}
#if USE_HORIZONTAL==1
vx=(vy1+vy2)/2;vy=(vx1+vx2)/2;
chx=(chy1+chy2)/2;chy=(chx1+chx2)/2;? ??
#elif USE_HORIZONTAL==0
vx=(vx1+vx2)/2;vy=(vy1+vy2)/2;
chx=(chx1+chx2)/2;chy=(chy1+chy2)/2;? ??
#endif
//顯示校準信息
LCD_Clear(WHITE);//清屏?
POINT_COLOR=BLACK;
BACK_COLOR=BLUE;? ??
lx=50;ly=50;? ? ? ? ? ??
LCD_ShowString(lx,ly,16,"VX:",1);lx+=40;LCD_ShowNum(lx,ly,vx,6,16);? ? ? ? ? ? ? ? ? ??
lx=50;ly+=20;
LCD_ShowString(lx,ly,16,"Vy:",1);lx+=40;LCD_ShowNum(lx,ly,vy,6,16);? ? ? ? ? ? ? ? ? ??
lx=50;ly+=20;?
LCD_ShowString(lx,ly,16,"CHX:",1);lx+=40;LCD_ShowNum(lx,ly,chx,6,16);? ? ? ? ? ? ? ? ? ??
lx=50;ly+=20;?
LCD_ShowString(lx,ly,16,"CHY:",1);lx+=40;LCD_ShowNum(lx,ly,chy,6,16);
? ? ? ? ? ? ? ? ? ? lx=30;ly+=30;
LCD_ShowString(lx,ly,16,"Adjust OK!",1);? ??
lx=30;ly+=30;
LCD_ShowString(lx,ly,16,"Touch Anywhere To Continue",1);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
Read_TP_Once(); //等待任意鍵后繼續
? ? ? ? ? ? ? ? ? ? LCD_Clear(WHITE);//清屏
return;//校正完成? ? ? ? ? ? ? ? ?
}
}
}?
}