完整教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980php
本章教程爲你們講解漢字小字庫和全字庫的製做方式,實際項目中用到的地方比較多。數組
53.1 初學者重要提示框架
53.2 使用MakeDot小軟件生成C文件格式小字庫方法函數
53.3 使用MakeDot小軟件生成C文件格式全字庫方法學習
53.4 C文件格式漢字使用方法測試
53.5 漢字顯示方法解析字體
53.6 LCD驅動移植和使用ui
53.7 實驗例程設計框架編碼
53.8 實驗例程說明(MDK)spa
53.9 實驗例程說明(IAR)
5.10 總結
生成方法比較簡單,這裏作個介紹:
好比要顯示以下字符,採用16點陣格式:
安富萊電子,www.armfly.com
故人西辭黃鶴樓,煙花三月下揚州。
孤帆遠影碧空盡,惟見長江天際流。
選擇16點陣,並將要顯示的字符複製到輸入窗口:
點擊生成數組按鈕後的效果以下:
在輸出窗口鼠標右擊,選擇「全選」,而後再次鼠標右擊選擇複製。
這樣就能夠粘貼到工程的hz.c文件裏面:
將點陣數據放在相應的文件裏面時要注意加上兩個0XFF。hz.c文件的內容以下:
/* FLASH中內嵌小字庫,只包括本程序用到的漢字點陣 每行點陣數據,頭2字節是漢子的內碼,後面是16點陣漢子的字模數據。 */ #ifdef USE_SMALL_FONT unsigned char const g_Hz16[] = { 0xA1,0xA3, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 。 // 0x00,0x00,0x00,0x00,0x18,0x00,0x24,0x00,0x24,0x00,0x18,0x00,0x00,0x00,0x00,0x00, 0xA3,0xAC, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// , // 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x20,0x00,0x00,0x00, 0xB0,0xB2, 0x02,0x00,0x01,0x00,0x3F,0xFC,0x20,0x04,0x42,0x08,0x02,0x00,0x02,0x00,0xFF,0xFE,// 安 // 0x04,0x20,0x08,0x20,0x18,0x40,0x06,0x40,0x01,0x80,0x02,0x60,0x0C,0x10,0x70,0x08, /* 中間部分省略未寫 */ 0xD7,0xD3, 0x00,0x00,0x7F,0xF8,0x00,0x10,0x00,0x20,0x00,0x40,0x01,0x80,0x01,0x00,0xFF,0xFE,// 子 // 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00, /* 最後一行必須用0xFF,0xFF結束,這是字庫數組結束標誌 */ 0xFF,0xFF }; #else unsigned char const g_Hz16[] = {0xFF, 0xFF}; #endif
添加完畢點陣數據後,在font.h文件裏面使能使用小字庫:
#define USE_SMALL_FONT /* 定義此行表示使用小字庫, 這個宏只在bsp_tft+lcd.c中使用 */
至此就完成了小字庫的漢字添加,用戶就能夠在使用16點陣時顯示第1步中轉換的字符了。
生成方法比較簡單,這裏作個介紹:
GB2312字符集已經在MakeDot小軟件裏面存好,點擊漢字編碼按鈕能夠看到:
複製MakeDot小軟件中GB2312全部字符到「輸入窗口區」(在GB2312字符顯示區,鼠標右擊選擇全選,以後就能夠複製了),
點擊生成數組按鈕後的效果以下:
在輸出窗口鼠標右擊,選擇「全選」,而後再次鼠標右擊選擇複製。
這樣就能夠粘貼到工程的hz.c文件裏面:
將點陣數據放在相應的文件裏面時要注意加上兩個0XFF。hz.c文件的內容以下:
/* FLASH中內嵌小字庫,只包括本程序用到的漢字點陣 每行點陣數據,頭2字節是漢子的內碼,後面是16點陣漢子的字模數據。 */ #ifdef USE_SMALL_FONT unsigned char const g_Hz16[] = { 0xA1,0xA1, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xA1,0xA2, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 、 // 0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x0C,0x00,0x04,0x00,0x00,0x00,0x00,0x00, 0xA1,0xA3, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 。 // 0x00,0x00,0x00,0x00,0x18,0x00,0x24,0x00,0x24,0x00,0x18,0x00,0x00,0x00,0x00,0x00, /* 中間部分省略未寫 */ 0xF7,0xFB, 0x20,0x0E,0xCE,0xF0,0x82,0x22,0xEE,0x92,0x82,0x44,0x82,0x20,0xFE,0x44,0x00,0xF8,// 鼷 // 0x92,0x10,0x92,0x24,0xDA,0xFE,0x92,0x10,0xDA,0xFE,0x92,0x28,0x93,0x44,0xD9,0x82, 0xF7,0xFC, 0x10,0x20,0x3E,0x20,0x22,0x20,0x3E,0x20,0x22,0xF8,0x3E,0x28,0x00,0x28,0x7F,0x28,// 鼽 // 0x49,0x28,0x7F,0x28,0x49,0x28,0x7F,0x2A,0x00,0x2A,0xFF,0xCA,0x22,0x46,0x42,0x80, 0xF7,0xFD, 0x10,0x00,0x3E,0x00,0x22,0x7C,0x3E,0x10,0x22,0x10,0x3E,0x10,0x00,0x10,0x7F,0x10,// 鼾 // 0x49,0xFE,0x7F,0x10,0x49,0x10,0x7F,0x10,0x00,0x10,0xFF,0x90,0x22,0x10,0x42,0x10, 0xF7,0xFE, 0x10,0x10,0x3E,0x10,0x22,0xFE,0x3E,0x38,0x22,0x54,0x3E,0x92,0x00,0x00,0x7F,0x7C,// 齇 // 0x49,0x44,0x7F,0x7C,0x49,0x44,0x7F,0x7C,0x00,0x44,0xFF,0x80,0x22,0xFE,0x42,0x00, /* 最後一行必須用0xFF,0xFF結束,這是字庫數組結束標誌 */ 0xFF,0xFF }; #else unsigned char const g_Hz16[] = {0xFF, 0xFF}; #endif
添加完畢點陣數據後,在font.h文件裏面使能宏定義:
#define USE_SMALL_FONT /*這個宏只在bsp_tft+lcd.c中使用 */
至此就完成了全字庫的漢字添加,用戶就可使用16點陣的漢字了。
漢字的顯示方法比較簡單。
FONT_T tFont12; /* 定義一個12點陣字體結構體變量,用於設置字體參數 */ FONT_T tFont16; /* 定義一個16點陣字體結構體變量,用於設置字體參數 */ FONT_T tFont24; /* 定義一個24點陣字體結構體變量,用於設置字體參數 */
FONT_T的原始定義以下:
typedef struct { FONT_CODE_E FontCode; /* 字體代碼 FONT_CODE_E */ uint16_t FrontColor; /* 字體顏色 */ uint16_t BackColor; /* 文字背景顏色,透明 */ uint16_t Space; /* 文字間距,單位 = 像素 */ }FONT_T;
設置12,16和24點陣。
/* 設置字體屬性 */ tFont.FontCode = FC_ST_12; /* 字體選擇宋體12點陣,高12 x寬11) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_MASK; /* 文字背景顏色,透明 */ tFont.Space = 0; /* 字符水平間距, 單位 = 像素 */ tFont.FontCode = FC_ST_16; /* 字體選擇宋體16點陣,高16 x寬15) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_MASK; /* 文字背景顏色,透明 */ tFont.Space = 0; /* 字符水平間距, 單位 = 像素 */ tFont.FontCode = FC_ST_24; /* 字體選擇宋體24點陣,高24 x寬23) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_MASK; /* 文字背景顏色,透明 */ tFont.Space = 0; /* 字符水平間距, 單位 = 像素 */
下面顯示了12,16和24點陣字符。
LCD_DispStr(5, 3, "故人西辭黃鶴樓,煙花三月下揚州。www.armfly.com", &tFont12); LCD_DispStr(5, 20, "孤帆遠影碧空盡,惟見長江天際流。www.armfly.com", &tFont12); LCD_DispStr(5, 38, "故人西辭黃鶴樓,煙花三月下揚州。", &tFont16); LCD_DispStr(5, 68, "孤帆遠影碧空盡,惟見長江天際流。", &tFont16); LCD_DispStr(5, 98, "故人西辭黃鶴樓煙花三月下揚州", &tFont24); LCD_DispStr(5, 128, "孤帆遠影碧空盡惟見長江天際流", &tFont24);
下面將漢字的顯示流程作個說明,幾個函數的調用關係以下:
LCD_DispStr ----> LCD_DispStrEx ----->_LCD_ReadAsciiDot
_LCD_ReadHZDot
中英文顯示都是調用的以下函數實現:
/* ********************************************************************************************************* * 函 數 名: LCD_DispStr * 功能說明: 在LCD指定座標(左上角)顯示一個字符串 * 形 參: * _usX : X座標 * _usY : Y座標 * _ptr : 字符串指針 * _tFont : 字體結構體,包含顏色、背景色(支持透明)、字體代碼、文字間距等參數 * 返 回 值: 無 ********************************************************************************************************* */ void LCD_DispStr(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont) { LCD_DispStrEx(_usX, _usY, _ptr, _tFont, 0, 0); }
這個函數的註釋已經比較詳細,這裏就再也不贅述了。而這個函數是經過調用LCD_DispStrEx實現。
此函數的源碼以下:
1. /* 2. ****************************************************************************************************** 3. * 函 數 名: LCD_DispStrEx 4. * 功能說明: 在LCD指定座標(左上角)顯示一個字符串。 加強型函數。支持左\中\右對齊,支持定長清屏。 5. * 形 參: 6. * _usX : X座標 7. * _usY : Y座標 8. * _ptr : 字符串指針 9. * _tFont : 字體結構體,包含顏色、背景色(支持透明)、字體代碼、文字間距等參數。能夠指定RA8875字庫 10. * 顯示漢字。 11. * _Width : 字符串顯示區域的寬度. 0 表示不處理留白區域,此時_Align無效 12. * _Align :字符串在顯示區域的對齊方式, 13. * ALIGN_LEFT = 0, 14. * ALIGN_CENTER = 1, 15. * ALIGN_RIGHT = 2 16. * 返 回 值: 無 17. ****************************************************************************************************** 18. */ 19. void LCD_DispStrEx(uint16_t _usX, uint16_t _usY, char *_ptr, FONT_T *_tFont, uint16_t _Width, 20. uint8_t _Align) 21. { 22. uint32_t i; 23. uint8_t code1; 24. uint8_t code2; 25. uint8_t buf[32 * 32 / 8]; /* 最大支持32點陣漢字 */ 26. uint8_t width; 27. uint16_t m; 28. uint8_t font_width = 0; 29. uint8_t font_height = 0; 30. uint16_t x, y; 31. uint16_t offset; 32. uint16_t str_width; /* 字符串實際寬度 */ 33. 34. switch (_tFont->FontCode) 35. { 36. case FC_ST_12: /* 12點陣 */ 37. font_height = 12; 38. font_width = 12; 39. break; 40. 41. case FC_ST_16: 42. font_height = 16; 43. font_width = 16; 44. break; 45. 46. case FC_ST_24: 47. font_height = 24; 48. font_width = 24; 49. break; 50. 51. case FC_ST_32: 52. font_height = 32; 53. font_width = 32; 54. break; 55. } 56. 57. str_width = LCD_GetStrWidth(_ptr, _tFont);/* 計算字符串實際寬度(RA8875內部ASCII點陣寬度爲變長 */ 58. offset = 0; 59. if (_Width > str_width) 60. { 61. if (_Align == ALIGN_RIGHT) /* 右對齊 */ 62. { 63. offset = _Width - str_width; 64. } 65. else if (_Align == ALIGN_CENTER) /* 居中 */ 66. { 67. offset = (_Width - str_width) / 2; 68. } 69. else /* 左對齊 ALIGN_LEFT */ 70. { 71. ; 72. } 73. } 74. 75. /* 左側填背景色, 中間對齊和右邊對齊 */ 76. if (offset > 0) 77. { 78. LCD_Fill_Rect(_usX, _usY, LCD_GetFontHeight(_tFont), offset, _tFont->BackColor); 79. _usX += offset; 80. } 81. 82. /* 右側填背景色 */ 83. if (_Width > str_width) 84. { 85. LCD_Fill_Rect(_usX + str_width, _usY, LCD_GetFontHeight(_tFont), _Width - str_width - offset, 86. _tFont->BackColor); 87. } 88. 89. /* 使用CPU內部字庫. 點陣信息由CPU讀取 */ 90. { 91. /* 開始循環處理字符 */ 92. while (*_ptr != 0) 93. { 94. code1 = *_ptr; /* 讀取字符串數據, 該數據多是ascii代碼,也可能漢字代碼的高字節 */ 95. if (code1 < 0x80) 96. { 97. /* 將ascii字符點陣複製到buf */ 98. //memcpy(buf, &pAscDot[code1 * (font_bytes / 2)], (font_bytes / 2)); 99. _LCD_ReadAsciiDot(code1, _tFont->FontCode, buf); /* 讀取ASCII字符點陣 */ 100. width = font_width / 2; 101. } 102. else 103. { 104. code2 = *++_ptr; 105. if (code2 == 0) 106. { 107. break; 108. } 109. /* 讀1個漢字的點陣 */ 110. _LCD_ReadHZDot(code1, code2, _tFont->FontCode, buf); 111. width = font_width; 112. } 113. 114. y = _usY; 115. /* 開始刷LCD */ 116. for (m = 0; m < font_height; m++) /* 字符高度 */ 117. { 118. x = _usX; 119. for (i = 0; i < width; i++) /* 字符寬度 */ 120. { 121. if ((buf[m * ((2 * width) / font_width) + i / 8] & (0x80 >> (i % 8 ))) != 0x00) 122. { 123. LCD_PutPixel(x, y, _tFont->FrontColor); /* 設置像素顏色爲文字色 */ 124. } 125. else 126. { 127. if (_tFont->BackColor != CL_MASK) /* 透明色 */ 128. { 129. LCD_PutPixel(x, y, _tFont->BackColor);/* 設置像素顏色爲文字背景色 */ 130. } 131. } 132. 133. x++; 134. } 135. y++; 136. } 137. 138. if (_tFont->Space > 0) 139. { 140. /* 若是文字底色按_tFont->usBackColor,而且字間距大於點陣的寬度,那麼須要在文字之間填 141. 充(暫時未實現) */ 142. } 143. _usX += width + _tFont->Space; /* 列地址遞增 */ 144. _ptr++; /* 指向下一個字符 */ 145. } 146. } 147. }
下面將代碼中幾個關鍵地方作個闡釋:
對於這個公式,你們經過代數法,代入兩次數值就好理解了。
此函數的做用是根據ASCII編碼值,讀取對應的點陣數據出來。
1. /* 2. ****************************************************************************************************** 3. * 函 數 名: _LCD_ReadAsciiDot 4. * 功能說明: 讀取1個ASCII字符的點陣數據 5. * 形 參: 6. * _code : ASCII字符的編碼,1字節。1-128 7. * _fontcode :字體代碼 8. * _pBuf : 存放讀出的字符點陣數據 9. * 返 回 值: 文字寬度 10. ****************************************************************************************************** 11. */ 12. static void _LCD_ReadAsciiDot(uint8_t _code, uint8_t _fontcode, uint8_t *_pBuf) 13. { 14. const uint8_t *pAscDot; 15. uint8_t font_bytes = 0; 16. 17. pAscDot = 0; 18. switch (_fontcode) 19. { 20. case FC_ST_12: /* 12點陣 */ 21. font_bytes = 24; 22. pAscDot = g_Ascii12; 23. break; 24. 25. case FC_ST_24: 26. case FC_ST_32: 27. case FC_ST_16: 28. /* 缺省是16點陣 */ 29. font_bytes = 32; 30. pAscDot = g_Ascii16; 31. break; 32. 33. case FC_RA8875_16: 34. case FC_RA8875_24: 35. case FC_RA8875_32: 36. return; 37. } 38. 39. /* 將CPU內部Flash中的ascii字符點陣複製到buf */ 40. memcpy(_pBuf, &pAscDot[_code * (font_bytes / 2)], (font_bytes / 2)); 41. }
下面將此函數涉及到的知識點爲你們作個闡釋:
此函數的做用是根據ASCII編碼值,讀取對應的點陣數據出來。
1. /* 2. ****************************************************************************************************** 3. * 函 數 名: _LCD_ReadHZDot 4. * 功能說明: 讀取1個漢字的點陣數據 5. * 形 參: 6. * _code1, _cod2 : 漢字內碼. GB2312編碼 7. * _fontcode :字體代碼 8. * _pBuf : 存放讀出的字符點陣數據 9. * 返 回 值: 無 10. ****************************************************************************************************** 11. */ 12. static void _LCD_ReadHZDot(uint8_t _code1, uint8_t _code2, uint8_t _fontcode, uint8_t *_pBuf) 13. { 14. #ifdef USE_SMALL_FONT /* 使用CPU 內部Flash 小字庫 */ 15. uint8_t *pDot; 16. uint8_t font_bytes = 0; 17. uint32_t address; 18. uint16_t m; 19. 20. pDot = 0; /* 僅僅用於避免告警 */ 21. switch (_fontcode) 22. { 23. case FC_ST_12: /* 12點陣 */ 24. font_bytes = 24; 25. pDot = (uint8_t *)g_Hz12; 26. break; 27. 28. case FC_ST_16: 29. font_bytes = 32; 30. pDot = (uint8_t *)g_Hz16; 31. break; 32. 33. case FC_ST_24: 34. font_bytes = 72; 35. pDot = (uint8_t *)g_Hz24; 36. break; 37. 38. case FC_ST_32: 39. font_bytes = 128; 40. pDot = (uint8_t *)g_Hz32; 41. break; 42. 43. case FC_RA8875_16: 44. case FC_RA8875_24: 45. case FC_RA8875_32: 46. return; 47. } 48. 49. m = 0; 50. while(1) 51. { 52. address = m * (font_bytes + 2); 53. m++; 54. if ((_code1 == pDot[address + 0]) && (_code2 == pDot[address + 1])) 55. { 56. address += 2; 57. memcpy(_pBuf, &pDot[address], font_bytes); 58. break; 59. } 60. else if ((pDot[address + 0] == 0xFF) && (pDot[address + 1] == 0xFF)) 61. { 62. /* 字庫搜索完畢,未找到,則填充全FF */ 63. memset(_pBuf, 0xFF, font_bytes); 64. break; 65. } 66. } 67. #else /* 用全字庫 */ 68. uint8_t *pDot = 0; 69. uint8_t font_bytes = 0; 70. 71. switch (_fontcode) 72. { 73. case FC_ST_12: /* 12點陣 */ 74. font_bytes = 24; 75. pDot = (uint8_t *)HZK12_ADDR; 76. break; 77. 78. case FC_ST_16: 79. font_bytes = 32; 80. pDot = (uint8_t *)HZK16_ADDR; 81. break; 82. 83. case FC_ST_24: 84. font_bytes = 72; 85. pDot = (uint8_t *)HZK24_ADDR; 86. break; 87. 88. case FC_ST_32: 89. font_bytes = 128; 90. pDot = (uint8_t *)HZK32_ADDR; 91. break; 92. 93. case FC_RA8875_16: 94. case FC_RA8875_24: 95. case FC_RA8875_32: 96. return; 97. } 98. 99. /* 此處須要根據字庫文件存放位置進行修改 */ 100. if (_code1 >=0xA1 && _code1 <= 0xA9 && _code2 >=0xA1) 101. { 102. pDot += ((_code1 - 0xA1) * 94 + (_code2 - 0xA1)) * font_bytes; 103. } 104. else if (_code1 >=0xB0 && _code1 <= 0xF7 && _code2 >=0xA1) 105. { 106. pDot += ((_code1 - 0xB0) * 94 + (_code2 - 0xA1) + 846) * font_bytes; 107. } 108. memcpy(_pBuf, pDot, font_bytes); 109. #endif 110. }
下面將此函數涉及到的知識點爲你們作個闡釋:
與第51章51.7小節相同,這裏就再也不贅述了。
經過程序設計框架,讓你們先對配套例程有一個全面的認識,而後再理解細節,本次實驗例程的設計框架以下:
第1階段,上電啓動階段:
第2階段,進入main函數:
配套例子:
V7-033_LCD的漢字小字庫和全字庫製做實驗
實驗目的:
實驗內容:
實驗操做:
LCD的界面顯示效果以下:
部分截圖:
上電後串口打印的信息:
波特率 115200,數據位 8,奇偶校驗位無,中止位 1
程序設計:
系統棧大小分配:
RAM空間用的DTCM:
硬件外設初始化
硬件外設的初始化是在 bsp.c 文件實現:
/* ********************************************************************************************************* * 函 數 名: bsp_Init * 功能說明: 初始化全部的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只須要調用一次 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */ void bsp_Init(void) { /* 配置MPU */ MPU_Config(); /* 使能L1 Cache */ CPU_CACHE_Enable(); /* STM32H7xx HAL 庫初始化,此時系統用的仍是H7自帶的64MHz,HSI時鐘: - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。 - 設置NVIV優先級分組爲4。 */ HAL_Init(); /* 配置系統時鐘到400MHz - 切換使用HSE。 - 此函數會更新全局變量SystemCoreClock,並從新配置HAL_InitTick。 */ SystemClock_Config(); /* Event Recorder: - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。 - 默認不開啓,若是要使能此選項,務必看V7開發板用戶手冊第8章 */ #if Enable_EventRecorder == 1 /* 初始化EventRecorder並開啓 */ EventRecorderInitialize(EventRecordAll, 1U); EventRecorderStart(); #endif bsp_InitKey(); /* 按鍵初始化,要放在滴答定時器以前,由於按鈕檢測是經過滴答定時器掃描 */ bsp_InitTimer(); /* 初始化滴答定時器 */ bsp_InitUart(); /* 初始化串口 */ bsp_InitExtIO(); /* 初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行 */ bsp_InitLed(); /* 初始化LED */ bsp_InitI2C(); /* 初始化I2C總線 */ TOUCH_InitHard(); /* 初始化觸摸芯片,LCD面板型號的檢查也在此函數,因此要在函數LCD_InitHard前調用 */ LCD_InitHard(); /* 初始化LCD */ }
MPU配置和Cache配置:
數據Cache和指令Cache都開啓。配置了AXI SRAM區(本例子未用到AXI SRAM),FMC的擴展IO區和SDRAM。因爲SDRAM要用於LCD的顯存,方便起見,直接將其配置爲WT模式。
/* ********************************************************************************************************* * 函 數 名: MPU_Config * 功能說明: 配置MPU * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */ static void MPU_Config( void ) { MPU_Region_InitTypeDef MPU_InitStruct; /* 禁止 MPU */ HAL_MPU_Disable(); /* 配置AXI SRAM的MPU屬性爲Write back, Read allocate,Write allocate */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x24000000; MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* 配置FMC擴展IO的MPU屬性爲Device或者Strongly Ordered */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x60000000; MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_64KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* 配置SDRAM的MPU屬性爲Write through, read allocate,no write allocate */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0xC0000000; MPU_InitStruct.Size = MPU_REGION_SIZE_32MB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER2; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /*使能 MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /* ********************************************************************************************************* * 函 數 名: CPU_CACHE_Enable * 功能說明: 使能L1 Cache * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */ static void CPU_CACHE_Enable(void) { /* 使能 I-Cache */ SCB_EnableICache(); /* 使能 D-Cache */ SCB_EnableDCache(); }
主功能:
主程序實現以下操做:
/* ********************************************************************************************************* * 函 數 名: main * 功能說明: c程序入口 * 形 參: 無 * 返 回 值: 錯誤代碼(無需處理) ********************************************************************************************************* */ int main(void) { uint16_t ucBright; /* 背光亮度(0-255) */ uint8_t ucKeyCode; /* 按鍵代碼 */ uint8_t ucStatus; /* 主程序狀態字 */ uint8_t fRefresh; /* 刷屏請求標誌,1表示須要刷新 */ bsp_Init(); /* 硬件初始化 */ PrintfLogo(); /* 打印例程名稱和版本等信息 */ PrintfHelp(); /* 打印操做提示 */ /* 延遲200ms再點亮背光,避免瞬間高亮 */ bsp_DelayMS(200); DispFirstPage(); /* 顯示第1頁 */ /* 界面總體顯示完畢後,再打開背光,設置爲缺省亮度 */ bsp_DelayMS(100); ucBright = BRIGHT_DEFAULT; LCD_SetBackLight(ucBright); bsp_StartAutoTimer(0, 200); /* 啓動1個200ms的自動重裝的定時器,軟件定時器0 */ /* 進入主程序循環體 */ ucStatus = 0; fRefresh = 0; while (1) { /* 判斷軟件定時器0是否超時 */ if(bsp_CheckTimer(0)) { /* 每隔200ms 進來一次 */ bsp_LedToggle(2); } if (fRefresh == 1) { fRefresh = 0; switch (ucStatus) { case 0: DispFirstPage(); /* 顯示第1頁 */ break; case 1: DispAsciiDot(); /* 顯示ASCII點陣 */ break; default: /* 區碼範圍 :1 - 87 */ if (ucStatus <= 89) { DispHZK16(ucStatus); /* 顯示一個區的94個漢字 */ } break; } } ucKeyCode = bsp_GetKey(); /* 讀取鍵值, 無鍵按下時返回 KEY_NONE = 0 */ if (ucKeyCode != KEY_NONE) { /* 有鍵按下 */ switch (ucKeyCode) { case JOY_DOWN_L: /* 搖桿LEFT鍵按下 */ if (ucStatus > 0) { ucStatus--; } fRefresh = 1; /* 請求刷新LCD */ break; case JOY_DOWN_R: /* 搖桿RIGHT鍵按下 */ if (ucStatus < DEMO_PAGE_COUNT - 1) { ucStatus++; } fRefresh = 1; /* 請求刷新LCD */ break; case JOY_DOWN_OK: /* 搖桿OK鍵 */ ucStatus = 0; /* 返回首頁 */ fRefresh = 1; /* 請求刷新LCD */ break; case JOY_DOWN_U: /* 搖桿UP鍵按下 */ ucBright += BRIGHT_STEP; if (ucBright > BRIGHT_MAX) { ucBright = BRIGHT_MAX; } LCD_SetBackLight(ucBright); printf("當前背景光亮度 : %d\r\n", ucBright); break; case JOY_DOWN_D: /* 搖桿DOWN鍵按下 */ if (ucBright < BRIGHT_STEP) { ucBright = 0; } else { ucBright -= BRIGHT_STEP; } LCD_SetBackLight(ucBright); printf("當前背景光亮度 : %d\r\n", ucBright); break; default: break; } } } }
下面的代碼用於LCD首頁顯示:
/* ********************************************************************************************************* * 函 數 名: DispFirstPage * 功能說明: 顯示操做提示 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */ static void DispFirstPage(void) { FONT_T tFont; /* 定義一個字體結構體變量,用於設置字體參數 */ uint16_t y; /* Y座標 */ uint16_t usLineCap; /* 行高 */ uint8_t buf[50]; LCD_ClrScr(CL_BLUE); /* 清屏,背景藍色 */ /* 設置字體屬性 */ tFont.FontCode = FC_ST_16; /* 字體選擇宋體16點陣,高16x寬15) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_MASK; /* 文字背景顏色,透明 */ tFont.Space = 0; /* 字符水平間距, 單位 = 像素 */ y = 0; usLineCap = 18; /* 行間距 */ LCD_DispStr(5, y, "安富萊STM32-V7開發板 www.armfly.com", &tFont); y += usLineCap; LCD_DispStr(5, y, "漢字小字庫和全字庫測試實驗", &tFont); y += 2 * usLineCap; LCD_DispStr(30, y, "操做提示:", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿上鍵 = 增長背光亮度", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿下鍵 = 下降背光亮度", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿左鍵 = 向前翻頁", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿右鍵 = 向後翻頁", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿OK鍵 = 返回首頁", &tFont); y += 2 * usLineCap; sprintf((char *)buf, "顯示器分辨率 :%dx%d", g_LcdWidth, g_LcdHeight); LCD_DispStr(5, y, (char *)buf, &tFont); y += usLineCap; LCD_DispStr(5, y, "每行能夠顯示25個漢字,或50個字符", &tFont); }
下面是ASCII字符顯示:
/* ********************************************************************************************************* * 函 數 名: DispAsciiDot * 功能說明: 顯示ASCII點陣 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */ static void DispAsciiDot(void) { uint8_t i,k; FONT_T tFont; /* 定義一個字體結構體變量,用於設置字體參數 */ uint16_t x; /* X座標 */ uint16_t y; /* Y座標 */ char buf[32 + 1]; uint8_t ascii; LCD_ClrScr(CL_BLUE); /* 清屏,背景藍色 */ /* 設置字體屬性 */ tFont.FontCode = FC_ST_16; /* 字體選擇宋體16點陣,高16x寬15) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_MASK; /* 文字背景顏色,透明 */ tFont.Space = 2; /* 字符水平間距, 單位 = 像素 */ LCD_DispStr(50, 0, "16點陣ASCII碼字庫,代碼1-127", &tFont); x = 50; y = 40; ascii = 0; for (i = 0; i < 4; i++) { for (k = 0; k < 32; k++) { buf[k] = ascii++; } buf[32] = 0; if (buf[0] == 0) { buf[0] = ' '; } LCD_DispStr(x, y, buf, &tFont); y += 20; } }
下面是GB2312編碼字符顯示:
/* ********************************************************************************************************* * 函 數 名: DispHZK16 * 功能說明: 顯示16點陣漢字陣 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */ static void DispHZK16(uint8_t _ucIndex) { uint8_t i,k; uint16_t x,y; char buf[50 + 1]; uint8_t code1,code2; /* 漢字內碼 */ uint8_t usLineCap = 18; FONT_T tFont; /* 定義一個字體結構體變量,用於設置字體參數 */ printf(" Display HZK Area Code = %d\r\n", _ucIndex - 1); if (_ucIndex == 2) { /* 第1次清屏,之後顯示位置不變,能夠不清屏,避免閃爍 */ LCD_ClrScr(CL_BLUE); /* 清屏,背景藍色 */ } /* 設置字體屬性 */ tFont.FontCode = FC_ST_16; /* 字體選擇宋體16點陣,高16x寬15) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_BLUE; /* 文字背景顏色,藍色 */ tFont.Space = 0; /* 字符水平間距, 單位 = 像素 */ y = 0; LCD_DispStr(20, y, "國標GB2312 16點陣漢字庫(區碼1-87,位碼1-94)", &tFont); code1 = _ucIndex - 1; /* 獲得區碼 */ code2 = 1; /* 位碼從1開始 */ y += usLineCap; sprintf((char *)buf, (char *)"當前區碼: %2d, 本頁位碼:1-94, 第10-15區無字符", code1); LCD_DispStr(20, y, buf, &tFont); y += (2 * usLineCap); /* 機內碼高位 = 區碼 + 0xA0 機內碼低位 = 位碼 + 0xA0 區碼範圍 :1 - 87 位碼範圍 : 1 - 94 每行顯示20個漢字,一個區是94個漢字,須要5行顯示,第5行顯示14個漢字 */ x = 40; code1 += 0xA0; /* 換算到內碼高位 */ code2 = 0xA1; /* 內碼低位起始 */ for (i = 0; i < 5; i++) { for (k = 0; k < 20; k++) { buf[2 * k] = code1; buf[2 * k + 1] = code2; code2++; if ((i == 4) && (k == 13)) { k++; break; } } buf[2 * k] = 0; LCD_DispStr(x, y, buf, &tFont); y += usLineCap; } }
配套例子:
V7-033_LCD的漢字小字庫和全字庫製做實驗
實驗目的:
實驗內容:
實驗操做:
LCD的界面顯示效果以下:
部分截圖:
上電後串口打印的信息:
波特率 115200,數據位 8,奇偶校驗位無,中止位 1
程序設計:
系統棧大小分配:
RAM空間用的DTCM:
硬件外設初始化
硬件外設的初始化是在 bsp.c 文件實現:
/* ********************************************************************************************************* * 函 數 名: bsp_Init * 功能說明: 初始化全部的硬件設備。該函數配置CPU寄存器和外設的寄存器並初始化一些全局變量。只須要調用一次 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */ void bsp_Init(void) { /* 配置MPU */ MPU_Config(); /* 使能L1 Cache */ CPU_CACHE_Enable(); /* STM32H7xx HAL 庫初始化,此時系統用的仍是H7自帶的64MHz,HSI時鐘: - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。 - 設置NVIV優先級分組爲4。 */ HAL_Init(); /* 配置系統時鐘到400MHz - 切換使用HSE。 - 此函數會更新全局變量SystemCoreClock,並從新配置HAL_InitTick。 */ SystemClock_Config(); /* Event Recorder: - 可用於代碼執行時間測量,MDK5.25及其以上版本才支持,IAR不支持。 - 默認不開啓,若是要使能此選項,務必看V7開發板用戶手冊第8章 */ #if Enable_EventRecorder == 1 /* 初始化EventRecorder並開啓 */ EventRecorderInitialize(EventRecordAll, 1U); EventRecorderStart(); #endif bsp_InitKey(); /* 按鍵初始化,要放在滴答定時器以前,由於按鈕檢測是經過滴答定時器掃描 */ bsp_InitTimer(); /* 初始化滴答定時器 */ bsp_InitUart(); /* 初始化串口 */ bsp_InitExtIO(); /* 初始化FMC總線74HC574擴展IO. 必須在 bsp_InitLed()前執行 */ bsp_InitLed(); /* 初始化LED */ bsp_InitI2C(); /* 初始化I2C總線 */ TOUCH_InitHard(); /* 初始化觸摸芯片,LCD面板型號的檢查也在此函數,因此要在函數LCD_InitHard前調用 */ LCD_InitHard(); /* 初始化LCD */ }
MPU配置和Cache配置:
數據Cache和指令Cache都開啓。配置了AXI SRAM區(本例子未用到AXI SRAM),FMC的擴展IO區和SDRAM。因爲SDRAM要用於LCD的顯存,方便起見,直接將其配置爲WT模式。
/* ********************************************************************************************************* * 函 數 名: MPU_Config * 功能說明: 配置MPU * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */ static void MPU_Config( void ) { MPU_Region_InitTypeDef MPU_InitStruct; /* 禁止 MPU */ HAL_MPU_Disable(); /* 配置AXI SRAM的MPU屬性爲Write back, Read allocate,Write allocate */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x24000000; MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* 配置FMC擴展IO的MPU屬性爲Device或者Strongly Ordered */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0x60000000; MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_64KB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* 配置SDRAM的MPU屬性爲Write through, read allocate,no write allocate */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.BaseAddress = 0xC0000000; MPU_InitStruct.Size = MPU_REGION_SIZE_32MB; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER2; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.SubRegionDisable = 0x00; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /*使能 MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /* ********************************************************************************************************* * 函 數 名: CPU_CACHE_Enable * 功能說明: 使能L1 Cache * 形 參: 無 * 返 回 值: 無 ********************************************************************************************************* */ static void CPU_CACHE_Enable(void) { /* 使能 I-Cache */ SCB_EnableICache(); /* 使能 D-Cache */ SCB_EnableDCache(); }
主功能:
主程序實現以下操做:
/* ********************************************************************************************************* * 函 數 名: main * 功能說明: c程序入口 * 形 參: 無 * 返 回 值: 錯誤代碼(無需處理) ********************************************************************************************************* */ int main(void) { uint16_t ucBright; /* 背光亮度(0-255) */ uint8_t ucKeyCode; /* 按鍵代碼 */ uint8_t ucStatus; /* 主程序狀態字 */ uint8_t fRefresh; /* 刷屏請求標誌,1表示須要刷新 */ bsp_Init(); /* 硬件初始化 */ PrintfLogo(); /* 打印例程名稱和版本等信息 */ PrintfHelp(); /* 打印操做提示 */ /* 延遲200ms再點亮背光,避免瞬間高亮 */ bsp_DelayMS(200); DispFirstPage(); /* 顯示第1頁 */ /* 界面總體顯示完畢後,再打開背光,設置爲缺省亮度 */ bsp_DelayMS(100); ucBright = BRIGHT_DEFAULT; LCD_SetBackLight(ucBright); bsp_StartAutoTimer(0, 200); /* 啓動1個200ms的自動重裝的定時器,軟件定時器0 */ /* 進入主程序循環體 */ ucStatus = 0; fRefresh = 0; while (1) { /* 判斷軟件定時器0是否超時 */ if(bsp_CheckTimer(0)) { /* 每隔200ms 進來一次 */ bsp_LedToggle(2); } if (fRefresh == 1) { fRefresh = 0; switch (ucStatus) { case 0: DispFirstPage(); /* 顯示第1頁 */ break; case 1: DispAsciiDot(); /* 顯示ASCII點陣 */ break; default: /* 區碼範圍 :1 - 87 */ if (ucStatus <= 89) { DispHZK16(ucStatus); /* 顯示一個區的94個漢字 */ } break; } } ucKeyCode = bsp_GetKey(); /* 讀取鍵值, 無鍵按下時返回 KEY_NONE = 0 */ if (ucKeyCode != KEY_NONE) { /* 有鍵按下 */ switch (ucKeyCode) { case JOY_DOWN_L: /* 搖桿LEFT鍵按下 */ if (ucStatus > 0) { ucStatus--; } fRefresh = 1; /* 請求刷新LCD */ break; case JOY_DOWN_R: /* 搖桿RIGHT鍵按下 */ if (ucStatus < DEMO_PAGE_COUNT - 1) { ucStatus++; } fRefresh = 1; /* 請求刷新LCD */ break; case JOY_DOWN_OK: /* 搖桿OK鍵 */ ucStatus = 0; /* 返回首頁 */ fRefresh = 1; /* 請求刷新LCD */ break; case JOY_DOWN_U: /* 搖桿UP鍵按下 */ ucBright += BRIGHT_STEP; if (ucBright > BRIGHT_MAX) { ucBright = BRIGHT_MAX; } LCD_SetBackLight(ucBright); printf("當前背景光亮度 : %d\r\n", ucBright); break; case JOY_DOWN_D: /* 搖桿DOWN鍵按下 */ if (ucBright < BRIGHT_STEP) { ucBright = 0; } else { ucBright -= BRIGHT_STEP; } LCD_SetBackLight(ucBright); printf("當前背景光亮度 : %d\r\n", ucBright); break; default: break; } } } }
下面的代碼用於LCD首頁顯示:
/* ********************************************************************************************************* * 函 數 名: DispFirstPage * 功能說明: 顯示操做提示 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */ static void DispFirstPage(void) { FONT_T tFont; /* 定義一個字體結構體變量,用於設置字體參數 */ uint16_t y; /* Y座標 */ uint16_t usLineCap; /* 行高 */ uint8_t buf[50]; LCD_ClrScr(CL_BLUE); /* 清屏,背景藍色 */ /* 設置字體屬性 */ tFont.FontCode = FC_ST_16; /* 字體選擇宋體16點陣,高16x寬15) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_MASK; /* 文字背景顏色,透明 */ tFont.Space = 0; /* 字符水平間距, 單位 = 像素 */ y = 0; usLineCap = 18; /* 行間距 */ LCD_DispStr(5, y, "安富萊STM32-V7開發板 www.armfly.com", &tFont); y += usLineCap; LCD_DispStr(5, y, "漢字小字庫和全字庫測試實驗", &tFont); y += 2 * usLineCap; LCD_DispStr(30, y, "操做提示:", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿上鍵 = 增長背光亮度", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿下鍵 = 下降背光亮度", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿左鍵 = 向前翻頁", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿右鍵 = 向後翻頁", &tFont); y += usLineCap; LCD_DispStr(50, y, "搖桿OK鍵 = 返回首頁", &tFont); y += 2 * usLineCap; sprintf((char *)buf, "顯示器分辨率 :%dx%d", g_LcdWidth, g_LcdHeight); LCD_DispStr(5, y, (char *)buf, &tFont); y += usLineCap; LCD_DispStr(5, y, "每行能夠顯示25個漢字,或50個字符", &tFont); }
下面是ASCII字符顯示:
/* ********************************************************************************************************* * 函 數 名: DispAsciiDot * 功能說明: 顯示ASCII點陣 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */ static void DispAsciiDot(void) { uint8_t i,k; FONT_T tFont; /* 定義一個字體結構體變量,用於設置字體參數 */ uint16_t x; /* X座標 */ uint16_t y; /* Y座標 */ char buf[32 + 1]; uint8_t ascii; LCD_ClrScr(CL_BLUE); /* 清屏,背景藍色 */ /* 設置字體屬性 */ tFont.FontCode = FC_ST_16; /* 字體選擇宋體16點陣,高16x寬15) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_MASK; /* 文字背景顏色,透明 */ tFont.Space = 2; /* 字符水平間距, 單位 = 像素 */ LCD_DispStr(50, 0, "16點陣ASCII碼字庫,代碼1-127", &tFont); x = 50; y = 40; ascii = 0; for (i = 0; i < 4; i++) { for (k = 0; k < 32; k++) { buf[k] = ascii++; } buf[32] = 0; if (buf[0] == 0) { buf[0] = ' '; } LCD_DispStr(x, y, buf, &tFont); y += 20; } }
下面是GB2312編碼字符顯示:
/* ********************************************************************************************************* * 函 數 名: DispHZK16 * 功能說明: 顯示16點陣漢字陣 * 形 參:無 * 返 回 值: 無 ********************************************************************************************************* */ static void DispHZK16(uint8_t _ucIndex) { uint8_t i,k; uint16_t x,y; char buf[50 + 1]; uint8_t code1,code2; /* 漢字內碼 */ uint8_t usLineCap = 18; FONT_T tFont; /* 定義一個字體結構體變量,用於設置字體參數 */ printf(" Display HZK Area Code = %d\r\n", _ucIndex - 1); if (_ucIndex == 2) { /* 第1次清屏,之後顯示位置不變,能夠不清屏,避免閃爍 */ LCD_ClrScr(CL_BLUE); /* 清屏,背景藍色 */ } /* 設置字體屬性 */ tFont.FontCode = FC_ST_16; /* 字體選擇宋體16點陣,高16x寬15) */ tFont.FrontColor = CL_WHITE; /* 字體顏色設置爲白色 */ tFont.BackColor = CL_BLUE; /* 文字背景顏色,藍色 */ tFont.Space = 0; /* 字符水平間距, 單位 = 像素 */ y = 0; LCD_DispStr(20, y, "國標GB2312 16點陣漢字庫(區碼1-87,位碼1-94)", &tFont); code1 = _ucIndex - 1; /* 獲得區碼 */ code2 = 1; /* 位碼從1開始 */ y += usLineCap; sprintf((char *)buf, (char *)"當前區碼: %2d, 本頁位碼:1-94, 第10-15區無字符", code1); LCD_DispStr(20, y, buf, &tFont); y += (2 * usLineCap); /* 機內碼高位 = 區碼 + 0xA0 機內碼低位 = 位碼 + 0xA0 區碼範圍 :1 - 87 位碼範圍 : 1 - 94 每行顯示20個漢字,一個區是94個漢字,須要5行顯示,第5行顯示14個漢字 */ x = 40; code1 += 0xA0; /* 換算到內碼高位 */ code2 = 0xA1; /* 內碼低位起始 */ for (i = 0; i < 5; i++) { for (k = 0; k < 20; k++) { buf[2 * k] = code1; buf[2 * k + 1] = code2; code2++; if ((i == 4) && (k == 13)) { k++; break; } } buf[2 * k] = 0; LCD_DispStr(x, y, buf, &tFont); y += usLineCap; } }
本章節涉及到的知識點比較多,須要你們花點時間去掌握,直至能夠獨立驅動一個顯示屏。