ZYNQ 庫函數學習之SPI

SPI是串行外設接口(Serial Peripheral Interface)的縮寫,是一種高速的,全雙工,同步的通信總線,並且在芯片的管腳上只佔用四根線,節約了芯片的管腳,同時爲PCB的佈局上節省空間,提供方便,正是出於這種簡單易用的特性,越來越多的芯片集成了這種通信協議。

sck:時鐘線

MOSI:數據輸出線

MISO:數據輸入線

ss:片選線;

特點:全雙工,傳輸速率幾Mbps。

1.SPI初始化函數:

#define SPI_DEVICE_ID        XPAR_XSPIPS_0_DEVICE_ID

XSpiPs_LookupConfig(SpiDeviceId);  //查找設備基地址:0xE0006000,時鐘:166666672

XSpiPs_CfgInitialize((&SpiInstance), SpiConfig,  //初始化設置
                    SpiConfig->BaseAddress);

裏面有個復位函數:XSpiPs_Reset(InstancePtr);     //回到初始狀態

                      XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_CR_OFFSET,
                                                    XSPIPS_CR_RESET_STATE);

XSPIPS_CR_RESET_STATE= 0x00020000U /**< Mode Fail Generation Enable */

2.spi工作模式選擇,主要涉及時鐘極性和相位極性,還有主從模式

XSpiPs_SetOptions((&SpiInstance),  XSPIPS_MASTER_OPTION);  //XSPIPS_MASTER_OPTION=1

3.  XSpiPs_SetClkPrescaler(&SpiInstance, XSPIPS_CLK_PRESCALE_64); //0x05U  64分頻
    //這個函數的關鍵就是設置分頻係數,分頻係數一定,其他基本確定。

4.XSpiPs_Enable((&SpiInstance)); //0xE0006014=1  enable the SPI

5.發送函數

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)) //XSPIPS_FIFO_DEPTH=128
	{
		SpiPs_SendByte(SpiInstance.Config.BaseAddress,*SendBuffer);
		//0x1CU  /**< Data Transmit Register */
		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);

}

將數據寫入數據發送寄存器;下半部分等待發送完成,沒有看明白,寄存器位第2位not_full。

等待發送完成。

XSPIPS_IXR_TXOW_MASK=0x4

6.接收函數

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);
	}

}

XSPIPS_IXR_RXNEMPTY_MASK=0x10

不斷判斷是否有數據,有數據則讀數據。

 

米聯客參考程序:

頭文件
#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 MAX_DATA		100

#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;

#endif /* SRC_SPIPS_H_ */


主要子程序:
/*
 * spips.c
 *
 *  Created on: 2019年5月3日
 *      Author: Administrator
 */

#include "spips.h"


int SpiPs_Init(u16 SpiDeviceId)
{
	int Status;
	u8 *BufferPtr;
	XSpiPs_Config *SpiConfig; //設備Id,地址和時鐘。

	/*
	 * Initialize the SPI driver so that it's ready to use
	 */
	SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);  //查找設備基地址:0xE0006000,時鐘:166666672
	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.
	 */
	Status = XSpiPs_SetOptions((&SpiInstance),  XSPIPS_MASTER_OPTION);  //XSPIPS_MASTER_OPTION=1
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	Status = XSpiPs_SetClkPrescaler(&SpiInstance, XSPIPS_CLK_PRESCALE_64); //0x05U  64分頻
	//這個函數的關鍵就是設置分頻係數,分頻係數一定,其他基本確定。

	/*
	 * Enable the device.
	 */
	XSpiPs_Enable((&SpiInstance)); //0xE0006014=1  enable the SPI

	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);
	}

}


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)) //XSPIPS_FIFO_DEPTH=128
	{
		SpiPs_SendByte(SpiInstance.Config.BaseAddress,*SendBuffer);
		//0x1CU  /**< Data Transmit Register */
		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);

}


測試程序:


/*
 * spi_test.c
 *
 *  Created on: 2019年5月3日
 *      Author: Administrator
 */


#include "spips.h"



u8 ReadBuf[MAX_DATA];  //100
u8 SendBuf[MAX_DATA];

int main(void)
{
	int i =0;

	SpiPs_Init(SPI_DEVICE_ID);   //宏定義XPAR_PS7_SPI_0_DEVICE_ID=0;

	for(i=0;i<10;i++)
		SendBuf[i]=i;

	SpiPs_Send(SendBuf,10);

	SpiPs_Read(ReadBuf,10);

	for(i=0;i<10;i++)
	{
		xil_printf("%d,",ReadBuf[i]);
	}

	return 0;
}





 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章