FSMC工程 ILI9325驱动LCD

2024-02-24 07:48
文章标签 驱动 工程 lcd fsmc ili9325

本文主要是介绍FSMC工程 ILI9325驱动LCD,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

开发环境:

STM32F103ZET6      STM32CubeMX      Keil5

使用STM32CubeMx创建FSMC工程,生成后使用keil5创建TFT-LCD驱动程序,实现在LCD上显示。

网上有一些配置FSMC的,有驱动TFT-LCD的程序,不过大多是标准库的,有一些找到的驱动程序可是试了试,没有效果,所以自己修改。

现在有四块屏,1602(显示一些数字),128604(显示字符,简单图片),2.4寸TFT液晶屏(ili9325驱动,可触摸,240*320),3.5寸TFT(hx8357驱动,可触摸),此篇只写2.4寸TFT液晶屏,基本方法是修改厂家提供的使用FSMC的驱动文件,将标准库文件修改为在HAL库中可以运行的文件,因为之前将12864的标准库程序修改为HAL库程序成功,所以可以借鉴。


1602



12864



12864



3.5TFT-LCD



图片发自简书App



图片发自简书App



图片发自简书App

在网上使用STM32CubeMx配置FSMC的工程有一些,不过存在问题

使用STM32CubeMx配置FSMC,GPIO

FSMC介绍

1. STM32CubeMx如何配置FSMC

按照上一篇的方法创建一个工程后,在引脚设置页面的左侧有FSMC的配置,不过STM32CubeMx的版本不同,STM芯片的选择不同,FSMC配置选项也不同,



FSMC

FSMC(16位)主要配置的引脚为

      CS 液晶屏片选    NE4

      RS  即LCD Register Select  PG0  (A10)

      WR  写信号    PD5

      RD 读信号    PD4

      以及16位数据总线,高八位和第八位

不过液晶屏会有BL背光控制和RST复位引脚,需要在配置完FSMC后再添加两个输出引脚。

那么问题来了,FSMC配置中的内存类型怎么选,是选SRAM还是其他?

      我觉得选图中所示可以直接选择寄存器数据选择信号引脚为A10即PG0,这符合我的彩屏的实际情况,具体怎么选要先看一下自己彩屏正常工作时配置了那些引脚。

在配置了FSMC后再经过一些小的修改就可以生成工程,添加自己的代码。

注意:

使用不同驱动的彩屏在初始化时对寄存器的操作都是不同的,一定要找到可以在自己彩屏上正常运行的程序,因为在初始化函数中都会对很多寄存器写入不同的值,错一个可能就无法初始化成功。

使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11,A10作为数据命令区分线,注意设置时STM32内部会右移一位对其! 111110=0X3E。

因为在标准库中和HAL库中数据类型本质相同,但表示不同,比如在标准库中为u16,不过在HAL库中却是uint16_t,需要注意。

在标准库中GPIO和FSMC相关结构体具体定义是不同的,也需要修改。

基本步骤:

修改向寄存器地址写数据和命令的函数

注意是否在STM32CUBEMX中配置好时钟,时钟配置是很重要的

修改LCD的初始化函数

修改GPIO初始化函数,还要使能相关引脚时钟

注意除了FSMC相关引脚配置为复用推挽输出外,PB0和PC5需要配置为推挽输出

修改FSMC初始函数,需要使能FSMC时钟

需要注意的是在标准库中和在HAL库中FSMC的配置有不小的不同,首先是FSMC相关结构体和标准库中不同,有一些在标准库中可以配置的选项在HAL库中并不存在,还有FSMC配置完成后初始化FSMC的函数和标准库中也有很大不同,如果使用了两个FSMC_NORSRAM_TimingTypeDef,则要使用HAL_SRAM_Init()函数进行初始化。还需要注意的是要使能BANK1。

修改复位函数

还有其他一些修改,改动不大

rebuild工程,如果没有错误,在main函数中调用LCD初始化函数,就可以直接使用标准库中可以使用的绘制函数了。

修改后的GPIO初始化函数

void LCD_GPIOInit(void)

