1# 小凌派-RK2206开发板基础外设开发——LCD液晶屏显示 2 3本示例将演示如何在小凌派-RK2206开发板上LCD液晶屏显示 4 5 6 7## 硬件资源 8 9硬件资源图如下所示: 10 11 12## 硬件接口说明 13 14引脚名称开发者可在硬件资源图中查看,也可在2.4寸液晶模块背面查看。 15 16| 引脚名称 | 功能描述 | 17| :------- | :------------------------------ | 18| D/C | 指令/数据选择端,L:指令,H:数据 | 19| RESET | 复位信号线,低电平有效 | 20| SPI_MOSI | SPI数据输入信号线 | 21| SPI_CLK | SPI时钟信号线 | 22| SPI_CS | SPI片选信号线,低电平有效 | 23| GND | 电源地引脚 | 24| 5V | 5V电源输入引脚 | 25 26## 硬件设计 27 28硬件电路如下图所示: 29 30 31### 硬件连接 32 33安装图如下所示: 34 35 36## 程序设计 37 38### API分析 39 40**头文件** 41 42```r 43//vendor/lockzhiner/lingpi/samples/b4_lcd/include/lcd.h 44``` 45 46#### lcd_init() 47 48```c 49unsigned int lcd_init(); 50``` 51 52**描述:** 53 54lcd液晶屏设备初始化。 55 56**参数:** 57 58无 59 60**返回值:** 61 62返回0为成功,反之为失败 63 64#### lcd_deinit() 65 66```c 67unsigned int lcd_deinit(); 68``` 69 70**描述:** 71 72lcd液晶屏设备注销。 73 74**参数:** 75 76无 77 78**返回值:** 79 80返回0为成功,反之为失败 81 82#### lcd_fill() 83 84```c 85void lcd_fill(uint16_t xsta, uint16_t ysta, uint16_t xend, uint16_t yend, uint16_t color); 86``` 87 88**描述:** 89 90lcd液晶屏指定区域填充颜色。 91 92**参数:** 93 94| 名字 | 描述 | 95| :---- | :-------------------- | 96| xsta | 指定区域的起始点X坐标 | 97| ysta | 指定区域的起始点Y坐标 | 98| xend | 指定区域的结束点X坐标 | 99| yend | 指定区域的结束点Y坐标 | 100| color | 指定区域的颜色 | 101 102**返回值:** 103 104无 105 106#### lcd_draw_point() 107 108```c 109void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color); 110``` 111 112**描述:** 113 114lcd液晶屏指定位置画一个点。 115 116**参数:** 117 118| 名字 | 描述 | 119| :---- | :------------ | 120| x | 指定点的X坐标 | 121| y | 指定点的Y坐标 | 122| color | 指定点的颜色 | 123 124**返回值:** 125 126无 127 128#### lcd_draw_line() 129 130```c 131void lcd_draw_line(uint16_t x1, uint16_t y1, 132 uint16_t x2, uint16_t y2, 133 uint16_t color); 134``` 135 136**描述:** 137 138lcd液晶屏指定位置画一条线。 139 140**参数:** 141 142| 名字 | 描述 | 143| :---- | :------------------ | 144| x1 | 指定线的起始点X坐标 | 145| y1 | 指定线的起始点Y坐标 | 146| x2 | 指定线的结束点X坐标 | 147| y2 | 指定线的结束点Y坐标 | 148| color | 指定线的颜色 | 149 150**返回值:** 151 152无 153 154#### lcd_draw_rectangle() 155 156```c 157void lcd_draw_rectangle(uint16_t x1, uint16_t y1, 158 uint16_t x2, uint16_t y2, 159 uint16_t color); 160``` 161 162**描述:** 163 164lcd液晶屏指定位置画矩形。 165 166**参数:** 167 168| 名字 | 描述 | 169| :---- | :-------------------- | 170| x1 | 指定矩形的起始点X坐标 | 171| y1 | 指定矩形的起始点Y坐标 | 172| x2 | 指定矩形的结束点X坐标 | 173| y2 | 指定矩形的结束点Y坐标 | 174| color | 指定矩形的颜色 | 175 176**返回值:** 177 178无 179 180#### lcd_draw_circle() 181 182```c 183void lcd_draw_circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color); 184``` 185 186**描述:** 187 188lcd液晶屏指定位置画圆。 189 190**参数:** 191 192| 名字 | 描述 | 193| :---- | :------------------ | 194| x0 | 指定圆的中心点X坐标 | 195| y0 | 指定圆的中心点Y坐标 | 196| r | 指定圆的半径 | 197| color | 指定圆的颜色 | 198 199**返回值:** 200 201无 202 203#### lcd_show_chinese() 204 205```c 206void lcd_show_chinese(uint16_t x, 207 uint16_t y, 208 uint8_t *s, 209 uint16_t fc, 210 uint16_t bc, 211 uint8_t sizey, 212 uint8_t mode); 213``` 214 215**描述:** 216 217lcd液晶屏显示汉字串。 218 219**参数:** 220 221| 名字 | 描述 | 222| :---- | :---------------------------- | 223| x | 指定汉字串的起始位置X坐标 | 224| y | 指定汉字串的起始位置X坐标 | 225| s | 指定汉字串(该汉字串为utf-8) | 226| fc | 字的颜色 | 227| bc | 字的背景色 | 228| sizey | 字号,可选:12、16、24、32 | 229| mode | 0为非叠加模式;1为叠加模式 | 230 231**返回值:** 232 233无 234 235#### lcd_show_char() 236 237```c 238void lcd_show_char(uint16_t x, 239 uint16_t y, 240 uint8_t *s, 241 uint16_t fc, 242 uint16_t bc, 243 uint8_t sizey, 244 uint8_t mode); 245``` 246 247**描述:** 248 249lcd液晶屏显示一个字符。 250 251**参数:** 252 253| 名字 | 描述 | 254| :---- | :------------------------- | 255| x | 指定汉字串的起始位置X坐标 | 256| y | 指定汉字串的起始位置X坐标 | 257| s | 指定一个ASCII字符 | 258| fc | 字的颜色 | 259| bc | 字的背景色 | 260| sizey | 字号,可选:12、16、24、32 | 261| mode | 0为非叠加模式;1为叠加模式 | 262 263**返回值:** 264 265无 266 267#### lcd_show_string() 268 269```c 270void lcd_show_string(uint16_t x, 271 uint16_t y, 272 const uint8_t *p, 273 uint16_t fc, 274 uint16_t bc, uint8_t sizey, uint8_t mode); 275``` 276 277**描述:** 278 279lcd液晶屏显示字符串。 280 281**参数:** 282 283| 名字 | 描述 | 284| :---- | :------------------------- | 285| x | 指定汉字串的起始位置X坐标 | 286| y | 指定汉字串的起始位置X坐标 | 287| p | 指定一个英文字符串 | 288| fc | 字的颜色 | 289| bc | 字的背景色 | 290| sizey | 字号,可选:12、16、24、32 | 291| mode | 0为非叠加模式;1为叠加模式 | 292 293**返回值:** 294 295无 296 297#### lcd_show_int_num() 298 299```c 300void lcd_show_int_num(uint16_t x, uint16_t y, uint16_t num, uint8_t len, uint16_t fc, uint16_t bc, uint8_t sizey); 301``` 302 303**描述:** 304 305lcd液晶屏显示一个整数。 306 307**参数:** 308 309| 名字 | 描述 | 310| :---- | :------------------------- | 311| x | 指定汉字串的起始位置X坐标 | 312| y | 指定汉字串的起始位置X坐标 | 313| p | 指定一个英文字符串 | 314| fc | 字的颜色 | 315| bc | 字的背景色 | 316| sizey | 字号,可选:12、16、24、32 | 317| mode | 0为非叠加模式;1为叠加模式 | 318 319**返回值:** 320 321无 322 323#### lcd_show_float_num1() 324 325```c 326void lcd_show_float_num1(uint16_t x, uint16_t y, float num, uint8_t len, uint16_t fc, uint16_t bc, uint8_t sizey); 327``` 328 329**描述:** 330 331lcd液晶屏显示两位小数变量。 332 333**参数:** 334 335| 名字 | 描述 | 336| :---- | :-------------------------- | 337| x | 指定浮点变量的起始位置X坐标 | 338| y | 指定浮点变量的起始位置X坐标 | 339| num | 指定浮点变量 | 340| fc | 字的颜色 | 341| bc | 字的背景色 | 342| sizey | 字号,可选:12、16、24、32 | 343 344**返回值:** 345 346无 347 348#### lcd_show_picture() 349 350```c 351void lcd_show_picture(uint16_t x, uint16_t y, uint16_t length, uint16_t width, const uint8_t *pic); 352``` 353 354**描述:** 355 356lcd液晶屏显示图片。 357 358**参数:** 359 360| 名字 | 描述 | 361| :----- | :------------------------ | 362| x | 指定浮图片的起始位置X坐标 | 363| y | 指定浮图片的起始位置X坐标 | 364| length | 指定图片的长度 | 365| width | 指定图片的宽度 | 366| pic | 指定图片的内容 | 367 368**返回值:** 369 370无 371 372### LCD液晶屏 373 374LCD型号为ST7789V,采用SPI通信方式,数据传输协议如下: 375 376`4-Line Serial Interface => 16-bit/pixel(RGB 5-6-5-bit input),65K-Color,3Ah="05h"` 377 378数据传输时序图如下: 379 380 381 382LCD使用的是SPI协议,SPI_CS与GPIO0_PC0相连接,SPI_CLK与GPIO0_PC1相连接,SPI_MOSI与GPIO0_PC2相连接,RES与GPIO0_PC3相连接,DC与GPIO0_PC6相连接。 383 384### 初始化代码分析 385 386本程序可使用SPI或GPIO模拟SPI与LCD进行通信。以下我们主要对SPI与LCD进行通信进行代码分析。 387这部分代码为SPI初始化的代码。首先用 `SpiIoInit()` 函数将GPIO0_PC0复用为SPI0_CS0n_M1,GPIO0_PC1复用为SPI0_CLK_M1,GPIO0_PC2复用为SPI0_MOSI_M1。最后调用 `LzI2cInit()`函数初始化SPI0端口。 388 389```c 390if (SpiIoInit(m_spiBus) != LZ_HARDWARE_SUCCESS) { 391 printf("%s, %d: SpiIoInit failed!\n", __FILE__, __LINE__); 392 return __LINE__; 393} 394if (LzSpiInit(LCD_SPI_BUS, m_spiConf) != LZ_HARDWARE_SUCCESS) { 395 printf("%s, %d: LzSpiInit failed!\n", __FILE__, __LINE__); 396 return __LINE__; 397} 398``` 399 400这部分代码为GPIO初始化的代码。首先用 `LzGpioInit()`函数将GPIO0_PC3初始化为GPIO引脚,然后用 `LzGpioSetDir()`将引脚设置为输出模式,最后调用 `LzGpioSetVal()`输出低电平。 401 402```c 403/* 初始化GPIO0_C3 */ 404LzGpioInit(LCD_PIN_RES); 405LzGpioSetDir(LCD_PIN_RES, LZGPIO_DIR_OUT); 406LzGpioSetVal(LCD_PIN_RES, LZGPIO_LEVEL_HIGH); 407 408/* 初始化GPIO0_C6 */ 409LzGpioInit(LCD_PIN_DC); 410LzGpioSetDir(LCD_PIN_DC, LZGPIO_DIR_OUT); 411LzGpioSetVal(LCD_PIN_DC, LZGPIO_LEVEL_LOW); 412``` 413 414### 通过SPI往LCD屏幕写数据操作 415 416这部分的代码是向LCD写入数据,具体如下: 417 418```c 419LzSpiWrite(LCD_SPI_BUS, 0, &dat, 1); 420``` 421 422### 配置ST7789V启动 423 424```c 425/* 重启lcd */ 426LCD_RES_Clr(); 427LOS_Msleep(100); 428LCD_RES_Set(); 429LOS_Msleep(100); 430LOS_Msleep(500); 431lcd_wr_reg(0x11); 432/* 等待LCD 100ms */ 433LOS_Msleep(100); 434/* 启动LCD配置,设置显示和颜色配置 */ 435lcd_wr_reg(0X36); 436if (USE_HORIZONTAL == 0) 437{ 438 lcd_wr_data8(0x00); 439} 440else if (USE_HORIZONTAL == 1) 441{ 442 lcd_wr_data8(0xC0); 443} 444else if (USE_HORIZONTAL == 2) 445{ 446 lcd_wr_data8(0x70); 447} 448else 449{ 450 lcd_wr_data8(0xA0); 451} 452lcd_wr_reg(0X3A); 453lcd_wr_data8(0X05); 454/* ST7789S帧刷屏率设置 */ 455lcd_wr_reg(0xb2); 456lcd_wr_data8(0x0c); 457lcd_wr_data8(0x0c); 458lcd_wr_data8(0x00); 459lcd_wr_data8(0x33); 460lcd_wr_data8(0x33); 461lcd_wr_reg(0xb7); 462lcd_wr_data8(0x35); 463/* ST7789S电源设置 */ 464lcd_wr_reg(0xbb); 465lcd_wr_data8(0x35); 466lcd_wr_reg(0xc0); 467lcd_wr_data8(0x2c); 468lcd_wr_reg(0xc2); 469lcd_wr_data8(0x01); 470lcd_wr_reg(0xc3); 471lcd_wr_data8(0x13); 472lcd_wr_reg(0xc4); 473lcd_wr_data8(0x20); 474lcd_wr_reg(0xc6); 475lcd_wr_data8(0x0f); 476lcd_wr_reg(0xca); 477lcd_wr_data8(0x0f); 478lcd_wr_reg(0xc8); 479lcd_wr_data8(0x08); 480lcd_wr_reg(0x55); 481lcd_wr_data8(0x90); 482lcd_wr_reg(0xd0); 483lcd_wr_data8(0xa4); 484lcd_wr_data8(0xa1); 485/* ST7789S gamma设置 */ 486lcd_wr_reg(0xe0); 487lcd_wr_data8(0xd0); 488lcd_wr_data8(0x00); 489lcd_wr_data8(0x06); 490lcd_wr_data8(0x09); 491lcd_wr_data8(0x0b); 492lcd_wr_data8(0x2a); 493lcd_wr_data8(0x3c); 494lcd_wr_data8(0x55); 495lcd_wr_data8(0x4b); 496lcd_wr_data8(0x08); 497lcd_wr_data8(0x16); 498lcd_wr_data8(0x14); 499lcd_wr_data8(0x19); 500lcd_wr_data8(0x20); 501lcd_wr_reg(0xe1); 502lcd_wr_data8(0xd0); 503lcd_wr_data8(0x00); 504lcd_wr_data8(0x06); 505lcd_wr_data8(0x09); 506lcd_wr_data8(0x0b); 507lcd_wr_data8(0x29); 508lcd_wr_data8(0x36); 509lcd_wr_data8(0x54); 510lcd_wr_data8(0x4b); 511lcd_wr_data8(0x0d); 512lcd_wr_data8(0x16); 513lcd_wr_data8(0x14); 514lcd_wr_data8(0x21); 515lcd_wr_data8(0x20); 516lcd_wr_reg(0x29); 517``` 518 519这部分代码将ST7789V配置为 `4-Line Serial Interface => 16-bit/pixel(RGB 5-6-5-bit input),65K-Color` 520 521## 编译调试 522 523### 修改 BUILD.gn 文件 524 525修改 `vendor/lockzhiner/lingpi/sample` 路径下 BUILD.gn 文件,指定 `b4_lcd` 参与编译。 526 527```r 528"b4_lcd", 529``` 530 531在主目录下输入编译命令 。 532 533```shell 534hb build -f 535``` 536 537### 运行结果 538 539示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志,并请使用带有LCD屏幕显示如下: 540 541```c 542************Lcd Example*********** 543 544************Lcd Example*********** 545 546``` 547