LCD_driver.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include "LCD_driver.h"
  2. #include <FreeRTOS.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <task.h>
  6. volatile static pika_dev* LCD_DC = NULL;
  7. volatile static pika_dev* LCD_SPI = NULL;
  8. static inline void _LCD_RS_SET(void) {
  9. uint32_t val = 1;
  10. pika_hal_write((pika_dev*)LCD_DC, &val, sizeof(val));
  11. }
  12. static inline void _LCD_RS_CLR(void) {
  13. uint32_t val = 0;
  14. pika_hal_write((pika_dev*)LCD_DC, &val, sizeof(val));
  15. }
  16. // 管理LCD重要参数
  17. // 默认为竖屏
  18. _lcd_dev lcddev;
  19. // 画笔颜色,背景颜色
  20. u16 POINT_COLOR = 0x0000, BACK_COLOR = 0xFFFF;
  21. u16 DeviceCode;
  22. #define LCD_WRITE_BATCH_SIZE 2048
  23. void LCD_write(uint8_t* data, uint32_t len) {
  24. for (int i = 0; i < len / LCD_WRITE_BATCH_SIZE; i++) {
  25. pika_hal_write((pika_dev*)LCD_SPI, data + i * LCD_WRITE_BATCH_SIZE,
  26. LCD_WRITE_BATCH_SIZE);
  27. }
  28. pika_hal_write((pika_dev*)LCD_SPI,
  29. data + len / LCD_WRITE_BATCH_SIZE * LCD_WRITE_BATCH_SIZE,
  30. len % LCD_WRITE_BATCH_SIZE);
  31. }
  32. void LCD_WR_REG(u8 data) {
  33. LCD_RS_CLR();
  34. LCD_write(&data, 1);
  35. }
  36. void LCD_WR_DATA(u8 data) {
  37. LCD_RS_SET();
  38. LCD_write(&data, 1);
  39. }
  40. void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue) {
  41. LCD_WR_REG(LCD_Reg);
  42. LCD_WR_DATA(LCD_RegValue);
  43. }
  44. void LCD_WriteRAM_Prepare(void) {
  45. LCD_WR_REG(lcddev.wramcmd);
  46. }
  47. static inline void color565_to_666(uint16_t color565, uint8_t* color666) {
  48. color666[0] = (color565 >> 8) & 0xF8;
  49. color666[1] = (color565 >> 3) & 0xFC;
  50. color666[2] = (color565 << 3);
  51. }
  52. void LCD_writePoint(u16 color) {
  53. /* rgb 666 */
  54. uint8_t data[3] = {0};
  55. color565_to_666(color, data);
  56. LCD_RS_SET();
  57. LCD_write(data, 3);
  58. }
  59. void LCD_drawPoint(u16 x, u16 y) {
  60. LCD_setCursor(x, y); // 设置光标位置
  61. LCD_writePoint(POINT_COLOR);
  62. }
  63. void LCD_drawRegin(u16 x_start,
  64. u16 y_start,
  65. u16 x_end,
  66. u16 y_end,
  67. uint8_t* pData) {
  68. u32 size = (x_end - x_start) * (y_end - y_start) * 2;
  69. LCD_setRegion(x_start, y_start, x_end - 1, y_end - 1);
  70. LCD_RS_SET();
  71. LCD_write(pData, size);
  72. }
  73. #define BUFF_LINE_NUM 4
  74. void LCD_fillRegin(u16 x_start, u16 y_start, u16 x_end, u16 y_end, u16 color) {
  75. size_t line_pix_size = x_end - x_start + 1;
  76. size_t buff_pix_size = (x_end - x_start + 1) * BUFF_LINE_NUM;
  77. uint8_t* buff = malloc(buff_pix_size * 3);
  78. if (NULL == buff) {
  79. printf("Error: malloc %d bytes failed\r\n", buff_pix_size * 3);
  80. }
  81. uint8_t color666[3] = {0};
  82. color565_to_666(color, color666);
  83. for (int i = 0; i < buff_pix_size; i++) {
  84. buff[i * 3] = color666[0];
  85. buff[i * 3 + 1] = color666[1];
  86. buff[i * 3 + 2] = color666[2];
  87. }
  88. LCD_setRegion(x_start, y_start, x_end, y_end);
  89. LCD_RS_SET();
  90. for (int i = 0; i < (y_end - y_start + 1) / BUFF_LINE_NUM; i++) {
  91. LCD_write(buff, buff_pix_size * 3);
  92. }
  93. if ((y_end - y_start + 1) % BUFF_LINE_NUM) {
  94. LCD_write(buff,
  95. line_pix_size * 3 * ((y_end - y_start + 1) % BUFF_LINE_NUM));
  96. }
  97. free(buff);
  98. }
  99. void LCD_clear(u16 Color) {
  100. LCD_fillRegin(0, 0, lcddev.width - 1, lcddev.height - 1, Color);
  101. }
  102. #define SPI_MODE_SOFT 1
  103. #define SPI_MODE_HARD 2
  104. #define SPI_MODE SPI_MODE_HARD
  105. void LCD_GPIOInit(void) {
  106. /* init spi */
  107. #if SPI_MODE == SPI_MODE_SOFT
  108. LCD_SPI = pika_hal_open(PIKA_HAL_SOFT_SPI, "SPI0");
  109. pika_hal_SOFT_SPI_config cfg_SPI = {0};
  110. cfg_SPI.CS = NULL;
  111. cfg_SPI.SCK = pika_hal_open(PIKA_HAL_GPIO, "P3");
  112. cfg_SPI.MISO = pika_hal_open(PIKA_HAL_GPIO, "P21");
  113. cfg_SPI.MOSI = pika_hal_open(PIKA_HAL_GPIO, "P20");
  114. #elif SPI_MODE == SPI_MODE_HARD
  115. LCD_SPI = pika_hal_open(PIKA_HAL_SPI, "SPI0");
  116. pika_hal_SPI_config cfg_SPI = {0};
  117. #endif
  118. cfg_SPI.master_or_slave = PIKA_HAL_SPI_MASTER;
  119. cfg_SPI.mode = PIKA_HAL_SPI_MODE_0;
  120. cfg_SPI.data_width = PIKA_HAL_SPI_DATA_WIDTH_8;
  121. cfg_SPI.speed = 40 * 1000 * 1000;
  122. pika_hal_ioctl((pika_dev*)LCD_SPI, PIKA_HAL_IOCTL_CONFIG, &cfg_SPI);
  123. pika_hal_ioctl((pika_dev*)LCD_SPI, PIKA_HAL_IOCTL_ENABLE);
  124. /* init gpio */
  125. LCD_DC = pika_hal_open(PIKA_HAL_GPIO, "P0");
  126. pika_hal_GPIO_config cfg_DC = {0};
  127. cfg_DC.dir = PIKA_HAL_GPIO_DIR_OUT;
  128. pika_hal_ioctl((pika_dev*)LCD_DC, PIKA_HAL_IOCTL_CONFIG, &cfg_DC);
  129. pika_hal_ioctl((pika_dev*)LCD_DC, PIKA_HAL_IOCTL_ENABLE);
  130. pika_dev* LCD_CS = pika_hal_open(PIKA_HAL_GPIO, "P22");
  131. pika_hal_GPIO_config cfg_CS = {0};
  132. cfg_CS.dir = PIKA_HAL_GPIO_DIR_OUT;
  133. pika_hal_ioctl((pika_dev*)LCD_CS, PIKA_HAL_IOCTL_CONFIG, &cfg_CS);
  134. pika_hal_ioctl((pika_dev*)LCD_CS, PIKA_HAL_IOCTL_ENABLE);
  135. uint32_t val = 0;
  136. pika_hal_write((pika_dev*)LCD_CS, &val, sizeof(val));
  137. }
  138. void LCD_RESET(void) {}
  139. void LCD_init(void) {
  140. LCD_GPIOInit(); // LCD GPIO初始化
  141. LCD_RESET(); // LCD 复位
  142. //************* ILI9488初始化**********//
  143. LCD_WR_REG(0XF7);
  144. LCD_WR_DATA(0xA9);
  145. LCD_WR_DATA(0x51);
  146. LCD_WR_DATA(0x2C);
  147. LCD_WR_DATA(0x82);
  148. LCD_WR_REG(0xC0);
  149. LCD_WR_DATA(0x11);
  150. LCD_WR_DATA(0x09);
  151. LCD_WR_REG(0xC1);
  152. LCD_WR_DATA(0x41);
  153. LCD_WR_REG(0XC5);
  154. LCD_WR_DATA(0x00);
  155. LCD_WR_DATA(0x0A);
  156. LCD_WR_DATA(0x80);
  157. LCD_WR_REG(0xB1);
  158. LCD_WR_DATA(0xB0);
  159. LCD_WR_DATA(0x11);
  160. LCD_WR_REG(0xB4);
  161. LCD_WR_DATA(0x02);
  162. LCD_WR_REG(0xB6);
  163. LCD_WR_DATA(0x02);
  164. LCD_WR_DATA(0x42);
  165. LCD_WR_REG(0xB7);
  166. LCD_WR_DATA(0xc6);
  167. LCD_WR_REG(0xBE);
  168. LCD_WR_DATA(0x00);
  169. LCD_WR_DATA(0x04);
  170. LCD_WR_REG(0xE9);
  171. LCD_WR_DATA(0x00);
  172. LCD_WR_REG(0x36);
  173. LCD_WR_DATA((1 << 3) | (0 << 7) | (1 << 6) | (1 << 5));
  174. LCD_WR_REG(0x3A);
  175. LCD_WR_DATA(0x66);
  176. LCD_WR_REG(0xE0);
  177. LCD_WR_DATA(0x00);
  178. LCD_WR_DATA(0x07);
  179. LCD_WR_DATA(0x10);
  180. LCD_WR_DATA(0x09);
  181. LCD_WR_DATA(0x17);
  182. LCD_WR_DATA(0x0B);
  183. LCD_WR_DATA(0x41);
  184. LCD_WR_DATA(0x89);
  185. LCD_WR_DATA(0x4B);
  186. LCD_WR_DATA(0x0A);
  187. LCD_WR_DATA(0x0C);
  188. LCD_WR_DATA(0x0E);
  189. LCD_WR_DATA(0x18);
  190. LCD_WR_DATA(0x1B);
  191. LCD_WR_DATA(0x0F);
  192. LCD_WR_REG(0XE1);
  193. LCD_WR_DATA(0x00);
  194. LCD_WR_DATA(0x17);
  195. LCD_WR_DATA(0x1A);
  196. LCD_WR_DATA(0x04);
  197. LCD_WR_DATA(0x0E);
  198. LCD_WR_DATA(0x06);
  199. LCD_WR_DATA(0x2F);
  200. LCD_WR_DATA(0x45);
  201. LCD_WR_DATA(0x43);
  202. LCD_WR_DATA(0x02);
  203. LCD_WR_DATA(0x0A);
  204. LCD_WR_DATA(0x09);
  205. LCD_WR_DATA(0x32);
  206. LCD_WR_DATA(0x36);
  207. LCD_WR_DATA(0x0F);
  208. LCD_WR_REG(0x11);
  209. vTaskDelay(120 / portTICK_RATE_MS);
  210. LCD_WR_REG(0x29);
  211. LCD_direction(USE_HORIZONTAL); // 设置LCD显示方向
  212. // LCD_LED = 1; // 点亮背光
  213. LCD_clear(WHITE); // 清全屏白色
  214. }
  215. void LCD_setRegion(u16 xStar, u16 yStar, u16 xEnd, u16 yEnd) {
  216. LCD_WR_REG(lcddev.setxcmd);
  217. LCD_WR_DATA(xStar >> 8);
  218. LCD_WR_DATA(0x00FF & xStar);
  219. LCD_WR_DATA(xEnd >> 8);
  220. LCD_WR_DATA(0x00FF & xEnd);
  221. LCD_WR_REG(lcddev.setycmd);
  222. LCD_WR_DATA(yStar >> 8);
  223. LCD_WR_DATA(0x00FF & yStar);
  224. LCD_WR_DATA(yEnd >> 8);
  225. LCD_WR_DATA(0x00FF & yEnd);
  226. LCD_WriteRAM_Prepare(); // 开始写入GRAM
  227. }
  228. void LCD_setCursor(u16 Xpos, u16 Ypos) {
  229. LCD_setRegion(Xpos, Ypos, Xpos, Ypos);
  230. }
  231. void LCD_direction(u8 direction) {
  232. lcddev.setxcmd = 0x2A;
  233. lcddev.setycmd = 0x2B;
  234. lcddev.wramcmd = 0x2C;
  235. switch (direction) {
  236. case 0:
  237. lcddev.width = LCD_W;
  238. lcddev.height = LCD_H;
  239. LCD_WriteReg(0x36, (1 << 3) | (0 << 6) |
  240. (0 << 7)); // BGR==1,MY==0,MX==0,MV==0
  241. break;
  242. case 1:
  243. lcddev.width = LCD_H;
  244. lcddev.height = LCD_W;
  245. LCD_WriteReg(0x36, (1 << 3) | (0 << 7) | (1 << 6) |
  246. (1 << 5)); // BGR==1,MY==1,MX==0,MV==1
  247. break;
  248. case 2:
  249. lcddev.width = LCD_W;
  250. lcddev.height = LCD_H;
  251. LCD_WriteReg(0x36, (1 << 3) | (1 << 6) |
  252. (1 << 7)); // BGR==1,MY==0,MX==0,MV==0
  253. break;
  254. case 3:
  255. lcddev.width = LCD_H;
  256. lcddev.height = LCD_W;
  257. LCD_WriteReg(0x36, (1 << 3) | (1 << 7) |
  258. (1 << 5)); // BGR==1,MY==1,MX==0,MV==1
  259. break;
  260. default:
  261. break;
  262. }
  263. }