【GD32】外部存储器控制器(EXMC)驱动16位8080时序并口屏(GD32F470ZGT6)

1. 简介

        GD32F4系列中的EXMC外设可以用来驱动外部的储存器,如SDRAM、SRAM等等,在之前的文章中有介绍其用法。

        但EXMC还有一种比较特别的玩法就是用来驱动8080并口屏;之前讲过,EXMC的工作原理就是把外部的储存器地址映射到芯片内部的一段地址中。而显示屏的驱动其实也是把数据写到显示芯片的RAM中,这个RAM本质还是储存器的一种,因此我们也可以用EXMC外设把显示芯片的RAM映射到单片机中,这样可以大大提高通讯速度。

2. 硬件设计

        下面的例程是基于我之前的一个小项目,项目的介绍已经开源在立创开源社区中了,跳转链接

        开发板使用的是立创梁山派,开发板上带有一个8080并口屏接口;屏幕买的是一块IPS的并口屏,屏幕驱动芯片是ST7796U

        因为屏幕是支持触摸的,所以忽略掉I2C部分的管脚。LCD_D0~16为显示屏的16根数据管脚,LCD_CS为片选线,LCD_DC脚控制数据或命令传输,LCD_WR为写使能管脚,LCD_RD为读使能管脚,LCD_BLC为显示屏背光使能。

3. 原理

        驱动屏幕使用的是EXMC的NOR Flash模式,因此使用的是EXMC的Bank0,总共256MB;Bank0又分为了4个Region,每个Region有64MB。梁山派的这个8080并口引出的是Region3的片选线(EXMC_NE3)

         由参考手册可以查看Region3的基地址映射,从0x6C000000开始。接下来我们要确认命令地址和数据地址,LCD_DC线是连接到EXMC_A10上的;屏幕驱动芯片的RAM是16位宽度,根据参考手册,使用16位宽度时,EXMC的HADDR[25:1]与EXMC_A[24:0]连接,另外LCD_DC高电平表示数据传输,低电平表示数据传输;综上可以得出数据地址为0x6C000800,命令地址为0x6C000000

        针对NOR Flash,EXMC提供了非常多的驱动时序,这块屏幕使用的是模式B来驱动,它的读时序和写时序如下面。

        芯片读过程,EXMC先拉低片选(EXMC_NEx);拉低输出使能(EXMC_NOE),其实就是读使能;拉高写使能(EXMC_NWE);在经过地址建立时间后拉高地址有效线(我们没有用到);再经过数据建立时间后就可以读取到稳定的数据了。

        芯片写过程差不多, 先拉低片选(EXMC_NEx);拉高输出使能(EXMC_NOE);拉低写使能(EXMC_NWE);在经过地址建立时间后拉高地址有效线(我们没有用到);经过地址建立时间后EXMC开始通过数据线(EXMC_Dx)向芯片输出数据;经过数据建立时间后拉高写使能;再经过一个HCLK时钟周期再恢复管脚状态。

         对于模式B的时序,我们要设置其地址建立时间(WASET)和数据建立时间(WDSET),这两个时间可以在屏幕驱动芯片的数据手册中找到。

        上面的T_{AST}T_{DST}就是地址建立时间和数据建立时间,最小值分别为0ns和10ns

4. 代码

        先看GPIO的初始化。代码有省略,因为都大差不差。主要注意的是设置复用模式,EXMC的复用组为GPIO_AF_12,EXMC的所有管脚最好上拉,速度设置为最高速。

static void ST7796_GPIOInit(void)
{
	/* config GPIO */
	rcu_periph_clock_enable(ST7796_D0_CLK);
    ...

	gpio_mode_set(ST7796_D0_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, ST7796_D0_PIN);
	gpio_output_options_set(ST7796_D0_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, ST7796_D0_PIN);
	gpio_af_set(ST7796_D0_PORT, EXMC_AF, ST7796_D0_PIN);
    ...
}

        比较关键的是EXMC的初始化。

static void ST7796_EXMCInit(void)
{
	exmc_norsram_parameter_struct exmc_init_struct = {0};
	exmc_norsram_timing_parameter_struct exmc_timing_struct = {0};
	
	/* config FMC clock */
	rcu_periph_clock_enable(EXMC_CLK);
	
	exmc_timing_struct.asyn_access_mode = EXMC_ACCESS_MODE_B;
	exmc_timing_struct.asyn_address_setuptime = 5;  // 5 / 240MHz = 20ns
	exmc_timing_struct.asyn_data_setuptime = 4;  // (4 + 1) / 240MHz = 20ns

	exmc_init_struct.address_data_mux = DISABLE;
	exmc_init_struct.asyn_wait = DISABLE;
	exmc_init_struct.burst_mode = DISABLE;
	exmc_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
	exmc_init_struct.extended_mode = DISABLE;
	exmc_init_struct.memory_type = EXMC_MEMORY_TYPE_NOR;
	exmc_init_struct.memory_write = ENABLE;
	exmc_init_struct.norsram_region = EXMC_BANK0_NORSRAM_REGION3;
	exmc_init_struct.nwait_signal = DISABLE;
	exmc_init_struct.wrap_burst_mode = DISABLE;
	exmc_init_struct.write_mode = EXMC_ASYN_WRITE;
	exmc_init_struct.read_write_timing = &exmc_timing_struct;
	exmc_init_struct.write_timing = &exmc_timing_struct;
	
	exmc_norsram_init(&exmc_init_struct);
	exmc_norsram_enable(EXMC_BANK0_REGIONx);
}

         先初始化exmc_norsram_timing_parameter_struct结构体配置时序;asyn_access_mode成员设置异步模式,这里为模式B;asyn_address_setuptime设置地址建立时间,这里设置为5,即20ns;asyn_data_setuptime设置数据建立时间,这里设置为4,也是20ns;这两个时间的话可以适当设得大点,因为硬件的体质是有差异的,设得离理论值很接近的话有可能会通讯失败

        再初始化exmc_norsram_parameter_struct结构体配置EXMC; address_data_mux设置地址线复用,这里不复用;aync_wait设置异步等待,这里不等待;burst_mode设置突发模式,这里不使用;databus_width设置数据宽度,这里为16位;extended_mode设置扩展模式,这里不使用;memory_type设置储存器类型,这里为NOR Flash;memory_write设置储存器写,这里使能;norsram_region设置使用的Region;这里设置为Region3;nwait_signal设置NWAIT信号,这里不使用;wrap_burst_mode设置突发模式中的数据包裹,这里不使用;write_mode设置写模式,这里使用异步模式;read_write_timing和write_timing填之前初始化好的时序结构体。

        最后初始化并使能EXMC外设就可以使用了。对屏幕芯片读和写操作只需要像操作指针一样即可。

#define EXMC_Addr_ST7796_CMD		((uint32_t)0x6C000000)
#define EXMC_Addr_ST7796_DATA		((uint32_t)0x6C000800)  // 0x6C000000 | (1 << (1 + Ax))

__inline void ST7796_WriteCmd(uint16_t cmd)
{
	*( __IO uint16_t*)(EXMC_Addr_ST7796_CMD) = cmd;
}


__inline void ST7796_WriteData(uint16_t data)
{
	*( __IO uint16_t*)(EXMC_Addr_ST7796_DATA) = data;
}

        当然我们还需要对屏幕芯片寄存器进行初始化后才能,执行其他的操作,但这里就不介绍了,因为每个芯片的寄存器都不同,只需要根据芯片手册进行编写即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

马浩同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值