zynq裸机和linux spidev操作W25Q16

张开发
2026/4/16 21:44:54 15 分钟阅读

分享文章

zynq裸机和linux spidev操作W25Q16
写使能读取地址0x000051的值发 03 00 00 51收 0x74BDlinux_spi_oled_system.tcl注意事项Vivado 自动生成了两个未使用的片选信号。请在 system_wrapper.v 文件中删除与这两个片选相关的代码以避免综合报错。未使用的片选信号包括output SPI_0_0_ss1_o;output SPI_0_0_ss2_o;PIN.xdc## SPI SCLKset_property PACKAGE_PIN M15[get_ports SPI_0_0_sck_io]set_property IOSTANDARD LVCMOS33[get_ports SPI_0_0_sck_io]## SPI MOSIset_property PACKAGE_PIN L16[get_ports SPI_0_0_io0_io]set_property IOSTANDARD LVCMOS33[get_ports SPI_0_0_io0_io]## SPI MISOset_property PACKAGE_PIN K14[get_ports SPI_0_0_io1_io]set_property IOSTANDARD LVCMOS33[get_ports SPI_0_0_io1_io]## SPI CSset_property PACKAGE_PIN J14[get_ports SPI_0_0_ss_io]set_property IOSTANDARD LVCMOS33[get_ports SPI_0_0_ss_io]## DCset_property PACKAGE_PIN N20[get_ports{GPIO_EMIO_tri_io[0]}]set_property IOSTANDARD LVCMOS33[get_ports{GPIO_EMIO_tri_io[0]}]## RESset_property PACKAGE_PIN U19[get_ports{GPIO_EMIO_tri_io[1]}]set_property IOSTANDARD LVCMOS33[get_ports{GPIO_EMIO_tri_io[1]}]代码裸机,驱动和应用是三个独立运行的例子裸机main.c#includexparameters.h#includexspips.h#includexil_printf.h#includesleep.h#defineSPI_DEVICE_IDXPAR_XSPIPS_0_DEVICE_ID#defineCS_ASSERT0x00// 片选引脚激活低电平使能SPI设备通信#defineCS_RELEASE0x0F// 片选引脚释放高电平禁用SPI设备通信#defineW25Q_WREN0x06// 写使能命令Write Enable允许写操作必须在进行写操作之前先发送此命令#defineW25Q_RDSR0x05// 读取状态寄存器命令Read Status Register用来读取闪存的状态寄存器#defineW25Q_PP0x02// 页编程命令Page Program用于将数据写入闪存的指定页#defineW25Q_READ0x03// 读取数据命令Read Data用于从闪存中读取数据#defineW25Q_SE0x20// 扇区擦除命令Sector Erase用于擦除闪存中的指定扇区#defineSR_WIP0x01#defineTEST_ADDR0x000051#defineTEST_VALUE0x74staticXSpiPs SpiInstance;/* CS */staticinlinevoidcs_low(){XSpiPs_SetSlaveSelect(SpiInstance,CS_ASSERT);usleep(2);}staticinlinevoidcs_high(){XSpiPs_SetSlaveSelect(SpiInstance,CS_RELEASE);usleep(5);}/* SR */staticu8read_sr(void){u8 tx[2]{W25Q_RDSR,0};u8 rx[2]{0};cs_low();XSpiPs_PolledTransfer(SpiInstance,tx,rx,2);cs_high();returnrx[1];}staticvoidwait_busy(void){while(read_sr()SR_WIP){usleep(100);}}/* WREN */staticvoidwrite_enable(void){u8 cmdW25Q_WREN;cs_low();XSpiPs_PolledTransfer(SpiInstance,cmd,NULL,1);cs_high();}/* 擦除 */staticvoiderase_sector(u32 addr){u8 tx[4];write_enable();tx[0]W25Q_SE;tx[1](addr16);tx[2](addr8);tx[3]addr;cs_low();XSpiPs_PolledTransfer(SpiInstance,tx,NULL,4);cs_high();wait_busy();}/* 写 */staticvoidwrite_byte(u32 addr,u8 data){u8 tx[5];write_enable();tx[0]W25Q_PP;tx[1](addr16);tx[2](addr8);tx[3]addr;tx[4]data;cs_low();XSpiPs_PolledTransfer(SpiInstance,tx,NULL,5);cs_high();wait_busy();}/* 读 */staticu8read_byte(u32 addr){u8 tx[5];u8 rx[5]{0};tx[0]W25Q_READ;tx[1](addr16);tx[2](addr8);tx[3]addr;tx[4]0x00;cs_low();XSpiPs_PolledTransfer(SpiInstance,tx,rx,5);cs_high();returnrx[4];}/* main */intmain(void){XSpiPs_Config*cfg;u8 wrTEST_VALUE;u8 rd;xil_printf(\r\n SPI WRITEREAD LOOP \r\n);cfgXSpiPs_LookupConfig(SPI_DEVICE_ID);if(!cfg)return-1;if(XSpiPs_CfgInitialize(SpiInstance,cfg,cfg-BaseAddress)!XST_SUCCESS)return-1;XSpiPs_SetOptions(SpiInstance,XSPIPS_MASTER_OPTION|XSPIPS_FORCE_SSELECT_OPTION);XSpiPs_SetClkPrescaler(SpiInstance,XSPIPS_CLK_PRESCALE_64);cs_high();usleep(1000);while(1){xil_printf(\r\n--- cycle ---\r\n);/* 1. 擦 */xil_printf(erase...\r\n);erase_sector(TEST_ADDR);/* 2. 写 */xil_printf(write...\r\n);write_byte(TEST_ADDR,wr);while(1){/* 3. 读 */rdread_byte(TEST_ADDR);xil_printf(WRITE0x%02X READ0x%02X %s\r\n,wr,rd,(wrrd)?OK:FAIL);sleep(1);}}}驱动myw25q16.c应用main.c

更多文章