zynq侧SPI硬核相关

一、概述

zynq自带两个SPI的硬核,SPI控制相关寄存器,ug585上有相关说明,其中SPI0的base address是0xe0006000,SPI1的base address是0xe0007000。

二、应用举例

SPI可以配置为master、multi master 和 slave 等模式,注意TX_FIFO和RX_FIFO实际有效数据位宽是8bit,即每次发送的数据是8bit,如果实际一次SPI操作位宽不是8bit,可通过手动控制CS来更改一次SPI拉低之后发送的数据量。

比如AD9361,其SPI一次是发送24bit数据,standalone使用SPI0进行SPI读写的模块如下:

main函数文件

#include "spips.h"

int main(void)
{
	int i =0;
	unsigned int reg_value;
	SpiPs_Init(SPI_DEVICE_ID);

	AD9361_WR(0x6a,0x5a);
	reg_value = AD9361_RD(0x6a);
	if(reg_value == 0x5a)
		xil_printf("spi test OK!\r\n");
	else
		xil_printf("spi test Error!\r\n");

	return 0;
}

unsigned int AD9361_WR(unsigned int reg_addr,unsigned int value)
{
    u8 spi_wr_Buf[3];
    int i =0;

    spi_wr_Buf[0] = 0x80 | (reg_addr >> 8);
    spi_wr_Buf[1] = reg_addr ;
    spi_wr_Buf[2] = value;
//    for(i=0;i<3;i++)
//    		xil_printf("%x\r\n",spi_wr_Buf[i]);
    XSpiPs_SetSlaveSelect(&SpiInstance, SLAVE0_SELECT);
    SpiPs_Send(spi_wr_Buf,3);
    XSpiPs_SetSlaveSelect(&SpiInstance, NONE_SELECT);
    SpiPs_Read(spi_wr_Buf,3);

    return 0;
}

unsigned int AD9361_RD(unsigned int reg_addr)
{
    unsigned int value;
    int i =0;
	u8 spi_rd_Buf[3];

    spi_rd_Buf[0] = 0x00 | (reg_addr >> 8);
    spi_rd_Buf[1] = reg_addr ;
    spi_rd_Buf[2] = 0x00;
//    for(i=0;i<3;i++)
//    		xil_printf("%x\r\n",spi_rd_Buf[i]);
    XSpiPs_SetSlaveSelect(&SpiInstance, SLAVE0_SELECT);

    SpiPs_Send(spi_rd_Buf,3);
    XSpiPs_SetSlaveSelect(&SpiInstance, NONE_SELECT);

    SpiPs_Read(spi_rd_Buf,3);
    value = spi_rd_Buf[2];

    return value;
}

spips.c文件:

//spips.c
#include "spips.h"
int SpiPs_Init(u16 SpiDeviceId)
{
	int Status;
	u8 *BufferPtr;
	XSpiPs_Config *SpiConfig;

	/*
	 * 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;
	}

	/*
	 * The SPI device is a slave by default and the clock phase
	 * have to be set according to its master. In this example, CPOL is set
	 * to quiescent high and CPHA is set to 1.
	 */
	XSpiPs_SetSlaveSelect(&SpiInstance, NONE_SELECT);
	Status = XSpiPs_SetOptions((&SpiInstance),   (XSPIPS_FORCE_SSELECT_OPTION) | \
			(XSPIPS_CLK_PHASE_1_OPTION) | (0) | XSPIPS_MASTER_OPTION);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	Status = XSpiPs_SetClkPrescaler(&SpiInstance, XSPIPS_CLK_PRESCALE_8);

	/*
	 * Enable the device.
	 */
	XSpiPs_Enable((&SpiInstance));

	return XST_SUCCESS;
}

void SpiPs_Read(u8 *ReadBuffer,int ByteCount)
{
	int Count;
	u32 StatusReg;

	do{
		StatusReg = XSpiPs_ReadReg(SpiInstance.Config.BaseAddress,
					XSPIPS_SR_OFFSET);
	}while(!(StatusReg & XSPIPS_IXR_RXNEMPTY_MASK));

	/*
	 * Reading the Rx Buffer
	 */
	for(Count = 0; Count < ByteCount; Count++){
		ReadBuffer[Count] = SpiPs_RecvByte(
				SpiInstance.Config.BaseAddress);
//	    xil_printf("%x\r\n",ReadBuffer[Count]);
	}
}

void SpiPs_Send(u8 *SendBuffer, int ByteCount)
{
	u32 StatusReg;
	int TransCount = 0;

	/*
	 * Fill the TXFIFO with as many bytes as it will take (or as
	 * many as we have to send).
	 */
	while ((ByteCount > 0) &&
		(TransCount < XSPIPS_FIFO_DEPTH)) {
		SpiPs_SendByte(SpiInstance.Config.BaseAddress,
				*SendBuffer);
		SendBuffer++;
		++TransCount;
		ByteCount--;
	}

	/*
	 * Wait for the transfer to finish by polling Tx fifo status.
	 */
	do {
		StatusReg = XSpiPs_ReadReg(
				SpiInstance.Config.BaseAddress,
					XSPIPS_SR_OFFSET);
	} while ((StatusReg & XSPIPS_IXR_TXOW_MASK) == 0);
}

spips.h文件:

//spips.h 对Xilinx的spi裸机驱动进行封装
#ifndef SRC_SPIPS_H_
#define SRC_SPIPS_H_

#include "xparameters.h"	/* SDK generated parameters */
#include "xspips.h"		    /* SPI device driver */
#include "xil_printf.h"

void SpiPs_Read (u8 *ReadBuffer, int ByteCount);
void SpiPs_Send (u8 *SendBuffer, int ByteCount);
int  SpiPs_Init (u16 SpiDeviceId);

#define SPI_DEVICE_ID		XPAR_XSPIPS_0_DEVICE_ID
#define SpiPs_RecvByte(BaseAddress) (u8)XSpiPs_In32((BaseAddress) + XSPIPS_RXD_OFFSET)
#define SpiPs_SendByte(BaseAddress, Data) XSpiPs_Out32((BaseAddress) + XSPIPS_TXD_OFFSET, (Data))
XSpiPs SpiInstance;

#define SLAVE0_SELECT 0
#define SLAVE1_SELECT 1
#define SLAVE2_SELECT 2
#define NONE_SELECT   0xf

extern unsigned int AD9361_WR(unsigned int reg_addr,unsigned int value);
extern unsigned int AD9361_RD(unsigned int reg_addr);

#endif /* SRC_SPIPS_H_ */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值