话不多说,直接开讲。 单片机使用的是GD32F450XX 主要功能是用GD32F450的EXMC总线与FPGA通信。初次使用所以网上差了很多资料,其实GD32F450的EXMC与STM32的FSMC相差无几,与FPGA通信我是将FPGA模拟成SRAM进行通信。具体单片机型号是 GD32F450ZIT6。 1,因为官方例程只有SDRAM的初始化所以我贴下SRAM的初始化代码:
void exmc_sram_init()
{
exmc_norsram_parameter_struct sdram_init_struct;
exmc_norsram_timing_parameter_struct read_write_timing;
uint32_t command_content = 0, bank_select;
uint32_t timeout = SDRAM_TIMEOUT;
rcu_periph_clock_enable(RCU_EXMC);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOE);
rcu_periph_clock_enable(RCU_GPIOF);
rcu_periph_clock_enable(RCU_GPIOG);
rcu_periph_clock_enable(RCU_GPIOH);
gpio_af_set(GPIOB, GPIO_AF_12, GPIO_PIN_7 );
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_7);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
gpio_af_set(GPIOD, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4 |
GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 |
GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4 |
GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 |
GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4 |
GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 |
GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
gpio_af_set(GPIOE, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | 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_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | 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_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | 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_af_set(GPIOF, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_12 | GPIO_PIN_13 |
GPIO_PIN_14 | GPIO_PIN_15);
gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_12 | GPIO_PIN_13 |
GPIO_PIN_14 | GPIO_PIN_15);
gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |
GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_12 | GPIO_PIN_13 |
GPIO_PIN_14 | GPIO_PIN_15);
gpio_af_set(GPIOG, GPIO_AF_12, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
read_write_timing.asyn_address_setuptime = 0x0U;
read_write_timing.asyn_address_holdtime = 0x0U;
read_write_timing.asyn_data_setuptime = 0x08U;
read_write_timing.bus_latency = 0xFU;
read_write_timing.syn_clk_division = EXMC_SYN_CLOCK_RATIO_16_CLK;
read_write_timing.syn_data_latency = EXMC_DATALAT_17_CLK;
read_write_timing.asyn_access_mode = EXMC_ACCESS_MODE_A;
sdram_init_struct.norsram_region = EXMC_BANK0_NORSRAM_REGION0;
sdram_init_struct.address_data_mux = DISABLE;
sdram_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM;
sdram_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
sdram_init_struct.burst_mode = DISABLE;
sdram_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
sdram_init_struct.wrap_burst_mode = DISABLE;
sdram_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
sdram_init_struct.memory_write = ENABLE;
sdram_init_struct.nwait_signal = DISABLE;
sdram_init_struct.extended_mode = DISABLE;
sdram_init_struct.asyn_wait = DISABLE;
sdram_init_struct.write_mode = EXMC_ASYN_WRITE;
sdram_init_struct.read_write_timing = &read_write_timing;
sdram_init_struct.write_timing = &read_write_timing;
exmc_norsram_init(&sdram_init_struct);
exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION0);
delay_1ms(10);
}
2,因为用的是EXMC的异步通信,一开始对这些概念不是很熟悉,所以自己弄了半天,最后查官方用户手册找到了一张时序表: 读数据函数:
void sdram_readbuffer_16(uint32_t sdram_device,uint16_t* pbuffer, uint32_t readaddr, uint32_t numtowrite)
{
uint32_t temp_addr;
__IO uint32_t write_addr_prt = readaddr;
temp_addr = SRAM_DEVICE0_ADDR;
for(; numtowrite != 0; numtowrite--){
*pbuffer++ = *(uint16_t*) (temp_addr + write_addr_prt);
write_addr_prt += 2;
}
}
首先单片机不断发送读地址命令,然后用示波器看看这些引脚上有没有对应的时序输出,如果有了的话再去找FPGA工程师或者自己根据这个时序来读数据,读数据的时候依据EXMC_NOE的电平变换将对应地址的数据放到数据引脚上,这样就能获取数据了
总结: 不要把EXMC看的很复杂,根据用户手册配置好之后读写数据非常方便,就跟读单片机内存一样。 而与FPGA通信用到的EXMC更简单,因为FPGA可以自行编程,所以只需要你这边地址,数据,信号线上有数据,那边就能更改时序进行处理!所以困难不可怕,相信自己!
|