{

GPIO_InitTypeDef GPIO_InitStruct;

//FSMC_NORSRAM_InitTypeDef  FSMC_NORSRAMInitStructure;

FSMC_NORSRAM_TimingTypeDef  readWriteTiming;

FSMC_NORSRAM_TimingTypeDef  writeTiming;

hsram2.Instance = FSMC_NORSRAM_DEVICE;

hsram2.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;

__HAL_RCC_FSMC_CLK_ENABLE();//ʹÄÜFSMCʱÖÓ

//RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE); //ʹÄÜFSMCʱÖÓ

__HAL_RCC_GPIOC_CLK_ENABLE();

__HAL_RCC_GPIOB_CLK_ENABLE();

__HAL_RCC_GPIOG_CLK_ENABLE();

__HAL_RCC_GPIOE_CLK_ENABLE();

__HAL_RCC_GPIOD_CLK_ENABLE();

__HAL_RCC_GPIOA_CLK_ENABLE();

//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOG|RCC_APB2Periph_AFIO,ENABLE);//ʹÄÜPORTB,D,E,GÒÔ¼°AFIO¸´Óù¦ÄÜʱÖÓ

/*Configure GPIO pin : PC5 */

GPIO_InitStruct.Pin = GPIO_PIN_5;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;

HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

/*Configure GPIO pin : PB0 */

GPIO_InitStruct.Pin = GPIO_PIN_0;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* GPIO_InitStruct */

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_12;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

/* GPIO_InitStruct */

GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10

|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14

|GPIO_PIN_15;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

/* GPIO_InitStruct */

GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14

|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4

|GPIO_PIN_5;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

readWriteTiming.AddressSetupTime = 0x01; //µØÖ·½¨Á¢Ê±¼ä£¨ADDSET£©Îª2¸öHCLK 1/36M=27ns

readWriteTiming.AddressHoldTime = 0x00; //µØÖ·±£³Öʱ¼ä£¨ADDHLD£©Ä£Ê½AδÓõ½

readWriteTiming.DataSetupTime = 0x0f; // Êý¾Ý±£´æʱ¼äΪ16¸öHCLK,ÒòΪҺ¾§Çý¶¯ICµÄ¶ÁÊý¾ÝµÄʱºò£¬ËٶȲ»ÄÜÌ«¿ì£¬ÓÈÆä¶Ô1289Õâ¸öIC¡£

readWriteTiming.BusTurnAroundDuration = 0x00;

readWriteTiming.CLKDivision = 0x00;

readWriteTiming.DataLatency = 0x00;

readWriteTiming.AccessMode = FSMC_ACCESS_MODE_A; //ģʽA

writeTiming.AddressSetupTime = 0x02; //0x01 µØÖ·½¨Á¢Ê±¼ä£¨ADDSET£©Îª1¸öHCLK

writeTiming.AddressHoldTime = 0x00; //µØÖ·±£³Öʱ¼ä£¨A

writeTiming.DataSetupTime = 0x05; 0x03 Êý¾Ý±£´æʱ¼äΪ4¸öHCLK

writeTiming.BusTurnAroundDuration = 0x00;

writeTiming.CLKDivision = 0x00;

writeTiming.DataLatency = 0x00;

writeTiming.AccessMode = FSMC_ACCESS_MODE_A; //ģʽA

hsram2.Init.NSBank = FSMC_NORSRAM_BANK4;//  ÕâÀïÎÒÃÇʹÓÃNE4 £¬Ò²¾Í¶ÔÓ¦BTCR[6],[7]¡£

hsram2.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE; // ²»¸´ÓÃÊý¾ÝµØÖ·

hsram2.Init.MemoryType =FSMC_MEMORY_TYPE_SRAM;// FSMC_MemoryType_SRAM;  //SRAM

hsram2.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;//´æ´¢Æ÷Êý¾Ý¿í¶ÈΪ16bit

hsram2.Init.BurstAccessMode =FSMC_BURST_ACCESS_MODE_DISABLE;// FSMC_BurstAccessMode_Disable;

hsram2.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;

hsram2.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;

hsram2.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;

hsram2.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;

hsram2.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE; //  ´æ´¢Æ÷дʹÄÜ

hsram2.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;

hsram2.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE; // ¶ÁдʹÓò»Í¬µÄʱÐò

hsram2.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;

//FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //¶ÁдʱÐò

//FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming;  //дʱÐò

if (HAL_SRAM_Init(&hsram2, &readWriteTiming, &writeTiming) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

__FSMC_NORSRAM_ENABLE(FSMC_NORSRAM_DEVICE,FSMC_NORSRAM_BANK4);

}

修改后的LCD初始化函数

void LCD_Init(void)

{

LCD_GPIOInit();

LCD_RESET();

//************* Start Initial Sequence **********//

LCD_WriteReg(0x00E5,0x78F0);

LCD_WriteReg(0x0001,0x0100);

LCD_WriteReg(0x0002,0x0700);

LCD_WriteReg(0x0003,0x1030);

LCD_WriteReg(0x0004,0x0000);

LCD_WriteReg(0x0008,0x0202);

LCD_WriteReg(0x0009,0x0000);

LCD_WriteReg(0x000A,0x0000);

LCD_WriteReg(0x000C,0x0000);

LCD_WriteReg(0x000D,0x0000);

LCD_WriteReg(0x000F,0x0000);

//power on sequence VGHVGL

LCD_WriteReg(0x0010,0x0000);

LCD_WriteReg(0x0011,0x0007);

LCD_WriteReg(0x0012,0x0000);

LCD_WriteReg(0x0013,0x0000);

LCD_WriteReg(0x0007,0x0000);

//vgh

LCD_WriteReg(0x0010,0x1690);

LCD_WriteReg(0x0011,0x0227);

//delay_ms(100);

//vregiout

LCD_WriteReg(0x0012,0x009D); //0x001b

//delay_ms(100);

//vom amplitude

LCD_WriteReg(0x0013,0x1900);

//delay_ms(100);

//vom H

LCD_WriteReg(0x0029,0x0025);

LCD_WriteReg(0x002B,0x000D);

//gamma

LCD_WriteReg(0x0030,0x0007);

LCD_WriteReg(0x0031,0x0303);

LCD_WriteReg(0x0032,0x0003);// 0006

LCD_WriteReg(0x0035,0x0206);

LCD_WriteReg(0x0036,0x0008);

LCD_WriteReg(0x0037,0x0406);

LCD_WriteReg(0x0038,0x0304);//0200

LCD_WriteReg(0x0039,0x0007);

LCD_WriteReg(0x003C,0x0602);// 0504

LCD_WriteReg(0x003D,0x0008);

//ram

LCD_WriteReg(0x0050,0x0000);

LCD_WriteReg(0x0051,0x00EF);

LCD_WriteReg(0x0052,0x0000);

LCD_WriteReg(0x0053,0x013F);

LCD_WriteReg(0x0060,0xA700);

LCD_WriteReg(0x0061,0x0001);

LCD_WriteReg(0x006A,0x0000);

//

LCD_WriteReg(0x0080,0x0000);

LCD_WriteReg(0x0081,0x0000);

LCD_WriteReg(0x0082,0x0000);

LCD_WriteReg(0x0083,0x0000);

LCD_WriteReg(0x0084,0x0000);

LCD_WriteReg(0x0085,0x0000);

//

LCD_WriteReg(0x0090,0x0010);

LCD_WriteReg(0x0092,0x0600);

LCD_WriteReg(0x0007,0x0133);

LCD_WriteReg(0x00,0x0022);//

LCD_SetParam();//ÉèÖÃLCD²ÎÊý

//LCD_LED=1;//µãÁÁ±³¹â

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);

LCD_Clear(WHITE);

}

