一、用STM32控制TFTLCD顯示的編程方法,在編程驅動TFTLCD液晶顯示器之前,我們先熟悉以下概念:
1、色彩深度,這是一個與TFTLCD顯存對應的概念;所謂色彩深度就是每個像素點需要多少位的RGB
數據表示該點的顏色信息。注意,不同的TFTLCD顯示器的RGB的對應關系不一樣,這個可以在LCD
控制芯片手冊中找到答案。
例: 某LCD顯示支持8、16、24位RGB,這些位數是指該像素點顏色由8、16、24位RGB構成,但是
R\G\B三種顏色各占的位數可以查看數據手冊。
2、TFTLCD的操作分為兩種:
A、對控制寄存器的讀寫操作(即程序員將要操作LCD顯存寄存器的地址設置成可讀或者可寫)。
B、對顯存寄存器的讀寫操作(即讀寫LCD顯存寄存器)。
3、TFTLCD有一個索引寄存器,對控制寄存器操作前,需要對索引寄存器進行定入操作,用以指明
寄存器讀寫是針對那個寄存器的,具體操作步驟如下:
RS為低電平狀態下,寫入兩個字節的數據,第一個字節為零,第二個字節為寄存器索引值。
RS為高電平狀態下,讀取兩個字節數據,第一個字節為高八位,第二個字節為低八位。
二、實驗平臺STM32F103RCT6與ILI9341 TFTLCD驅動模塊
硬件采用 16 位的并方式與外部連接,之所以不采用 8 位的方式,是因為彩屏的數據量比較大,
尤其在顯示圖片的時候,如果用 8 位數據線,就會比 16 位方式慢一倍以上,我們當然希望速
度越快越好,所以我們選擇 16 位的 80 并口。有如下一些信號線:
CS:TFTLCD 片選信號。
WR:向 TFTLCD 寫入數據。
RD:從 TFTLCD 讀取數據。
D[15:0]:16 位雙向數據線。
RST:硬復位 TFTLCD。
RS:命令/數據標志(0,讀寫命令;1,讀寫數據)。
在 16 位模式下,ILI9341 采用 RGB565 格式存儲顏色數據,接下來看一下ILI9341 的幾個重要命令
1、 0XD3,用于讀取 LCD 控制器的 ID。
2、0X36,這是存儲訪問控制指令,可以控制 ILI9341 存儲器的讀寫方向,簡單的說,就是在連續寫
GRAM 的時候,可以控制 GRAM 指針的增長方向,從而控制顯示方式。
3、0X2A,這是列地址設置指令,在從左到右,從上到下的掃描方式(默認)下面,該指令用于設置
橫坐標(x 坐標)。
4、0X2B,是頁地址設置指令,在從左到右,從上到下的掃描方式(默認)下面,該指令用于設置縱
坐標(y 坐標)。
5、0X2C,該指令是寫 GRAM 指令,在發送該指令之后,我們便可以往 LCD的 GRAM 里面寫入顏色
數據了,該指令支持連續寫,在收到指令 0X2C 之后,數據有效位寬變為 16 位,我們可以連續寫入
LCD GRAM 值,而 GRAM 的地址將根據 MY/MX/MV 設置的掃描方向進行自增。
6、 0X2E, 該指令是讀 GRAM 指令,用于讀取 ILI9341 的顯存(GRAM)。
三、軟件編程
lcd.h 里面的一個重要結構體:
//LCD重要參數集
typedef struct
{
u16 width;//LCD 寬度
u16 height;//LCD 高度
u16 id;//LCD ID
u8 dir;//橫屏還是豎屏控制:0,豎屏;1,橫屏。
u16wramcmd;//開始寫gram指令
u16 setxcmd;//設置x坐標指令
u16 setycmd;//設置y坐標指令
}_lcd_dev;
//LCD參數
extern _lcd_dev lcddev; //管理LCD重要參數
該結構體用于保存一些 LCD 重要參數信息,比如 LCD 的長寬、LCD ID(驅動 IC 型號)、
LCD 橫豎屏狀態等,這個結構體雖然占用了 14 個字節的內存,但是卻可以讓我們的驅動函數
支持不同尺寸的 LCD,同時可以實現 LCD 橫豎屏切換等重要功能,所以還是利大于弊的。有
了以上了解,下面我們開始介紹 ILI93xx.c 里面的一些重要函數。
第一個是 LCD_WR_DATA 函數,該函數在 lcd.h 里面,通過宏定義的方式申明。該函數通
過 80 并口向 LCD 模塊寫入一個 16 位的數據,使用頻率是最高的,這里我們采用了宏定義的方
式,以提高速度。其代碼如下
//寫數據函數
#define LCD_WR_DATA(data){\
LCD_RS_SET;\
LCD_CS_CLR;\
DATAOUT(data);\
LCD_WR_CLR;\
LCD_WR_SET;\
LCD_CS_SET;\
}
//寫數據函數
//可以替代LCD_WR_DATAX宏,拿時間換空間.
//data:寄存器值
void LCD_WR_DATAX(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
第三個是 LCD_WR_REG 函數,該函數是通過 8080 并口向 LCD 模塊寫入寄存器命令,因
為該函數使用頻率不是很高,我們不采用宏定義來做(宏定義占用 FLASH 較多),通過 LCD_RS
來標記是寫入命令(LCD_RS=0)還是數據(LCD_RS=1)。該函數代碼如下:
//寫寄存器函數
//data:寄存器值
void LCD_WR_REG(u16 data)
{
LCD_RS_CLR;//寫地址
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
既然有寫寄存器命令函數,那就有讀寄存器數據函數。接下來介紹 LCD_RD_DATA 函數,
該函數用來讀取 LCD 控制器的寄存器數據(非 GRAM 數據),該函數代碼如下:
//讀LCD數據
//返回值:讀到的值
u16 LCD_RD_DATA(void)
{
u16 t;
GPIOB->CRL=0X88888888; //PB0-7 上拉輸入
GPIOB->CRH=0X88888888; //PB8-15 上拉輸入
GPIOB->ODR=0X0000; //全部輸出0
LCD_RS_SET;
LCD_CS_CLR;
//讀取數據(讀寄存器時,并不需要讀2次)
LCD_RD_CLR;
if(lcddev.id==0X8989)delay_us(2);//FOR 8989,延時2us
t=DATAIN;
LCD_RD_SET;
LCD_CS_SET;
GPIOB->CRL=0X33333333; //PB0-7 上拉輸出
GPIOB->CRH=0X33333333; //PB8-15 上拉輸出
GPIOB->ODR=0XFFFF; //全部輸出高
return t;
}
以上 4 個函數,用于實現 LCD 基本的讀寫操作,接下來,我們介紹 2 個 LCD 寄存器操作
的函數,LCD_WriteReg 和 LCD_ReadReg,這兩個函數代碼如下:
//寫寄存器
//寫寄存器
//LCD_Reg:寄存器編號
//LCD_RegValue:要寫入的值
void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
}
//讀寄存器
//LCD_Reg:寄存器編號
//返回值:讀到的值
u16 LCD_ReadReg(u16 LCD_Reg)
{
LCD_WR_REG(LCD_Reg); //寫入要讀的寄存器號
return LCD_RD_DATA();
}
這兩個函數函數十分簡單,LCD_WriteReg 用于向 LCD 指定寄存器寫入指定數據,而
LCD_ReadReg 則用于讀取指定寄存器的數據,這兩個函數,都只帶一個參數/返回值,所以,
在有多個參數操作(讀取/寫入)的時候,就不適合用這兩個函數了,得另外實現。
第七個要介紹的函數是坐標設置函數,該函數代碼如下:
//設置光標位置
//Xpos:橫坐標
//Ypos:縱坐標
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
if(lcddev.id==0X9341||lcddev.id==0X5310)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
}else if(lcddev.id==0X6804)
{
if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//橫屏時處理
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
}else if(lcddev.id==0X5510)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_REG(lcddev.setxcmd+1);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_REG(lcddev.setycmd+1);
LCD_WR_DATA(Ypos&0XFF);
}else
{
if(lcddev.dir==1) Xpos=lcddev.width-1-Xpos;//橫屏其實就是調轉x,y坐標
LCD_WriteReg(lcddev.setxcmd, Xpos);
LCD_WriteReg(lcddev.setycmd, Ypos);
}
}
該函數實現將 LCD 的當前操作點設置到指定坐標(x,y)。因為不同 LCD 的設置方式不一定
完全一樣,所以代碼里面有好幾個判斷,對不同的驅動 IC 進行不同的設置。
接下來我們介紹第八個函數:畫點函數。該函數實現代碼如下:
//畫點
//x,y:坐標
//POINT_COLOR:此點的顏色
void LCD_DrawPoint(u16 x,u16 y)
{
LCD_SetCursor(x,y);//設置光標位置
LCD_WriteRAM_Prepare();//開始寫入GRAM
LCD_WR_DATA(POINT_COLOR);
}
該函數實現比較簡單,就是先設置坐標,然后往坐標寫顏色。其中 POINT_COLOR 是我們
定義的一個全局變量,用于存放畫筆顏色,順帶介紹一下另外一個全局變量: BACK_COLOR,
該變量代表 LCD 的背景色。LCD_DrawPoint 函數雖然簡單,但是至關重要,其他幾乎所有上
層函數,都是通過調用這個函數實現的。
有了畫點,當然還需要有讀點的函數,第九個介紹的函數就是讀點函數,用于讀取 LCD
的 GRAM, 這里說明一下,為什么 OLED 模塊沒做讀 GRAM 的函數,而這里做了。因為 OLED
模塊是單色的,所需要全部 GRAM 也就 1K 個字節,而 TFTLCD 模塊為彩色的,點數也比 OLED
模塊多很多,以 16 位色計算, 一款 320×240 的液晶,需要 320×240×2 個字節來存儲顏色值,
也就是也需要 150K 字節,這對任何一款單片機來說,都不是一個小數目了。而且我們在圖形
疊加的時候,可以先讀回原來的值,然后寫入新的值,在完成疊加后,我們又恢復原來的值。
這樣在做一些簡單菜單的時候,是很有用的。這里我們讀取 TFTLCD 模塊數據的函數為
LCD_ReadPoint,該函數直接返回讀到的 GRAM 值。該函數使用之前要先設置讀取的 GRAM
地址,通過 LCD_SetCursor 函數來實現。LCD_ReadPoint 的代碼如下:
//讀取個某點的顏色值
//x,y:坐標
//返回值:此點的顏色
u16 LCD_ReadPoint(u16 x,u16 y)
{
u16 r,g,b;
if(x>=lcddev.width||y>=lcddev.height)return 0;//超過了范圍,直接返回
LCD_SetCursor(x,y);
if(lcddev.id==0X9341||lcddev.id==0X6804||lcddev.id==0X5310)LCD_WR_REG(0X2E);//9341/6804/5310發送讀GRAM指令
else if(lcddev.id==0X5510)LCD_WR_REG(0X2E00);//5510 發送讀GRAM指令
else LCD_WR_REG(R34); //其他IC發送讀GRAM指令
GPIOB->CRL=0X88888888; //PB0-7 上拉輸入
GPIOB->CRH=0X88888888; //PB8-15 上拉輸入
GPIOB->ODR=0XFFFF; //全部輸出高
LCD_RS_SET;
LCD_CS_CLR;
//讀取數據(讀GRAM時,第一次為假讀)
LCD_RD_CLR;
delay_us(1);//延時1us
LCD_RD_SET;
//dummy READ
LCD_RD_CLR;
delay_us(1);//延時1us
r=DATAIN; //實際坐標顏色
LCD_RD_SET;
if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510)//9341/NT35310/NT35510要分2次讀出
{
LCD_RD_CLR;
b=DATAIN;//讀取藍色值
LCD_RD_SET;
g=r&0XFF;//對于9341,第一次讀取的是RG的值,R在前,G在后,各占8位
g<<=8;
}else if(lcddev.id==0X6804)
{
LCD_RD_CLR;
LCD_RD_SET;
r=DATAIN;//6804第二次讀取的才是真實值
}
LCD_CS_SET;
GPIOB->CRL=0X33333333; //PB0-7 上拉輸出
GPIOB->CRH=0X33333333; //PB8-15 上拉輸出
GPIOB->ODR=0XFFFF; //全部輸出高
if(lcddev.id==0X9325||lcddev.id==0X4535||lcddev.id==0X4531||lcddev.id==0X8989||lcddev.id==0XB505)
return r;//這幾種IC直接返回顏色值
else if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510)
return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));//ILI9341/NT35310/NT35510需要公式轉換一下
else return LCD_BGR2RGB(r);//其他IC
}
在 LCD_ReadPoint 函數中,因為我們的代碼不止支持一種 LCD 驅動器,所以,我們根據
不同的 LCD 驅動器((lcddev.id)型號,執行不同的操作,以實現對各個驅動器兼容,提高函數
的通用性。
第十個要介紹的是字符顯示函數 LCD_ShowChar,該函數同前面 OLED 模塊的字符顯示函
數差不多,但是這里的字符顯示函數多了一個功能,就是可以以疊加方式顯示,或者以非疊加
方式顯示。疊加方式顯示多用于在顯示的圖片上再顯示字符。非疊加方式一般用于普通的顯示。
該函數實現代碼如下:
//在指定位置顯示一個字符
//x,y:起始坐標
//num:要顯示的字符:" "--->"~"
//size:字體大小 12/16/24
//mode:疊加方式(1)還是非疊加方式(0)
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
{
u8 temp,t1,t;
u16 y0=y;
u8 csize=(size/8+((size%8)?1:0))*(size/2);//得到字體一個字符對應點陣集所占的字節數
//設置窗口
num=num-' ';//得到偏移后的值
for(t=0;t
if(size==12)temp=asc2_1206[num][t]; //調用1206字體
else if(size==16)temp=asc2_1608[num][t];//調用1608字體
else if(size==24)temp=asc2_2412[num][t];//調用2412字體
else return; //沒有的字庫
for(t1=0;t1<8;t1++)
{
if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR);
else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR);
temp<<=1;
y++;
if(x>=lcddev.width)return;//超區域了
if((y-y0)==size)
{
y=y0;
x++;
if(x>=lcddev.width)return;//超區域了
break;
}
}
}
}
在 LCD_ShowChar 函數里面,我們采用快速畫點函數 LCD_Fast_DrawPoint 來畫點顯示字
符,該函數同 LCD_DrawPoint 一樣,只是帶了顏色參數,且減少了函數調用的時間,詳見本例
程源碼。
最后,我們再介紹一下 TFTLCD 模塊的初始化函數 LCD_Init,該函數先初始化 STM32 與
TFTLCD 連接的 IO 口,并配置 FSMC 控制器,然后讀取 LCD 控制器的型號,根據控制 IC 的
型號執行不同的初始化代碼,其簡化代碼如下:
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能PORTB,C時鐘和AFIO時鐘
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);//開啟SWD,失能JTAG
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6; ///PORTC6~10復用推挽輸出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;// PORTB推挽輸出
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_All);
delay_ms(50); // delay 50 ms
LCD_WriteReg(0x0000,0x0001);
delay_ms(50); // delay 50 ms
lcddev.id = LCD_ReadReg(0x0000);
if(lcddev.id<0XFF||lcddev.id==0XFFFF||lcddev.id==0X9300)//讀到ID不正確,新增lcddev.id==0X9300判斷,因為9341在未被復位的情況下會被讀成9300
{
//嘗試9341 ID的讀取
LCD_WR_REG(0XD3);
LCD_RD_DATA(); //dummy read
LCD_RD_DATA(); //讀到0X00
lcddev.id=LCD_RD_DATA(); //讀取93
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //讀取41
if(lcddev.id!=0X9341)//非9341,嘗試是不是6804
{
LCD_WR_REG(0XBF);
LCD_RD_DATA(); //dummy read
LCD_RD_DATA(); //讀回0X01
LCD_RD_DATA(); //讀回0XD0
lcddev.id=LCD_RD_DATA();//這里讀回0X68
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA();//這里讀回0X04
if(lcddev.id!=0X6804)//也不是6804,嘗試看看是不是NT35310
{
LCD_WR_REG(0XD4);
LCD_RD_DATA(); //dummy read
LCD_RD_DATA(); //讀回0X01
lcddev.id=LCD_RD_DATA();//讀回0X53
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA();//這里讀回0X10
if(lcddev.id!=0X5310)//也不是NT35310,嘗試看看是不是NT35510
{
LCD_WR_REG(0XDA00);
LCD_RD_DATA(); //讀回0X00
LCD_WR_REG(0XDB00);
lcddev.id=LCD_RD_DATA();//讀回0X80
lcddev.id<<=8;
LCD_WR_REG(0XDC00);
lcddev.id|=LCD_RD_DATA();//讀回0X00
if(lcddev.id==0x8000)lcddev.id=0x5510;//NT35510讀回的ID是8000H,為方便區分,我們強制設置為5510
}
}
}
}
printf(" LCD ID:%x\r\n",lcddev.id); //打印LCD ID
if(lcddev.id==0X9341)//9341初始化
{
LCD_WR_REG(0xCF);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0xC1);
LCD_WR_DATAX(0X30);
LCD_WR_REG(0xED);
LCD_WR_DATAX(0x64);
LCD_WR_DATAX(0x03);
LCD_WR_DATAX(0X12);
LCD_WR_DATAX(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATAX(0x85);
LCD_WR_DATAX(0x10);
LCD_WR_DATAX(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATAX(0x39);
LCD_WR_DATAX(0x2C);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x34);
LCD_WR_DATAX(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATAX(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATAX(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control
LCD_WR_DATAX(0x01); //SAP[2:0];BT[3:0]
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATAX(0x30); //3F
LCD_WR_DATAX(0x30); //3C
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATAX(0XB7);
LCD_WR_REG(0x36); // Memory Access Control
LCD_WR_DATAX(0x48);
LCD_WR_REG(0x3A);
LCD_WR_DATAX(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x1A);
LCD_WR_REG(0xB6); // Display Function Control
LCD_WR_DATAX(0x0A);
LCD_WR_DATAX(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable
LCD_WR_DATAX(0x00);
LCD_WR_REG(0x26); //Gamma curve selected
LCD_WR_DATAX(0x01);
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x2A);
LCD_WR_DATAX(0x28);
LCD_WR_DATAX(0x08);
LCD_WR_DATAX(0x0E);
LCD_WR_DATAX(0x08);
LCD_WR_DATAX(0x54);
LCD_WR_DATAX(0XA9);
LCD_WR_DATAX(0x43);
LCD_WR_DATAX(0x0A);
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x15);
LCD_WR_DATAX(0x17);
LCD_WR_DATAX(0x07);
LCD_WR_DATAX(0x11);
LCD_WR_DATAX(0x06);
LCD_WR_DATAX(0x2B);
LCD_WR_DATAX(0x56);
LCD_WR_DATAX(0x3C);
LCD_WR_DATAX(0x05);
LCD_WR_DATAX(0x10);
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x3F);
LCD_WR_DATAX(0x3F);
LCD_WR_DATAX(0x0F);
LCD_WR_REG(0x2B);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x01);
LCD_WR_DATAX(0x3f);
LCD_WR_REG(0x2A);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0xef);
LCD_WR_REG(0x11); //Exit Sleep
delay_ms(120);
LCD_WR_REG(0x29); //display on
}
LCD_Display_Dir(0);//默認為豎屏
LCD_LED=1; //點亮背光
LCD_Clear(WHITE);
}
//LCD重要參數集
typedef struct
{
u16 width; //LCD 寬度
u16 height; //LCD 高度
u16 id; //LCD ID
u8 dir; //橫屏還是豎屏控制:0,豎屏;1,橫屏。
u16 wramcmd;//開始寫gram指令
u16 setxcmd; //設置x坐標指令
u16 setycmd; //設置y坐標指令
}_lcd_dev;
//LCD參數
extern _lcd_dev lcddev; //管理LCD重要參數
//LCD的畫筆顏色和背景色
extern u16 POINT_COLOR;//默認紅色
extern u16 BACK_COLOR; //背景顏色.默認為白色
////////////////////////////////////////////////////////////////////
//-----------------LCD端口定義----------------
#define LCD_LED PCout(10) //LCD背光 PC10
/*
#define LCD_CS_SET GPIOC->BSRR=1<<9 //片選端口 PC9
#define LCD_RS_SETGPIOC->BSRR=1<<8 //數據/命令 PC8
#define LCD_WR_SETGPIOC->BSRR=1<<7 //寫數據 PC7
#define LCD_RD_SETGPIOC->BSRR=1<<6 //讀數據 PC6
#define LCD_CS_CLR GPIOC->BRR=1<<9 //片選端口 PC9
#define LCD_RS_CLRGPIOC->BRR=1<<8 //數據/命令 PC8
#define LCD_WR_CLRGPIOC->BRR=1<<7 //寫數據 PC7
#define LCD_RD_CLRGPIOC->BRR=1<<6 //讀數據 PC6
*/
#define LCD_CS_SET GPIO_SetBits(GPIOC,GPIO_Pin_9) //片選端口 PC9
#define LCD_RS_SETGPIO_SetBits(GPIOC,GPIO_Pin_8) //數據/命令 PC8
#define LCD_WR_SETGPIO_SetBits(GPIOC,GPIO_Pin_7) //寫數據 PC7
#define LCD_RD_SETGPIO_SetBits(GPIOC,GPIO_Pin_6) //讀數據 PC6
#define LCD_CS_CLR GPIO_ResetBits(GPIOC,GPIO_Pin_9) //片選端口 PC9
#define LCD_RS_CLRGPIO_ResetBits(GPIOC,GPIO_Pin_8) //數據/命令PC8
#define LCD_WR_CLRGPIO_ResetBits(GPIOC,GPIO_Pin_7) //寫數據 PC7
#define LCD_RD_CLRGPIO_ResetBits(GPIOC,GPIO_Pin_6) //讀數據 PC6
//PB0~15,作為數據線
//#define DATAOUT(x) GPIOB->ODR=x; //數據輸出
//#define DATAIN GPIOB->IDR; //數據輸入
#define DATAOUT(x) GPIO_Write(GPIOB,x);
#define DATAIN GPIO_ReadInputData(GPIOB)
//////////////////////////////////////////////////////////////////////
//掃描方向定義
#define L2R_U2D 0 //從左到右,從上到下
#define L2R_D2U 1 //從左到右,從下到上
#define R2L_U2D 2 //從右到左,從上到下
#define R2L_D2U 3 //從右到左,從下到上
#define U2D_L2R 4 //從上到下,從左到右
#define U2D_R2L 5 //從上到下,從右到左
#define D2U_L2R 6 //從下到上,從左到右
#define D2U_R2L 7 //從下到上,從右到左
#define DFT_SCAN_DIR L2R_U2D //默認的掃描方向
//掃描方向定義
#define L2R_U2D 0 //從左到右,從上到下
#define L2R_D2U 1 //從左到右,從下到上
#define R2L_U2D 2 //從右到左,從上到下
#define R2L_D2U 3 //從右到左,從下到上
#define U2D_L2R 4 //從上到下,從左到右
#define U2D_R2L 5 //從上到下,從右到左
#define D2U_L2R 6 //從下到上,從左到右
#define D2U_R2L 7 //從下到上,從右到左
#define DFT_SCAN_DIR L2R_U2D //默認的掃描方向
//畫筆顏色
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕紅色
#define GRAY 0X8430 //灰色
//GUI顏色
#define DARKBLUE 0X01CF//深藍色
#define LIGHTBLUE 0X7D7C//淺藍色
#define GRAYBLUE 0X5458 //灰藍色
//以上三色為PANEL的顏色
#define LIGHTGREEN 0X841F //淺綠色
#define LGRAY 0XC618 //淺灰色(PANNEL),窗體背景色
#define LGRAYBLUE 0XA651 //淺灰藍色(中間層顏色)
#define LBBLUE 0X2B12 //淺棕藍色(選擇條目的反色)
void LCD_Init(void); //初始化
void LCD_DisplayOn(void); //開顯示
void LCD_DisplayOff(void); //關顯示
void LCD_Clear(u16 Color); //清屏
void LCD_SetCursor(u16 Xpos, u16 Ypos); //設置光標
void LCD_DrawPoint(u16 x,u16 y); //畫點
void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color); //快速畫點
u16 LCD_ReadPoint(u16 x,u16 y); //讀點
void LCD_Draw_Circle(u16 x0,u16 y0,u8 r); //畫圓
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2); //畫線
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2); //畫矩形
void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color); //填充單色
void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color);//填充指定顏色
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode);//顯示一個字符
void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size); //顯示一個數字
void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode);//顯示 數字
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p);//顯示一個字符串,12/16字體
void LCD_WriteReg(u16 LCD_Reg, u16 LCD_RegValue);
u16 LCD_ReadReg(u16 LCD_Reg);
void LCD_WriteRAM_Prepare(void);
void LCD_WriteRAM(u16 RGB_Code);
void LCD_Scan_Dir(u8 dir); //設置屏掃描方向
void LCD_Display_Dir(u8 dir); //設置屏幕顯示方向
void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height);//設置窗口
//寫數據函數
#define LCD_WR_DATA(data){\
LCD_RS_SET;\
LCD_CS_CLR;\
DATAOUT(data);\
LCD_WR_CLR;\
LCD_WR_SET;\
LCD_CS_SET;\
}
//9320/9325 LCD寄存器
#define R0 0x00
#define R1 0x01
#define R2 0x02
#define R3 0x03
#define R4 0x04
#define R5 0x05
#define R6 0x06
#define R7 0x07
#define R8 0x08
#define R9 0x09
#define R10 0x0A
#define R12 0x0C
#define R13 0x0D
#define R14 0x0E
#define R15 0x0F
#define R16 0x10
#define R17 0x11
#define R18 0x12
#define R19 0x13
#define R20 0x14
#define R21 0x15
#define R22 0x16
#define R23 0x17
#define R24 0x18
#define R25 0x19
#define R26 0x1A
#define R27 0x1B
#define R28 0x1C
#define R29 0x1D
#define R30 0x1E
#define R31 0x1F
#define R32 0x20
#define R33 0x21
#define R34 0x22
#define R36 0x24
#define R37 0x25
#define R40 0x28
#define R41 0x29
#define R43 0x2B
#define R45 0x2D
#define R48 0x30
#define R49 0x31
#define R50 0x32
#define R51 0x33
#define R52 0x34
#define R53 0x35
#define R54 0x36
#define R55 0x37
#define R56 0x38
#define R57 0x39
#define R59 0x3B
#define R60 0x3C
#define R61 0x3D
#define R62 0x3E
#define R63 0x3F
#define R64 0x40
#define R65 0x41
#define R66 0x42
#define R67 0x43
#define R68 0x44
#define R69 0x45
#define R70 0x46
#define R71 0x47
#define R72 0x48
#define R73 0x49
#define R74 0x4A
#define R75 0x4B
#define R76 0x4C
#define R77 0x4D
#define R78 0x4E
#define R79 0x4F
#define R80 0x50
#define R81 0x51
#define R82 0x52
#define R83 0x53
#define R96 0x60
#define R97 0x61
#define R106 0x6A
#define R118 0x76
#define R128 0x80
#define R129 0x81
#define R130 0x82
#define R131 0x83
#define R132 0x84
#define R133 0x85
#define R134 0x86
#define R135 0x87
#define R136 0x88
#define R137 0x89
#define R139 0x8B
#define R140 0x8C
#define R141 0x8D
#define R143 0x8F
#define R144 0x90
#define R145 0x91
#define R146 0x92
#define R147 0x93
#define R148 0x94
#define R149 0x95
#define R150 0x96
#define R151 0x97
#define R152 0x98
#define R153 0x99
#define R154 0x9A
#define R157 0x9D
#define R192 0xC0
#define R193 0xC1
#define R229 0xE5
#endif
上一篇:FSMC驅動TFTLCD原理,時序和寄存器介紹
下一篇:stm32_19264液晶LCD驅動程序
推薦閱讀
史海拾趣
對于門控夜明燈電路,網友們可能會有多種問題,以下是一些常見問題及其詳細回答:
一、工作原理相關問題
-
問:門控夜明燈電路是如何實現自動開關的?
答: 門控夜明燈電路主要通過門控開關、延遲電路、光控電路和電源電路等幾部分組成。當門打開時,門控開關觸發電路,使電燈點亮。同時,延遲電路控制電燈的點亮時間,一般為幾十秒左右。光控電路則確保在光線較暗的環境下(如夜晚)電路才會工作,而在白天則自動封鎖電路,避免電燈誤亮。 -
問:電路中的光控部分是如何工作的?
答: 電路中的光控部分通常由光敏電阻器(如MG45型)和相關的電子元件組成。光敏電阻器的阻值會隨著光照強度的變化而變化。在白天,由于光照強度大,光敏電阻器呈現低阻值狀態,導致電路中的某個三極管(如VT3)導通,進而封鎖整個電路,使電燈不會點亮。而在夜晚,光照強度減弱,光敏電阻器呈現高阻值狀態,三極管截止,電路恢復正常工作狀態,受門控開關控制。
二、安裝調試相關問題
-
問:如何安裝門控夜明燈電路?
答: 安裝門控夜明燈電路時,首先需要將干簧管安裝在門框上,將小磁鐵安裝在門上,并確保兩者在門關閉時能夠對準并吸合。接著,將電路板固定在合適的位置,并連接好電源線和電燈線。最后,進行電路調試,確保電路能夠正常工作。 -
問:如何調整電燈的點亮時間?
答: 電燈的點亮時間主要由延遲電路中的電阻和電容決定。要調整點亮時間,可以通過改變電阻(如R2)的阻值或電容(如C1)的容量來實現。一般來說,電阻阻值增大或電容容量增大,都會導致點亮時間延長;反之,則點亮時間縮短。
三、故障排除相關問題
-
問:如果電燈不亮,可能是什么原因?
答: 如果電燈不亮,可能是由多種原因造成的。首先,應檢查電源是否正常,以及電路中的保險絲是否熔斷。其次,檢查門控開關是否工作正常,即干簧管和小磁鐵是否能夠在門打開時正確觸發電路。此外,還應檢查光控電路是否因光線過強而處于封鎖狀態。最后,檢查電燈本身是否損壞。 -
問:電燈在白天也會亮,怎么辦?
答: 如果電燈在白天也會亮,可能是光控電路出現了問題。首先,應檢查光敏電阻器是否損壞或受到其他光源的干擾。其次,檢查與光敏電阻器相關的電子元件(如VT3)是否工作正常。如果問題依然存在,可能需要重新調整光控電路的靈敏度或更換相關元件。
四、其他相關問題
-
問:門控夜明燈電路適用于哪些場合?
答: 門控夜明燈電路適用于需要自動照明的各種場合,如家庭玄關、走廊、樓梯間等。它能夠在人們進門時自動點亮電燈,為人們提供方便,同時也能夠節省能源。 -
問:如何選擇合適的電燈與電路匹配?
答: 在選擇電燈與電路匹配時,首先需要考慮電燈的功率和類型。由于門控夜明燈電路通常設計為低功耗電路,因此建議選擇功率較小、發光效率較高的電燈,如LED燈泡。此外,還需要確保電燈的電壓和電流與電路的輸出相匹配,以避免電路損壞或電燈燒毀。
為了進一步擴大市場覆蓋和品牌影響力,福斯特半導體積極尋求戰略合作。2023年2月,福斯特半導體與世強先進(深圳)科技股份有限公司簽署授權代理協議,借助世強先進在技術分銷和互聯網推廣方面的豐富經驗,布局線上和線下功率器件渠道市場。這一合作不僅拓寬了福斯特半導體的產品應用領域,還提升了公司在新能源汽車、儲能、照明等市場的知名度。通過世強硬創平臺,福斯特半導體的功率MOS和二極管等產品得以快速覆蓋目標市場,進一步降低了客戶供應鏈成本。
隨著光伏膠膜業務的快速發展,福斯特面臨著倉庫管理和存儲的巨大挑戰。光伏膠膜成品體積大、重量重,傳統人工作業方式效率低下且勞動強度大。為了應對這一挑戰,福斯特引入了智能倉儲系統,與亨通智能合作打造自動化立庫系統。該系統通過堆垛機、RGV、纏繞膜等設備的配合使用,實現了庫內產品的全面自動化搬運、存儲與管理。這不僅大大提高了倉庫的運營管理效率,還確保了產品的先進先出和庫存盤點的準確性。這一智能化改造不僅提升了福斯特自身的競爭力,也為整個光伏行業的數字化轉型樹立了標桿。
“全球陶瓷”公司憑借其卓越的產品質量和國際化戰略,成功拓展了海外市場。該公司積極參與國際展覽和交流活動,與多國電子企業建立了合作關系。同時,全球陶瓷還針對不同國家和地區的市場需求,推出了定制化的陶瓷電子材料解決方案。這一國際化戰略不僅提升了公司的品牌影響力,也為其在全球范圍內的業務拓展提供了有力支持。
隨著電子技術的快速發展,教育和培訓成為了Global Specialties的另一個重要領域。公司敏銳地捕捉到這一市場需求,推出了一系列針對教育的試驗板和套件。這些產品不僅幫助學生更好地理解電子原理,還激發了他們的創造力和實踐能力。通過與多所高校和職業院校的合作,Global Specialties成功地將自己的品牌深入到教育市場的每一個角落。
在電子行業中,ABC Electronics Inc. 深知單打獨斗難以取得長遠發展。因此,公司積極尋求與其他企業的合作機會,通過技術共享、聯合研發、市場互補等方式實現共贏。例如,公司與一家知名芯片制造商合作,共同開發了一款具有高性能的嵌入式系統解決方案,成功應用于智能家居、工業自動化等領域。這種合作模式不僅加速了產品的研發進程,也提高了公司的市場競爭力。
負載拉移(Load-Pull)原理在射頻功率放大器設計中的應用.pdf 近年來由於微波通訊技術的進步,及通訊頻寬與移動性越來越高的需求,使得無線區域網路(Wireless LAN)在人類日常生活中之重要性大幅提昇,進而帶動產學界紛紛投入此系統電路技術及產品之研發?!? 查看全部問答∨ |
|
目前有個項目,需要請一位工程師(業余兼職即可)。 1、熟悉TI 達芬奇系列DSP芯片,有DM64xx上開發,優化經驗。 2、熟悉H264協議或者MPEG4協議,最好在DM64XX上做過相關協議的開發或者優化工作。 詳細可以QQ455247859聯系。 … 查看全部問答∨ |
|
小弟是DSP初學者,想把simulink的框圖轉化成c代碼,在DSP上跑.我在rtw工具箱的設置是: Solver: stop time 選inf &nb ...… 查看全部問答∨ |
|
例如我要傳送一張圖片 大小為100KB,而我的端點最大包長度為1KB,那么我就要傳100次是嗎,對數據的分割時應用層來做還是驅動層自動做的,我大概看了驅動的代碼好像沒有數據分割這么一說,見笑。… 查看全部問答∨ |
|
沒有接觸過不間斷電源,有幾個問題像大家請教,忘不惜告知,先謝了! 有裝飾用的LED燈,總功率根據項目不同一般在25W~50W之間,12Vdc。之前一直采用開關電源(輸入220,輸出12vdc)直接供電,停電后則滅。 現客戶提出新要求: 要求正常時,LED燈 ...… 查看全部問答∨ |
usbdemo代碼在flash可以運行,無法在ram里面運行?(問題已經解決) IAR EWARM 4.41 & JLink & STR912FW44 & Windows 2003我把中斷向量表復制到ram的最高端, 一共64bytes.在flash里面, 中斷都沒有問題. 但是在ram里面不正常.我測試了0x04000000&nb ...… 查看全部問答∨ |