一、LCD結構體
定義LCD為LCD_TypeDef類型的指針,指向0x6C000000的地址空間(bank1分區4的地址范圍)。
為什么需要并上0x000007FE呢?
因為雖然驅動SRAM的時序和16位8080接口時序(驅動LCD時序)很像,但是8080的RS(寄存器選擇)信號需要解決,解決方法是使用SRAM地址信號中的A10作為RS位。
0x000007FE是內部地址,指向一個8位的存儲空間。同時也是A10引腳的偏移值,因為A10是外部存儲器16位的地址,所以我們要先把該地址變成外部地址(右移一位或除以2),也就是說
111 1111 1110 -> 011 1111 1111
也就是該結構體變量的首地址是011 1111 1111(對于外部存儲器來說),那么結構體變量成員LCD_REG的地址就是011 1111 1111,而LCD_RAM的地址是外部地址加1,即100 0000 0000。
這種設計使得,兩個變量所在地址空間的A10不同,解決了RS的問題。
二、lcddev結構體
用來設置LCD的結構體。
三、底層接口函數
四、LCD初始化函數
五、LCD坐標設置函數
六、LCD畫點函數
七、LCD字符顯示函數
以下是針對圖片中 LCD_ShowChar
函數的逐行解析,結合其功能實現和硬件交互邏輯:
?1. 函數功能概述?
void LCD_ShowChar(u16 x, u16 y, u8 num, u8 size, u8 mode)
- ?作用?:在LCD屏幕的指定位置
(x,y)
顯示一個ASCII字符。 - ?參數?:
x, y
:字符左上角起始坐標(像素單位)。num
:要顯示的字符(ASCII碼,范圍從空格' '
到'~'
)。size
:字體大小(12/16/24像素)。mode
:顯示模式(0
非疊加,1
疊加。疊加模式下保留背景,僅繪制字符像素)。
?2. 關鍵變量與初始化?
u8 temp, t1, t;
u16 y0 = y; // 保存起始y坐標
u8 csize = (size/8 + ((size%8)?1:0)) * (size/2); // 計算字符點陣數據占用的字節數
num = num - ' '; // ASCII字庫偏移(字庫從空格開始存儲)
?**
csize
計算邏輯?:
字體點陣通常按行存儲**,每行像素用1字節表示(每bit代表1像素)。例如:- ?12像素字體?:每行12像素 → 占用2字節(12/8=1.5 → 向上取整為2字節)。
- 總字節數 =
(行字節數) * (行數)
=(size/8 + 余數處理) * (size/2)
。
?**
num
偏移**?:
字庫數組(如asc2_1206
)從空格字符(ASCII 32)開始存儲,減去' '
得到正確的索引。
?3. 字符點陣數據獲取?
for(t=0; t<csize; t++) {if(size==12) temp = asc2_1206[num][t]; // 12像素字體else if(size==16) temp = asc2_1608[num][t]; // 16像素字體else if(size==24) temp = asc2_2412[num][t]; // 24像素字體else return; // 不支持的字體大小
- ?字庫結構?:
字庫為二維數組(如asc2_1206[字符數][點陣字節數]
),每個字符的點陣數據按行排列。 - ?示例?:
若顯示字符'A'
(ASCII 65),則num = 65 - 32 = 33
,從字庫中獲取第33個字符的點陣。
?4. 逐像素繪制字符?
for(t1=0; t1<8; t1++) {if(temp & 0x80) LCD_Fast_DrawPoint(x, y, POINT_COLOR); // 當前bit=1,繪制字符顏色else if(mode==0) LCD_Fast_DrawPoint(x, y, BACK_COLOR); // 非疊加模式,繪制背景色temp <<= 1; // 左移檢查下一bity++; // 移動到下一行像素if(y >= lcddev.height) return; // 超出屏幕高度if((y - y0) == size) { // 完成一列繪制y = y0; // y坐標復位x++; // 移動到下一列if(x >= lcddev.width) return; // 超出屏幕寬度break;}
}
- ?像素繪制邏輯?:
- ?檢查最高位(
temp & 0x80
)??:- 若為1,調用
LCD_Fast_DrawPoint
繪制字符顏色(POINT_COLOR
)。 - 若為0且
mode=0
,繪制背景色(BACK_COLOR
,覆蓋原有內容)。
- 若為1,調用
- ?坐標更新?:
- 每處理1bit,
y++
向下移動一行像素。 - 當
y - y0 == size
時,表示一列像素繪制完成,復位y
并右移一列(x++
)。
- 每處理1bit,
- ?檢查最高位(
?5. 邊界檢查與優化?
- ?屏幕邊界處理?:
每次更新坐標后檢查x
和y
是否超出屏幕尺寸(lcddev.width/height
),避免越界。 - ?性能優化?:
LCD_Fast_DrawPoint
應為優化后的快速畫點函數(可能直接操作FSMC或顯存)。
?6. 字庫與硬件交互?
- ?字庫存儲?:
字庫數組(如asc2_1206
)通常存儲在代碼區(Flash)或外部SPI Flash,通過查表獲取點陣。 - ?LCD寫入?:
LCD_Fast_DrawPoint
內部通過FSMC或GPIO模擬8080接口,向LCD顯存寫入像素顏色值。
?總結:字符顯示流程?
- ?參數校驗? → 2. ?計算字模數據位置? → 3. ?逐字節讀取點陣? →
- ?逐bit繪制像素? → 5. ?坐標更新與邊界檢查? → 6. ?循環直至字符繪制完成。
此函數通過硬件加速的像素操作和高效的字模解析,實現了靈活的字符顯示功能。如需顯示中文或自定義圖形,需擴展字庫和繪制邏輯。