xld0932

  • 20 主题
  • 35 帖子
  • 1472 积分
  • 身份:LV4 高级技术员
  • 论坛新秀
  • E币:1236

NUCLEO-L412KB使用硬件SPI驱动2.2寸液晶显示屏

2019-5-16 13:57:52 显示全部楼层
    1.概述

    使用NUCLEO-L412开发板驱动SPI接口的2.2" TFT液晶屏,显示一些简单的信息。掌握硬件SPI操作,简单图形点阵绘制。

    2.硬件连接

    2.1.硬件连接示意图

    4.png
    说明:
    液晶屏工作电压为3.3V,LCD_CS为液晶屏的选通引脚,LCD_RESET为液晶屏的复位引脚,LCD_DC为液晶屏用来区分命令或数据的控制引脚,LCD_BL为液晶屏的背光控制引脚,LCD_SCK & LCD_MISO & LCD_MOSI为液晶屏的SPI通讯接口。

    2.2.实物连接图

    1.jpg

    3.STM32CubeMX配置

    3.1.GPIO口及SPI GPIO口配置如下图所示:

    5.png

    6.png

    3.2.SPI1配置如下图所示:

    7.png

    4.编写驱动程序

    4.1.ILI9341驱动程序

  1. /**
  2.   ******************************************************************************
  3.   * @file    ILI9341.c
  4.   * @version V1.00
  5.   * @author  xld0932
  6.   * @brief   
  7.   ******************************************************************************
  8.   * @attention
  9.   *
  10.   * Copyright (c) 2019. All rights reserved.
  11.   *
  12.   ******************************************************************************
  13.   */


  14. /* Define to prevent recursive inclusion ------------------------------------*/
  15. #define __ILI9341_C__


  16. /* Includes -----------------------------------------------------------------*/
  17. #include "ILI9341.h"


  18. /* Private constants --------------------------------------------------------*/
  19. /* Private defines ----------------------------------------------------------*/
  20. /* Private typedef ----------------------------------------------------------*/
  21. /* Private macro ------------------------------------------------------------*/
  22. /* Private variables --------------------------------------------------------*/
  23. /* Private function prototypes ----------------------------------------------*/


  24. /* Exported variables -------------------------------------------------------*/
  25. extern SPI_HandleTypeDef hspi1;


  26. /* Exported function prototypes ---------------------------------------------*/


  27. /**
  28. * @brief  :
  29. * @param  :
  30. * @returns:
  31. * @details:
  32. */
  33. static void ILI9341_SPI_Transmit(uint8_t data)
  34. {
  35.     if(HAL_SPI_Transmit(&hspi1, &data, 1, 1000) != HAL_OK)
  36.     {
  37.         printf("\r\nSPI Transmit Error!");
  38.     }
  39. }


  40. /**
  41. * @brief  :
  42. * @param  :
  43. * @returns:
  44. * @details:
  45. */
  46. void ILI9341_WriteCommand(uint8_t cmd)
  47. {
  48.     LCD_DC_CLR;

  49.     LCD_CS_CLR;
  50.     ILI9341_SPI_Transmit(cmd);
  51.     LCD_CS_SET;
  52. }


  53. /**
  54. * @brief  :
  55. * @param  :
  56. * @returns:
  57. * @details:
  58. */
  59. void ILI9341_WriteData(uint8_t dat)
  60. {
  61.     LCD_DC_SET;

  62.     LCD_CS_CLR;
  63.     ILI9341_SPI_Transmit(dat);
  64.     LCD_CS_SET;
  65. }


  66. /**
  67. * @brief  :
  68. * @param  :
  69. * @returns:
  70. * @details:
  71. */
  72. void ILI9341_WriteWord(uint16_t dat)
  73. {
  74.     ILI9341_WriteData((uint8_t)(dat >> 8));
  75.     ILI9341_WriteData((uint8_t)(dat >> 0));
  76. }


  77. /**
  78. * @brief  :
  79. * @param  :
  80. * @returns:
  81. * @details:
  82. */
  83. static void ILI9341_HardwareReset(void)
  84. {
  85.     LCD_RST_CLR;
  86.     HAL_Delay(100);

  87.     LCD_RST_SET;
  88.     HAL_Delay(100);
  89. }


  90. /**
  91. * @brief  :
  92. * @param  :
  93. * @returns:
  94. * @details:
  95. */
  96. void ILI9341_Init(void)
  97. {
  98.     ILI9341_HardwareReset();

  99.     //---Sleep Out
  100.         ILI9341_WriteCommand(0x11);
  101.     HAL_Delay(150);

  102.         //---Memory Access Control
  103.     ILI9341_WriteCommand(0x36);
  104.     ILI9341_WriteData(0x48);

  105.     //---COLMOD:Pixel Format Set = 16 bits / pixel
  106.         ILI9341_WriteCommand(0x3A);
  107.         ILI9341_WriteData(0x55);

  108.     //---Display ON
  109.         ILI9341_WriteCommand(0x29);
  110. }


  111. /*********************** (C) COPYRIGHT ************************END OF FILE****/

    4.2.基于ILI9341编写的LCD驱动程序

  1. /**
  2.   ******************************************************************************
  3.   * @file    LCD.h
  4.   * @version V1.00
  5.   * @author  xld0932
  6.   * @brief   
  7.   ******************************************************************************
  8.   * @attention
  9.   *
  10.   * Copyright (c) 2019. All rights reserved.
  11.   *
  12.   ******************************************************************************
  13.   */


  14. /* Define to prevent recursive inclusion ------------------------------------*/
  15. #ifndef __LCD_H__
  16. #define __LCD_H__


  17. #undef  EXTERN

  18. #ifdef  __LCD_C__
  19. #define EXTERN
  20. #else
  21. #define EXTERN extern
  22. #endif


  23. /* Includes -----------------------------------------------------------------*/
  24. #include "platform.h"


  25. /* Exported constants -------------------------------------------------------*/


  26. /* Exported defines ---------------------------------------------------------*/
  27. #define USE_HORIZONTAL      0

  28. #define LCD_X_SIZE          240
  29. #define LCD_Y_SIZE          320

  30. #if USE_HORIZONTAL
  31. #define X_MAX_PIXEL         LCD_Y_SIZE
  32. #define Y_MAX_PIXEL         LCD_X_SIZE
  33. #else
  34. #define X_MAX_PIXEL         LCD_X_SIZE
  35. #define Y_MAX_PIXEL         LCD_Y_SIZE
  36. #endif


  37. /* Exported typedef ---------------------------------------------------------*/
  38. typedef enum
  39. {
  40.     TopLeft = 0,
  41.     TopCenter,
  42.     TopRight,
  43.     MiddleLeft,
  44.     MiddleCenter,
  45.     MiddleRight,
  46.     BottomLeft,
  47.     BottomCenter,
  48.     BottomRight,
  49. } eALIGN;


  50. typedef struct
  51. {
  52.     uint16_t x;
  53.     uint16_t y;

  54.     eALIGN  align;
  55.     char    *text;
  56. } sTEXT;


  57. /* Exported macro -----------------------------------------------------------*/
  58. #define RGB(r,g,b) ((((r) & 0x1F) << 11) | (((g) & 0x3F) << 6) | ((b) & 0x1F))


  59. /* Exported functions prototypes --------------------------------------------*/
  60. EXTERN void LCD_Init(void);


  61. #endif


  62. /*********************** (C) COPYRIGHT ************************END OF FILE****/

  1. /**
  2.   ******************************************************************************
  3.   * @file    LCD.c
  4.   * @version V1.00
  5.   * @author  xld0932
  6.   * @brief   
  7.   ******************************************************************************
  8.   * @attention
  9.   *
  10.   * Copyright (c) 2019. All rights reserved.
  11.   *
  12.   ******************************************************************************
  13.   */


  14. /* Define to prevent recursive inclusion ------------------------------------*/
  15. #define __LCD_C__


  16. /* Includes -----------------------------------------------------------------*/
  17. #include "font.h"
  18. #include "LCD.h"
  19. #include "ILI9341.h"


  20. /* Private constants --------------------------------------------------------*/


  21. /* Private defines ----------------------------------------------------------*/
  22. #define LCD_DEFAULT_FONT    Font08x16


  23. /* Private typedef ----------------------------------------------------------*/
  24. /* Private macro ------------------------------------------------------------*/


  25. /* Private variables --------------------------------------------------------*/
  26. sFONT   *TextFont;
  27. uint16_t TextColor = 0;
  28. uint16_t BackColor = 0;

  29. sTEXT title = {0, 10, MiddleCenter, "MianBaoBan"};


  30. /* Private function prototypes ----------------------------------------------*/


  31. /* Exported variables -------------------------------------------------------*/
  32. /* Exported function prototypes ---------------------------------------------*/


  33. /**
  34. * @brief  :
  35. * @param  :
  36. * @returns:
  37. * @details:
  38. */
  39. void LCD_SetCursor(uint16_t x, uint16_t y)
  40. {        
  41.         ILI9341_WriteCommand(0x2A);
  42.         ILI9341_WriteWord(x);

  43.         ILI9341_WriteCommand(0x2B);
  44.         ILI9341_WriteWord(y);

  45.         ILI9341_WriteCommand(0x2C);        
  46. }


  47. /**
  48. * @brief  :
  49. * @param  :
  50. * @returns:
  51. * @details:
  52. */
  53. void LCD_SetRegion(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
  54. {
  55.         ILI9341_WriteCommand(0x2A);
  56.         ILI9341_WriteWord(x);
  57.         ILI9341_WriteWord(x+width);

  58.         ILI9341_WriteCommand(0x2B);
  59.         ILI9341_WriteWord(y);
  60.         ILI9341_WriteWord(y+height);

  61.         ILI9341_WriteCommand(0x2C);
  62. }


  63. /**
  64. * @brief  :
  65. * @param  :
  66. * @returns:
  67. * @details:
  68. */
  69. void LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color)
  70. {
  71.         LCD_SetCursor(x, y);

  72.         ILI9341_WriteWord(color);
  73. }


  74. /**
  75. * @brief  :
  76. * @param  :
  77. * @returns:
  78. * @details:
  79. */
  80. void LCD_Clear(uint16_t color)               
  81. {        
  82.     uint32_t i = 0;

  83.     LCD_SetRegion(0, 0, X_MAX_PIXEL-1, Y_MAX_PIXEL-1);

  84.     for(i = 0; i < X_MAX_PIXEL * Y_MAX_PIXEL; i++)
  85.     {
  86.         ILI9341_WriteWord(color);
  87.     }
  88. }


  89. /**
  90. * @brief  :
  91. * @param  :
  92. * @returns:
  93. * @details:
  94. */
  95. void LCD_Setup(void)
  96. {
  97.     ILI9341_Init();

  98.     LCD_LED_SET;
  99. }


  100. /**
  101. * @brief  :
  102. * @param  :
  103. * @returns:
  104. * @details:
  105. */
  106. void LCD_SetFont(sFONT *font)
  107. {
  108.     TextFont = font;
  109. }


  110. /**
  111. * @brief  :
  112. * @param  :
  113. * @returns:
  114. * @details:
  115. */
  116. sFONT *LCD_GetFont(void)
  117. {
  118.     return TextFont;
  119. }


  120. /**
  121. * @brief  :
  122. * @param  :
  123. * @returns:
  124. * @details:
  125. */
  126. void LCD_SetColor(uint16_t  forecolor, uint16_t  backcolor)
  127. {
  128.     TextColor = forecolor;
  129.     BackColor = backcolor;
  130. }


  131. /**
  132. * @brief  :
  133. * @param  :
  134. * @returns:
  135. * @details:
  136. */
  137. void LCD_GetColor(uint16_t *forecolor, uint16_t *backcolor)
  138. {
  139.     *forecolor = TextColor;
  140.     *backcolor = BackColor;
  141. }


  142. /**
  143. * @brief  :
  144. * @param  :
  145. * @returns:
  146. * @details:
  147. */
  148. void LCD_SetTextColor(uint16_t color)
  149. {
  150.     TextColor = color;
  151. }


  152. /**
  153. * @brief  :
  154. * @param  :
  155. * @returns:
  156. * @details:
  157. */
  158. uint16_t LCD_GetTextColor(void)
  159. {
  160.     return TextColor;
  161. }


  162. /**
  163. * @brief  :
  164. * @param  :
  165. * @returns:
  166. * @details:
  167. */
  168. void LCD_SetBackColor(uint16_t color)
  169. {
  170.     BackColor = color;
  171. }


  172. /**
  173. * @brief  :
  174. * @param  :
  175. * @returns:
  176. * @details:
  177. */
  178. uint16_t LCD_GetBackColor(void)
  179. {
  180.     return BackColor;
  181. }


  182. /**
  183. * @brief  :
  184. * @param  :
  185. * @returns:
  186. * @details:
  187. */
  188. void LCD_DisplayASCII(uint8_t x, uint16_t y, const uint8_t ch)
  189. {
  190.     uint8_t  i = 0,  j = 0, k = 0, temp = 0;
  191.     uint16_t forecolor = 0, backcolor   = 0;

  192.     sFONT *font = LCD_GetFont();

  193.     LCD_GetColor(&forecolor, &backcolor);

  194.     for(i = 0; i < font->width; i++)
  195.     {
  196.         for(j = 0; j < (font->height / 8); j++)
  197.         {
  198.             temp = font->table[(ch - 0x20) * (font->width / 8)][i + j * font->width];

  199.             for(k = 0; k < 8; k++)
  200.             {
  201.                 if((temp << k) & 0x80) LCD_DrawPoint(x + i, y + j * 8 + k, forecolor);
  202.                 else                   LCD_DrawPoint(x + i, y + j * 8 + k, backcolor);
  203.             }
  204.         }
  205.     }
  206. }


  207. /**
  208. * @brief  :
  209. * @param  :
  210. * @returns:
  211. * @details:
  212. */
  213. void LCD_DisplayString(uint16_t x, uint16_t y, char *str)
  214. {
  215.     sFONT *font = LCD_GetFont();

  216.     while (*str != '\0')
  217.     {
  218.         if(*str == '\n')
  219.         {
  220.             x = 0; y += font->height;
  221.         }
  222.         else if(*str == '\r')
  223.         {
  224.             // do nothing
  225.         }
  226.         else if(*str == '\t')
  227.         {
  228.             x += font->width * 4;
  229.             x %= X_MAX_PIXEL;
  230.         }
  231.         else
  232.         {
  233.             LCD_DisplayASCII(x, y, *str);

  234.             x += font->width;
  235.         }

  236.         if(x >= X_MAX_PIXEL)
  237.         {
  238.             x = 0; y += font->height;
  239.         }

  240.         if(y >= Y_MAX_PIXEL)
  241.         {
  242.             x = 0; y = 0;
  243.         }

  244.         str++;
  245.     }
  246. }


  247. /**
  248. * @brief  :
  249. * @param  :
  250. * @returns:
  251. * @details:
  252. */
  253. void LCD_DisplayText(sTEXT text)
  254. {
  255.     uint16_t x = 0,  width = 0;

  256.     width = strlen(text.text) * LCD_GetFont()->width;

  257.     switch(text.align)
  258.     {
  259.         case TopLeft:
  260.         case MiddleLeft:
  261.         case BottomLeft:
  262.             break;

  263.         case TopCenter:
  264.         case MiddleCenter:
  265.         case BottomCenter:
  266.             if((text.x + width) < X_MAX_PIXEL)
  267.             {
  268.                 x = (X_MAX_PIXEL - width) / 2;
  269.             }
  270.             break;

  271.         case TopRight:
  272.         case MiddleRight:
  273.         case BottomRight:
  274.             if((text.x + width) < X_MAX_PIXEL)
  275.             {
  276.                 x = X_MAX_PIXEL - width;
  277.             }
  278.             break;

  279.         default: break;
  280.     }

  281.     LCD_DisplayString(x, text.y, text.text);
  282. }


  283. /**
  284. * @brief  :
  285. * @param  :
  286. * @returns:
  287. * @details:
  288. */
  289. void LCD_Init(void)
  290. {
  291.     LCD_Setup();

  292.     LCD_SetColor(RGB(255,255,0),RGB(255,0,0));

  293.     LCD_Clear(LCD_GetBackColor());


  294.     LCD_SetFont(&Font16x16);
  295.     LCD_DisplayText(title);


  296.     LCD_SetFont(&LCD_DEFAULT_FONT);

  297.     LCD_DisplayString(0, 50,  "\r\nHardware : Nucleo-L412KB");
  298.     LCD_DisplayString(0, 100, "\r\nProject : LCD DEMO");
  299.     LCD_DisplayString(0, 125, "\r\nAuthor  : xld0932");
  300.     LCD_DisplayString(0, 150, "\r\nDetails : Hardware SPI Drive LCD (ILI9341) Demo");
  301. }


  302. /*********************** (C) COPYRIGHT ************************END OF FILE****/


    5.显示效果

    2.jpg

    6.总结

    使用STM32L412KB的硬件SPI接口驱动液晶屏,驱动液晶屏的显示速度较软件模拟实现的SPI操作速度要快很多。但对于有显示需要的项目来说,STM32L412KB肯定不是一个好选择,驱屏的速度还远达不到显示要求,本身这颗芯片也没有对应的总线接口或者内置屏驱。芯片内置的FLASH和SRAM也偏小,外扩SRAM对于芯片引脚数量也是一个限制。所以个人感觉这颗芯片还是适于用对功耗有要求的场合^^。

    7.工程代码

    LCD_DEMO.part03.rar (3.79 MB, 下载次数: 8)