Bootstrap

Zynq中SPI的读和写

    在配置很多外围器件的时候,几乎都要用到SPI口。一般流程都是用SPI向器件相应的寄存器写数据,然后读回来检测是否成功写入。ADI公司的AD/DA器件的SPI读写格式都差不多,如下图所示:

这也是4线SPI的常用格式。

 

       数据的读和写用SDI的第一个bit来表示,1为从器件(SLAVE)的寄存器中读取数据,0表示向寄存器写入数据。SDI上跟着的一般为地址,地址后面,SDI上跟着的是需要写入的数据,SDO上相应位置为读出来的数据。

 

对于通用的SPI格式,用Vivado自带的AXI Quad SPI基本可以满足要求。应用的时候,对于大于8bit的数据,需要注意在传输数据的时候需要写入正确的次数。比如:

XSpi_Transfer(&SpiAdc, ADCCommand, ADCRegData, 2);

这里就是需要写入或者读取16bit的数据,则次数要写成2。

我的写入数据的代码为:

第一个参数选择slave,第二个为寄存器地址,第三个为数据。

int ADCWriteReg(u8 ADCSerialNum, u8 RegAddr, u16 Data) {

	int Status;

	if (ADCSerialNum == 0) {
		Status = XSpi_SetSlaveSelect(&SpiAdc, ADC0_MASK);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}
	} else if (ADCSerialNum == 1) {
		Status = XSpi_SetSlaveSelect(&SpiAdc, ADC1_MASK);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}
	} else if (ADCSerialNum == 2) {
		Status = XSpi_SetSlaveSelect(&SpiAdc, ADC2_MASK);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}
	} else {
		xil_printf("There is no adc with this serial number.\r\n");
	}

	u8 ADCCommand[2];
	u16 ADCCommand16 = 0x0;
	ADCCommand16 = ((u16) RegAddr << 8) + Data;

	ADCCommand[1] = (u8) (ADCCommand16 >> 8);
	ADCCommand[0] = (u8) (ADCCommand16);

	XSpi_Transfer(&SpiAdc, ADCCommand, NULL, 2);
	xil_printf("Write ADC%d Address %02x the data : %08x\r\n", ADCSerialNum,
			RegAddr, Data);
	usleep(5000);
	return XST_SUCCESS;
}

读取数据的代码为:


int ADCReadReg(u8 ADCSerialNum, u8 RegAddr) {

	int Status;

	if (ADCSerialNum == 0) {
		Status = XSpi_SetSlaveSelect(&SpiAdc, ADC0_MASK);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}
	} else if (ADCSerialNum == 1) {
		Status = XSpi_SetSlaveSelect(&SpiAdc, ADC1_MASK);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}
	} else if (ADCSerialNum == 2) {
		Status = XSpi_SetSlaveSelect(&SpiAdc, ADC2_MASK);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}
	} else {
		xil_printf("There is no adc with this serial number.\r\n");
	}

	u8 ADCCommand[2];
	u8 ADCRegData[2] = { 0x0, 0x0 };
	u16 ADCCommand16 = 0x0;
	ADCCommand16 = ((u16) RegAddr << 8);

	ADCCommand[1] = (u8) (ADCCommand16) + 0x80;
	ADCCommand[0] = 0x00;

	Status = XSpi_Transfer(&SpiAdc, ADCCommand, ADCRegData, 2);
	xil_printf("ADC%d %02x Address Reg data is: %02x", ADCSerialNum, RegAddr,
			ADCRegData[1]);
	xil_printf("%02x\r\n", ADCRegData[0]);
	usleep(5000);
	return XST_SUCCESS;
}

 

;