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,gpiofsmc介绍
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上显示其他功能的状态信息。

继电器的作用是什么?继电器是什么?
关于PWM脉冲宽度调制,你懂多少?
安科瑞无线测温产品在浙江某半导体项目的应用
防水电动牙刷该如何选择,防水性能到底有多重要
8位单片机NY8B062F概述
FSMC工程 ILI9325驱动LCD
三星S8未发先火, 三星这次能否走出爆炸阴影?
联通和电信在4G增量上逆转移动
美国准备推出FWA 5G家庭互联网服务
雄安新区供电公司发布1+3+1+1电网标准体系构建一流绿色智能电网梦
魅族16s正式发布
NASA资助太空3D打印建筑计划,旨在开发在月球进行机器人建筑的方法
贸泽备货Microchip Hello FPGA套件,专为FPGA领域经验不足的终端用户而开发
工程能力是关键,自动驾驶无图方案加速进入前装量产
卫星射频前端的性能、功能要求及应用解决方案
科大讯飞语音控制模块怎么用
5G风生水起,中国主动权话语权显著提升
采用PCA82C250芯片的照明控制系统及短距离无线通信介绍
漏极开路(OD)原理说解
高超声速飞行器输入受限反步控制研究探讨