xilinx sdk 之SPI配置
使用ZYNQ PS端的SPI接口配置图像 cmos芯片
第一步:看原理图,看看原理图的cmos芯片的接口接在PL的那个管脚上的。有几个管脚
第二步:打开zynq ps,选择SD0 MIO 40- 45
选择UART0 选择 MIO 46-47
SPI0 选择 EMIO 因为ps接口连接到了PL侧
选择GPIO中的EMIO,因为要配置摄像头的复位引脚,复位引脚连接PL侧,要使用EMIO,先选择一个就可以了。
第三步:引出管脚,引出需要的管脚 ,选择make externel
第四步:可以修改管脚名,方便认识
第五步:create hdl wrapper,创建硬件描述
第六步:因为使用了gpio,所以需要进行配置管脚约束
add source
设置管脚,设置电平
set_property PACKAGE_PIN P20 [get_ports spi_miso ]
set_property PACKAGE_PIN R19 [get_ports spi_cs ]
set_property PACKAGE_PIN J19 [get_ports spi_mosi ]
set_property PACKAGE_PIN K19 [get_ports spi_sclk ]
set_property PACKAGE_PIN U20 [get_ports cmos_rst ]
set_property IOSTANDARD LVCMOS33 [get_ports spi_miso]
set_property IOSTANDARD LVCMOS33 [get_ports spi_mosi]
set_property IOSTANDARD LVCMOS33 [get_ports spi_cs]
set_property IOSTANDARD LVCMOS33 [get_ports spi_sclk]
set_property IOSTANDARD LVCMOS33 [get_ports cmos_rst]
之后生成bitstream文件。
然后export bit stream文件,之后进行设计。
latch sdk
添加配置文件,之后添加spi文件,可以参考spi例子
使用 SPI库函数,这里涉及到库函数使用
#define XPAR_XSPIPS_0_DEVICE_ID XPAR_PS7_SPI_0_DEVICE_ID
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
在main函数中,包含spi结构体函数
定义两个结构体
首先在xparameters.h里面找到设备
static XSpiPs Spi_Instance;
static XSpiPs_Config *SpiPsCfg;
/*
* Initialize the SPI driver so that it's ready to use
*/
SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize((&SpiInstance), SpiConfig,
SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
初试化以后,调用s32 XSpiPs_SetOptions(XSpiPs *InstancePtr, u32 Options),设置模式函数,XSPIPS_*_OPTIONS
关键在第二个参数,第二个参数到底怎么用呢???
首先要选择Master 模式,然后选择片选信号,
XSPIPS_DECODE_SSELECT_OPTION,设置38译码器,可以接一个38译码器,因为有三个片选信号。
XSPIPS_FORCE_SSELECT_OPTION,强制选择模式,通过调用发送函数来强制选择CS来使CS有效。
XSPIPS_MASTER_OPTION ,Master设置,
status = XSpiPs_SetOptions(&Spi_Instance,XSPIPS_FORCE_SSELECT_OPTION|XSPIPS_MASTER_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
然后设置时钟频率
This function sets the clock prescaler for an SPI device
s32 XSpiPs_SetClkPrescaler(XSpiPs *InstancePtr, u8 Prescaler)
关键还是第二个参数
XSPIPS_CLK_PRESCALE_32,这个32分频是怎么用的呢?
在zynq ps中,可以展开CLock Configuration,然后里面有个IO Peripheral clocks,这个就是SPI的时钟
然后,这个设置时钟的分频系数,就是分频这个时钟的。
设置完时钟以后,在设置片选
s32 XSpiPs_SetSlaveSelect(XSpiPs *InstancePtr, u8 SlaveSel)
第二个参数如果没有接38译码器的话,0-2对应着你zynq ps端接片选的值
比如2的话,你用的就是CS2.
大致流程如下:在main函数里注意先声明,不然找不到。
int spi_init(u16 SpiDeviceId)
{
int Status;
SpiPsCfg = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiPsCfg) {
return XST_FAILURE;
}
SpiPsCfg = XSpiPs_CfgInitialize((&Spi_Instance), SpiPsCfg,
SpiPsCfg->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = XSpiPs_SetOptions(&Spi_Instance,XSPIPS_FORCE_SSELECT_OPTION|XSPIPS_MASTER_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = XSpiPs_SetClkPrescaler(&Spi_Instance, XSPIPS_CLK_PRESCALE_32);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XSpiPs_SetSlaveSelect(&Spi_Instance,0);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}