修改后在main函数中使用绘图函数时要注释掉原有的GPIO和FSMC初始化函数。

测试结果:



图片发自简书App



图片发自简书App


修改后即可以在STM32CubeMX中配置后就可以将之前修改好的文件直接添加到工程中使用,这样即可在LCD上显示其他功能的状态信息。

这篇关于FSMC工程 ILI9325驱动LCD的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/741431

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

Jenkins构建Maven聚合工程,指定构建子模块

一、设置单独编译构建子模块 配置: 1、Root POM指向父pom.xml 2、Goals and options指定构建模块的参数: mvn -pl project1/project1-son -am clean package 单独构建project1-son项目以及它所依赖的其它项目。 说明: mvn clean package -pl 父级模块名/子模块名 -am参数

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

二、Maven工程的创建--JavaSEJavaEE

1、idea创建Maven JavaSE工程:  2、idea创建Maven JavaEE工程:   (1)手动创建 (2)插件方式创建 在idea里安装插件JBLJavaToWeb; 选择需要生成的项目文件后,右击: 项目的webapp文件夹出现小蓝点,代表成功。

三、Maven工程的构建

首先,创建和构建是两个概念。 构建是指将源代码、依赖库和资源文件等转换为可执行或可部署的应用程序的过程。 在这个过程中包括编译源代码、链接依赖库、打包和部署等多个步骤。 项目构建是软件开发过程中至关重要的一部分,它能够大大提高软件开发效率,使得开发人员更加专注于应用程序的开发和维护,而不必关心应用程序的构建细节。 同时,项目构建还能将多人写的代码聚合,并能够自动化项目的构建和部署,

我在高职教STM32——准备HAL库工程模板(1)

新学期开学在即,又要给学生上 STM32 嵌入式课程了。这课上了多年了,一直用的都是标准库来开发,已经驾轻就熟了。人就是这样,有了自己熟悉的舒适圈,就很难做出改变,老师上课也是如此,排斥新课和不熟悉的内容。显然,STM32 的开发,HAL 库已是主流,自己其实也在使用,只不过更换库就意味着教学内容有很大变化,自己也就迟迟没有迈出调整这一步。现在,是时候做出变化了,笔者计划保持教学项

电脑驱动分类

电脑驱动程序(驱动程序)是操作系统与硬件设备之间的桥梁,用于使操作系统能够识别并与硬件设备进行通信。以下是常见的驱动分类: 1. 设备驱动程序 显示驱动程序:控制显卡和显示器的显示功能,负责图形渲染和屏幕显示。 示例:NVIDIA、AMD 显示驱动程序。打印机驱动程序:允许操作系统与打印机通信,控制打印任务。 示例:HP、Canon 打印机驱动程序。声卡驱动程序:管理音频输入和输出,与声卡硬件