打印
[活动专区]

【AT-START-F405测评】SPI LCD 驱动移植

[复制链接]
628|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 [鑫森淼焱垚] 于 2024-5-5 16:26 编辑

SPI LCD 简介
此款显示屏是从某宝购买的,型号是 MSP3223,是一款3.2寸IPS彩色液晶显示模块,支持电容触摸。显示模块采用4线制SPI接口,只需要5个IO即可显示显示,240x320标清分辨率,可应用于各种需要屏显功能的产品。



液晶屏参数



引脚确定

开发板上J7接口有 SPI 管脚,查阅原理图 AT_START_F405_V1.0_SCH.pdf,确定其引脚标号。

这里只关注以下3个管脚,将在 AT32 WorkBench 中进行配置。


  • PB13, SCK
  • PC2, MISO
  • PC3, MOSI




对比 SPI LCD 的管脚,最终确定显示屏和开发板的连接关系如下表所示:





WorkBench 创建工程
选择 MCU

双击 AT32_Work_Bench.exe 打开软件,开始一个新设计,按照下图设置 MCU 系列为 AT32F405,MCU 型号为 AT32F405RCT7-7



SPI2 配置参数

选择 Pin布局和配置,依次点击 外设 --> SPI --> SPI2

配置 SPI2 功能为 主机双线单向全双工模式,关闭硬件CS信号

SPI 参数配置如下图所示,Motorola 模式8bit模式MSB优先传输时钟分频系数为3时钟极性为高电平时钟相位为第二个边沿进行数据捕获CRC校验关闭CS信号类型为软件CS




SPI2 GPIO配置
按照下图配置 SPI2 的 GPIO,并且修改了用户标签。对应右侧的红框中的3个管脚。

  • LCD_SCK 为 PB13
  • LCD_MOSI 为 PC3
  • LCD_MISO 为 PC2




SPI2 时钟配置
在时钟配置界面找到 apb1 展开即可看到 SPI2 挂在 APB1 上。当前把 apb1div 设置为4分频,即 SPI2 时钟源为 54MHz。


再回到 SPI2 模式和配置中,其时钟参数配置分频系数为3,即SCK时钟只有 54MHz/3=18MHz 对应上了。



LCD的控制管脚

SPI LCD除了SPI收发数据,还需要额外的管脚控制时序,例如

  • LCD_CS,用一个管脚用作 SPI 片选 -- PC5 管脚;
  • LCD_RST,用一个管脚控制 LCD 复位 -- PB1 管脚;
  • LCD_RS,用一个管脚选择 data/cmd -- PB10 管脚;


这三个管脚的配置如下图所示。



USART1 配置参数

为了重定向 printf() 函数,查看打印日志,这里配置 USART1,配置为异步模式,关闭硬件流控。

串口常用配置选项为:926100, 8bit 数据,无奇偶校验,1个停止位。



USART1 配置GPIO



生成代码

配置完成后,选择菜单栏 生成代码,然后配置项目。

设置项目名称为 AT32F405-LCD

项目位置,根据需要设置到合适的目录。

工具链,这里选择 MDK_V5.

勾选重新生成代码时保留用户代码



WorkBench 安装固件包
如果是第一次生成代码,可能固件包没有安装。点击右侧的固件包管理



点击从本地安装,浏览固件库,直接选择 zip 文件即可。




等待固件包安装成功,之后就可以愉快地使用 WorkBench 创建初始化代码。


关键代码

主流程
AT32 WorkBench 自动创建的初始化代码以 wk_ 开头,如下图中的 wk_usart1_init() , wk_spi2_init() 和 wk_gpio_config() 等函数。

这个先初始化了时钟,USART1 和 SPI2 外设,并配置了管脚,然后调用 LCD_Init() 初始化 LCD 显示屏。

由于我移植了AT32固件库中的 FreeRTOS,所以在 init_tasks() 中创建 LCD 应用程序。




