赞
踩
话不多说,直接开讲。
单片机使用的是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; /* enable EXMC clock*/ 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); /* common GPIO configuration */ /* NL(PB7), pin configuration */ 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); /* D2(PD0),D3(PD1),CLK(PD3),NOE(PD4),NWE(PD5),NWAIT(PD6),NE0(PD7),D13(PD8),D14(PD9),D15(PD10),D0(PD14),D1(PD15) pin configuration */ 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); /* NBL0(PE0),NBL1(PE1),D4(PE7),D5(PE8),D6(PE9),D7(PE10),D8(PE11),D9(PE12),D10(PE13),D11(PE14),D12(PE15) pin configuration */ 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); /* A0(PF0),A1(PF1),A2(PF2),A3(PF3),A4(PF4),A5(PF5),A6(PF12),A7(PF13),A8(PF14),A9(PF15) pin configuration */ 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); /* A10(PG0),A11(PG1),A12(PG2),A13(PG3), pin configuration */ 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); /* configure read/write timing */ read_write_timing.asyn_address_setuptime = 0x0U; //地址建立时间(ADDSET)为1个HCLK 1/36M=27ns read_write_timing.asyn_address_holdtime = 0x0U; //地址保持时间(ADDHLD)模式A未用到 read_write_timing.asyn_data_setuptime = 0x08U; //数据保持时间(DATAST)为9个HCLK 6*9=54ns 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; /* configure the structure with default values */ sdram_init_struct.norsram_region = EXMC_BANK0_NORSRAM_REGION0; //这里我们使用NE0,也就对应BTCR[0],[1]。 sdram_init_struct.address_data_mux = DISABLE; //地址和数据复用数据线 sdram_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM; //SRAM sdram_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B; //存储器数据宽度为16bit sdram_init_struct.burst_mode = DISABLE; //突发访问模式 sdram_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW; //设置WAIT信号的有效电平 sdram_init_struct.wrap_burst_mode = DISABLE; //是否使用回环模式 sdram_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE; //设置WAIT信号有效时机 sdram_init_struct.memory_write = ENABLE; //存储器写使能 sdram_init_struct.nwait_signal = DISABLE; //是否使用WAIT信号 sdram_init_struct.extended_mode = DISABLE; //是否使用扩展模式,扩展模式用于访问不同读写操作时序的存储器 sdram_init_struct.asyn_wait = DISABLE; /*!< enable or disable the asynchronous wait function */ sdram_init_struct.write_mode = EXMC_ASYN_WRITE; /*!< asynchronous write mode */ 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; /* select the base address according to EXMC_Bank */ // if(sdram_device == EXMC_SDRAM_DEVICE0){ // temp_addr = SDRAM_DEVICE0_ADDR; // }else{ // temp_addr = SDRAM_DEVICE1_ADDR; // } temp_addr = SRAM_DEVICE0_ADDR; /* while there is data to read */ for(; numtowrite != 0; numtowrite--){ /* read a byte from the memory */ *pbuffer++ = *(uint16_t*) (temp_addr + write_addr_prt); /* increment the address */ write_addr_prt += 2; } }
首先单片机不断发送读地址命令,然后用示波器看看这些引脚上有没有对应的时序输出,如果有了的话再去找FPGA工程师或者自己根据这个时序来读数据,读数据的时候依据EXMC_NOE的电平变换将对应地址的数据放到数据引脚上,这样就能获取数据了
总结:
不要把EXMC看的很复杂,根据用户手册配置好之后读写数据非常方便,就跟读单片机内存一样。
而与FPGA通信用到的EXMC更简单,因为FPGA可以自行编程,所以只需要你这边地址,数据,信号线上有数据,那边就能更改时序进行处理!所以困难不可怕,相信自己!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。