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驱动程序
/**
  •   ******************************************************************************
  •   * @file    ILI9341.c
  •   * @version V1.00
  •   * @author  xld0932
  •   * @brief   
  •   ******************************************************************************
  •   * @attention
  •   *
  •   * Copyright (c) 2019. All rights reserved.
  •   *
  •   ******************************************************************************
  •   */
  • /* Define to prevent recursive inclusion ------------------------------------*/
  • #define __ILI9341_C__
  • /* Includes -----------------------------------------------------------------*/
  • #include "ILI9341.h"
  • /* Private constants --------------------------------------------------------*/
  • /* Private defines ----------------------------------------------------------*/
  • /* Private typedef ----------------------------------------------------------*/
  • /* Private macro ------------------------------------------------------------*/
  • /* Private variables --------------------------------------------------------*/
  • /* Private function prototypes ----------------------------------------------*/
  • /* Exported variables -------------------------------------------------------*/
  • extern SPI_HandleTypeDef hspi1;
  • /* Exported function prototypes ---------------------------------------------*/
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • static void ILI9341_SPI_Transmit(uint8_t data)
  • {
  •     if(HAL_SPI_Transmit(&hspi1, &data, 1, 1000) != HAL_OK)
  •     {
  •         printf("\r\nSPI Transmit Error!");
  •     }
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void ILI9341_WriteCommand(uint8_t cmd)
  • {
  •     LCD_DC_CLR;
  •     LCD_CS_CLR;
  •     ILI9341_SPI_Transmit(cmd);
  •     LCD_CS_SET;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void ILI9341_WriteData(uint8_t dat)
  • {
  •     LCD_DC_SET;
  •     LCD_CS_CLR;
  •     ILI9341_SPI_Transmit(dat);
  •     LCD_CS_SET;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void ILI9341_WriteWord(uint16_t dat)
  • {
  •     ILI9341_WriteData((uint8_t)(dat >> 8));
  •     ILI9341_WriteData((uint8_t)(dat >> 0));
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • static void ILI9341_HardwareReset(void)
  • {
  •     LCD_RST_CLR;
  •     HAL_Delay(100);
  •     LCD_RST_SET;
  •     HAL_Delay(100);
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void ILI9341_Init(void)
  • {
  •     ILI9341_HardwareReset();
  •     //---Sleep Out
  •         ILI9341_WriteCommand(0x11);
  •     HAL_Delay(150);
  •         //---Memory Access Control
  •     ILI9341_WriteCommand(0x36);
  •     ILI9341_WriteData(0x48);
  •     //---COLMOD:Pixel Format Set = 16 bits / pixel
  •         ILI9341_WriteCommand(0x3A);
  •         ILI9341_WriteData(0x55);
  •     //---Display ON
  •         ILI9341_WriteCommand(0x29);
  • }
  • /*********************** (C) COPYRIGHT ************************END OF FILE****/
  • 复制代码
        4.2.基于ILI9341编写的LCD驱动程序
    /**
  •   ******************************************************************************
  •   * @file    LCD.h
  •   * @version V1.00
  •   * @author  xld0932
  •   * @brief   
  •   ******************************************************************************
  •   * @attention
  •   *
  •   * Copyright (c) 2019. All rights reserved.
  •   *
  •   ******************************************************************************
  •   */
  • /* Define to prevent recursive inclusion ------------------------------------*/
  • #ifndef __LCD_H__
  • #define __LCD_H__
  • #undef  EXTERN
  • #ifdef  __LCD_C__
  • #define EXTERN
  • #else
  • #define EXTERN extern
  • #endif
  • /* Includes -----------------------------------------------------------------*/
  • #include "platform.h"
  • /* Exported constants -------------------------------------------------------*/
  • /* Exported defines ---------------------------------------------------------*/
  • #define USE_HORIZONTAL      0
  • #define LCD_X_SIZE          240
  • #define LCD_Y_SIZE          320
  • #if USE_HORIZONTAL
  • #define X_MAX_PIXEL         LCD_Y_SIZE
  • #define Y_MAX_PIXEL         LCD_X_SIZE
  • #else
  • #define X_MAX_PIXEL         LCD_X_SIZE
  • #define Y_MAX_PIXEL         LCD_Y_SIZE
  • #endif
  • /* Exported typedef ---------------------------------------------------------*/
  • typedef enum
  • {
  •     TopLeft = 0,
  •     TopCenter,
  •     TopRight,
  •     MiddleLeft,
  •     MiddleCenter,
  •     MiddleRight,
  •     BottomLeft,
  •     BottomCenter,
  •     BottomRight,
  • } eALIGN;
  • typedef struct
  • {
  •     uint16_t x;
  •     uint16_t y;
  •     eALIGN  align;
  •     char    *text;
  • } sTEXT;
  • /* Exported macro -----------------------------------------------------------*/
  • #define RGB(r,g,b) ((((r) & 0x1F) << 11) | (((g) & 0x3F) << 6) | ((b) & 0x1F))
  • /* Exported functions prototypes --------------------------------------------*/
  • EXTERN void LCD_Init(void);
  • #endif
  • /*********************** (C) COPYRIGHT ************************END OF FILE****/
  • 复制代码
    /**
  •   ******************************************************************************
  •   * @file    LCD.c
  •   * @version V1.00
  •   * @author  xld0932
  •   * @brief   
  •   ******************************************************************************
  •   * @attention
  •   *
  •   * Copyright (c) 2019. All rights reserved.
  •   *
  •   ******************************************************************************
  •   */
  • /* Define to prevent recursive inclusion ------------------------------------*/
  • #define __LCD_C__
  • /* Includes -----------------------------------------------------------------*/
  • #include "font.h"
  • #include "LCD.h"
  • #include "ILI9341.h"
  • /* Private constants --------------------------------------------------------*/
  • /* Private defines ----------------------------------------------------------*/
  • #define LCD_DEFAULT_FONT    Font08x16
  • /* Private typedef ----------------------------------------------------------*/
  • /* Private macro ------------------------------------------------------------*/
  • /* Private variables --------------------------------------------------------*/
  • sFONT   *TextFont;
  • uint16_t TextColor = 0;
  • uint16_t BackColor = 0;
  • sTEXT title = {0, 10, MiddleCenter, "MianBaoBan"};
  • /* Private function prototypes ----------------------------------------------*/
  • /* Exported variables -------------------------------------------------------*/
  • /* Exported function prototypes ---------------------------------------------*/
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_SetCursor(uint16_t x, uint16_t y)
  • {        
  •         ILI9341_WriteCommand(0x2A);
  •         ILI9341_WriteWord(x);
  •         ILI9341_WriteCommand(0x2B);
  •         ILI9341_WriteWord(y);
  •         ILI9341_WriteCommand(0x2C);        
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_SetRegion(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
  • {
  •         ILI9341_WriteCommand(0x2A);
  •         ILI9341_WriteWord(x);
  •         ILI9341_WriteWord(x+width);
  •         ILI9341_WriteCommand(0x2B);
  •         ILI9341_WriteWord(y);
  •         ILI9341_WriteWord(y+height);
  •         ILI9341_WriteCommand(0x2C);
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color)
  • {
  •         LCD_SetCursor(x, y);
  •         ILI9341_WriteWord(color);
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_Clear(uint16_t color)               
  • {        
  •     uint32_t i = 0;
  •     LCD_SetRegion(0, 0, X_MAX_PIXEL-1, Y_MAX_PIXEL-1);
  •     for(i = 0; i < X_MAX_PIXEL * Y_MAX_PIXEL; i++)
  •     {
  •         ILI9341_WriteWord(color);
  •     }
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_Setup(void)
  • {
  •     ILI9341_Init();
  •     LCD_LED_SET;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_SetFont(sFONT *font)
  • {
  •     TextFont = font;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • sFONT *LCD_GetFont(void)
  • {
  •     return TextFont;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_SetColor(uint16_t  forecolor, uint16_t  backcolor)
  • {
  •     TextColor = forecolor;
  •     BackColor = backcolor;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_GetColor(uint16_t *forecolor, uint16_t *backcolor)
  • {
  •     *forecolor = TextColor;
  •     *backcolor = BackColor;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_SetTextColor(uint16_t color)
  • {
  •     TextColor = color;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • uint16_t LCD_GetTextColor(void)
  • {
  •     return TextColor;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_SetBackColor(uint16_t color)
  • {
  •     BackColor = color;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • uint16_t LCD_GetBackColor(void)
  • {
  •     return BackColor;
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_DisplayASCII(uint8_t x, uint16_t y, const uint8_t ch)
  • {
  •     uint8_t  i = 0,  j = 0, k = 0, temp = 0;
  •     uint16_t forecolor = 0, backcolor   = 0;
  •     sFONT *font = LCD_GetFont();
  •     LCD_GetColor(&forecolor, &backcolor);
  •     for(i = 0; i < font->width; i++)
  •     {
  •         for(j = 0; j < (font->height / 8); j++)
  •         {
  •             temp = font->table[(ch - 0x20) * (font->width / 8)][i + j * font->width];
  •             for(k = 0; k < 8; k++)
  •             {
  •                 if((temp << k) & 0x80) LCD_DrawPoint(x + i, y + j * 8 + k, forecolor);
  •                 else                   LCD_DrawPoint(x + i, y + j * 8 + k, backcolor);
  •             }
  •         }
  •     }
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_DisplayString(uint16_t x, uint16_t y, char *str)
  • {
  •     sFONT *font = LCD_GetFont();
  •     while (*str != '\0')
  •     {
  •         if(*str == '\n')
  •         {
  •             x = 0; y += font->height;
  •         }
  •         else if(*str == '\r')
  •         {
  •             // do nothing
  •         }
  •         else if(*str == '\t')
  •         {
  •             x += font->width * 4;
  •             x %= X_MAX_PIXEL;
  •         }
  •         else
  •         {
  •             LCD_DisplayASCII(x, y, *str);
  •             x += font->width;
  •         }
  •         if(x >= X_MAX_PIXEL)
  •         {
  •             x = 0; y += font->height;
  •         }
  •         if(y >= Y_MAX_PIXEL)
  •         {
  •             x = 0; y = 0;
  •         }
  •         str++;
  •     }
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_DisplayText(sTEXT text)
  • {
  •     uint16_t x = 0,  width = 0;
  •     width = strlen(text.text) * LCD_GetFont()->width;
  •     switch(text.align)
  •     {
  •         case TopLeft:
  •         case MiddleLeft:
  •         case BottomLeft:
  •             break;
  •         case TopCenter:
  •         case MiddleCenter:
  •         case BottomCenter:
  •             if((text.x + width) < X_MAX_PIXEL)
  •             {
  •                 x = (X_MAX_PIXEL - width) / 2;
  •             }
  •             break;
  •         case TopRight:
  •         case MiddleRight:
  •         case BottomRight:
  •             if((text.x + width) < X_MAX_PIXEL)
  •             {
  •                 x = X_MAX_PIXEL - width;
  •             }
  •             break;
  •         default: break;
  •     }
  •     LCD_DisplayString(x, text.y, text.text);
  • }
  • /**
  • * @brief  :
  • * @param  :
  • * @returns:
  • * @details:
  • */
  • void LCD_Init(void)
  • {
  •     LCD_Setup();
  •     LCD_SetColor(RGB(255,255,0),RGB(255,0,0));
  •     LCD_Clear(LCD_GetBackColor());
  •     LCD_SetFont(&Font16x16);
  •     LCD_DisplayText(title);
  •     LCD_SetFont(&LCD_DEFAULT_FONT);
  •     LCD_DisplayString(0, 50,  "\r\nHardware : Nucleo-L412KB");
  •     LCD_DisplayString(0, 100, "\r\nProject : LCD DEMO");
  •     LCD_DisplayString(0, 125, "\r\nAuthor  : xld0932");
  •     LCD_DisplayString(0, 150, "\r\nDetails : Hardware SPI Drive LCD (ILI9341) Demo");
  • }
  • /*********************** (C) COPYRIGHT ************************END OF FILE****/
  • 复制代码
        5.显示效果

        2.jpg

        6.总结

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

        7.工程代码

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