Ai8051 2.4寸320*240 ILI9341 I8080接口驅動

/*---------------------------------------------------------------------*/
/* --- 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;//校正完成? ? ? ? ? ? ? ? ?
}
}
}?
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/921466.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/921466.shtml
英文地址,請注明出處:http://en.pswp.cn/news/921466.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

最大似然估計:損失函數的底層數學原理

引言當你第一次看到線性回歸時&#xff0c;你是否注意到了作為參數優化關鍵的損失函數&#xff08;均方損失&#xff09;&#xff0c;你是否能夠理解它的本質和由來。其實&#xff0c;在我第一次接觸時&#xff0c;我是感到有些驚訝的&#xff0c;然后試著去強行理解它&#xf…

使用 n8n 結合通義千問大模型構建業務數據庫分析智能體

一、項目概述 本項目致力于構建一個結合 n8n 工作流引擎 與 通義千問大模型 的智能體&#xff0c;旨在對龐大的業務數據庫進行自動化分析、語義建模及自然語言問答。通過不同工作流的迭代構建&#xff0c;實現了表結構解析、業務含義提取、關系可視化、問答服務等能力&#xff…

css margin外邊距重疊/塌陷問題

一、定義 相鄰塊級元素或父子元素的垂直外邊距會合并&#xff08;折疊&#xff09;為單個邊距&#xff0c;其大小為單個邊距的最大值&#xff08;或如果他們相等&#xff0c;則僅為其中的一個&#xff09;&#xff0c;這種行為稱為邊距折疊 <div style"margin-bottom: …

可重復讀 是否“100%”地解決幻讀?

這是一個非常深刻的問題&#xff0c;答案是&#xff1a;幾乎解決了&#xff0c;但在一個非常特殊且罕見的邊界場景下&#xff0c;理論上仍然可能出現幻讀。 因此&#xff0c;嚴格來說&#xff0c;它并非被“徹底”或“100%”地解決。下面我們來詳細分解這個結論&#xff1a;1. …

從零開始的云計算生活——第五十八天,全力以赴,Jenkins部署

目錄 一.故事背景 二.安裝Jenkins必要插件 1.安裝Publish Over SSH 2.安裝maven integration插件 3. 配置jenkins并發執行數量 4. 配置郵件地址 三. 基于Jenkins部署PHP環境 1. 下載ansible插件 2. 下載ansible應用 3. 構建項目 ?編輯 使用Jenkins賬戶生成ssh密鑰 …

串口HAL庫發送問題

想了很久&#xff0c;不知道該標題起的是否合適&#xff0c;該篇Blog用于記錄在使用HAL庫的USART模塊時實際遇到的一個涉及發送方式的問題&#xff0c;用于提醒自身同時也希望能幫到各位。程序問題敘述先來看一段代碼&#xff1a;void CusUSART_SendByte_IT( uint8_t Byte ) { …

CUDA默認流的同步行為

默認流 對于需要指定 cudaStream_t參數的 cuda API&#xff0c;如果將 0作為實參傳入&#xff0c;則視為使用默認流&#xff1b;對于不需要指定 cudaStream_t參數的 cuda API&#xff0c;則也視為使用默認流。 在 cuda中&#xff0c;默認流有兩種類型&#xff0c;一種是 legacy…

「數據獲取」《中國電力統計年鑒》(1993-2024)(含中國電力年鑒)

01、數據簡介一、《中國電力統計年鑒》作為全面系統反映中國電力領域發展狀況的權威性年度統計資料&#xff0c;涵蓋了電力建設、生產、消費及供需等全鏈條關鍵信息。其編制工作有著深厚的歷史積淀&#xff0c;可追溯至 20 世紀 50 年代&#xff0c;歷經數十年的積累與完善&…

《AI大模型應知應會100篇》第68篇:移動應用中的大模型功能開發 —— 用 React Native 打造你的語音筆記摘要 App

&#x1f4f1; 第68篇&#xff1a;移動應用中的大模型功能開發 —— 用 React Native 打造你的語音筆記摘要 App &#x1f3af; 核心目標&#xff1a;零門檻集成大模型&#xff0c;5步開發跨平臺智能功能 &#x1f9e9; 適用人群&#xff1a;前端開發者、產品經理、獨立開發者 …

FPGA ad9248驅動

ad9248的最高時鐘頻率65mhz&#xff0c;采用cmos3.3v電壓的并行io接口&#xff0c;做成電子模塊后一般為雙通道adc&#xff0c;有兩個對外輸出時鐘cha_clk與chb_clk&#xff0c;一個并行輸入端口&#xff0c;14分辨率的ddr_data&#xff0c;其模塊邏輯如下&#xff0c;首先向ad…

Spring MVC 處理請求的流程

Spring MVC 處理請求的流程流程步驟詳解第1步&#xff1a;發起請求 (HTTP Request)第2步&#xff1a;映射處理器 (Handler Mapping)第3步&#xff1a;獲取適配器 (Handler Adapter)第4步&#xff1a;執行攔截器前置處理 (Interceptors - preHandle)第5步&#xff1a;真正調用處…

敏捷scrum管理實戰經驗總結

1.敏捷 敏捷的構成 敏捷由實踐來源、應用場景、組織文化、領導力、團隊、需求、管理、技術、質量、度量、交付、過程改進、大型項目組合管理以及受監管行業中的敏捷等構成 敏捷開發的特點 短發布周期小批量的方式、開展從需求到實現的開發工作高層級的預先規劃結合詳細的即時規…

南科大適應、協同與規劃的完美融合!P3:邁向多功能的具身智能體

作者&#xff1a;Shengli Zhou1^{1}1, Xiangchen Wang1^{1}1, Jinrui Zhang1^{1}1, Ruozai Tian2^{2}2, Rongtao Xu2,3^{2,3}2,3, Feng Zheng1,2^{1,2}1,2單位&#xff1a;1^{1}1南方科技大學&#xff0c;2^{2}2時空智能&#xff0c;3^{3}3穆罕默德本扎耶德人工智能大學論文標題…

自動化流水線

import React, { useState, useEffect } from ‘react’; import { ChevronRight, CheckCircle, Circle, AlertCircle, Clock, Play, Pause, Settings, Code, Server, Shield, Database, Globe, Zap, FileText, Users, GitBranch, Package, Monitor, ChevronDown } from ‘luci…

【高等數學】第十一章 曲線積分與曲面積分——第三節 格林公式及其應用

上一節&#xff1a;【高等數學】第十一章 曲線積分與曲面積分——第二節 對坐標的曲線積分 總目錄&#xff1a;【高等數學】 目錄 文章目錄1. 格林公式2. 平面上曲線積分與路徑無關的條件3. 二元函數的全微分求積4. 曲線積分的基本定理1. 格林公式 單連通與復連通區域 設 DDD …

Boost電路:平均狀態空間建模

電路特征介紹如圖所示是一個非理想情況下的boost電路&#xff0c;其中L1L_{1}L1?和RL1R_{L1}RL1?是分別是電感和串聯電阻&#xff1b;C1C_{1}C1?和RC1R_{C1}RC1?是輸出電容和串聯電阻&#xff1b;Q1Q_{1}Q1?是MOS管&#xff0c;其導通電阻是RonR_{on}Ron?&#xff1b;D1D…

免費網站模板/網站模板建站的優勢/如何下載網站模板搭建網站?

在網站建設領域&#xff0c;“網站模板” 是降低技術門檻、提升建站效率的核心工具&#xff0c;尤其適合非專業開發者或追求低成本、快上線的需求場景。下面從定義、核心優勢兩方面展開詳細解析&#xff0c;幫助你全面理解其價值。 一、什么是網站模板&#xff1f; 網站模板&am…

【MATLAB例程】平面上的組合導航例程,使用EKF融合IMU和GNSS數據,8維狀態量和2維觀測量,附代碼下載鏈接

文章目錄程序詳解概述系統架構核心數學模型性能評估算法特點運行結果MATLAB源代碼程序詳解 概述 本代碼實現基于擴展卡爾曼濾波器&#xff08;EKF&#xff09;的二維組合導航系統&#xff0c;融合IMU&#xff08;慣性測量單元&#xff09;和GNSS&#xff08;全球導航衛星系統…

react生命周期,詳細版本

React 組件的生命周期分為三個階段:掛載(Mounting)、更新(Updating) 和 卸載(Unmounting)。以下是類組件生命周期的詳細說明(基于 React 16.3+ 版本): 一、掛載階段(Mounting) 組件實例被創建并插入 DOM 時的流程: constructor(props) ○ 用途:初始化狀態(this…

騰訊最新開源HunyuanVideo-Foley本地部署教程:端到端TV2A框架,REPA策略+MMDiT架構,重新定義視頻音效新SOTA!

一、模型介紹HunyuanVideo-Foley 是騰訊混元團隊在2025年8月底開源的一款端到端視頻音效生成模型。它旨在解決AI生成視頻“有畫無聲”的痛點&#xff0c;通過輸入視頻和文本描述&#xff0c;就能自動生成電影級別的同步音效&#xff0c;顯著提升視頻的沉浸感。它是專為視頻內容…