SPI2 初始化
此代码由 WorkBench 生成,配置了 SCK, MOSI, MISO 三个 GPIO 为复用模式,并配置 SPI2 参数。

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  init spi2 function
  * @param  none
  * @retval none
  */
void wk_spi2_init(void)
{
  /* add user code begin spi2_init 0 */

  /* add user code end spi2_init 0 */

  gpio_init_type gpio_init_struct;
  spi_init_type spi_init_struct;

  gpio_default_para_init(&gpio_init_struct);
  spi_default_para_init(&spi_init_struct);

  /* add user code begin spi2_init 1 */

  /* add user code end spi2_init 1 */

  /* configure the SCK pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = LCD_SCK_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_UP;
  gpio_init(LCD_SCK_GPIO_PORT, &gpio_init_struct);

  gpio_pin_mux_config(LCD_SCK_GPIO_PORT, GPIO_PINS_SOURCE13, GPIO_MUX_5);

  /* configure the MISO pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = LCD_MISO_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_UP;
  gpio_init(LCD_MISO_GPIO_PORT, &gpio_init_struct);

  gpio_pin_mux_config(LCD_MISO_GPIO_PORT, GPIO_PINS_SOURCE2, GPIO_MUX_5);

  /* configure the MOSI pin */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pins = LCD_MOSI_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_UP;
  gpio_init(LCD_MOSI_GPIO_PORT, &gpio_init_struct);

  gpio_pin_mux_config(LCD_MOSI_GPIO_PORT, GPIO_PINS_SOURCE3, GPIO_MUX_5);

  /* configure param */
  spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;
  spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
  spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
  spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
  spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_3;
  spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
  spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
  spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
  spi_init(SPI2, &spi_init_struct);

  spi_enable(SPI2, TRUE);

  /* add user code begin spi2_init 2 */

  /* add user code end spi2_init 2 */
}



GPIO 初始化
由于 LCD 除了 SPI2 的 MOSI, MISO 和 SCK 管脚,还需要 LCD_CS, LCD_RST LCD_RS 三个GPIO管脚用以控制命令时序。

这三个 GPIO 的初始化在 WorkBench 中单独配置,生成的代码见 wk_gpio_config()



/**
  * @brief  init gpio_input/gpio_output/gpio_analog/eventout function.
  * @param  none
  * @retval none
  */
void wk_gpio_config(void)
{
  /* add user code begin gpio_config 0 */

  /* add user code end gpio_config 0 */

  gpio_init_type gpio_init_struct;
  gpio_default_para_init(&gpio_init_struct);

  /* add user code begin gpio_config 1 */

  /* add user code end gpio_config 1 */

  /* gpio output config */
  gpio_bits_set(LCD_CS_GPIO_PORT, LCD_CS_PIN);
  gpio_bits_reset(GPIOB, LCD_RST_PIN | LCD_RS_PIN);

  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins = LCD_CS_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(LCD_CS_GPIO_PORT, &gpio_init_struct);

  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins = LCD_RST_PIN | LCD_RS_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);

  /* add user code begin gpio_config 2 */

  /* add user code end gpio_config 2 */
}



LCD 初始化

调用函数 LCD_Init() 进行初始化。

这个函数有3个步骤:

  • 初始化 GPIO,即配置 LCD_CS, LCD_RST LCD_RS 三个管脚初始化。由于已经在 wk_gpio_init() 中初始化了这三个管脚,这里实现为空;
  • 调用 LCD_RESET() 函数,操作 LCD_RST 管脚,拉高50毫秒,再拉低100毫秒,再拉高50毫秒,即可以复位 LCD;
  • 最后是下发 LCD 初始化参数,这些参数由屏幕产商提供。




移植结果

  • 测试程序读取 LCD Driver IC 的 ID,成功读取数值为 0x9341。
  • 在屏幕上显示7种颜色,并读取某个点的颜色值并进行比对,比对成功。






使用特权

评论回复
沙发
chenqianqian| | 2024-5-10 20:06 | 只看该作者
现在TFT LCE屏幕真的是白菜价了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

67

帖子

0

粉丝