本文主要是介绍八、赛普拉斯EZ-USB FX3 SPI,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、简介
SPI(Serial Perripheral Interface)串行外设接口,是由摩托罗拉(Motorola)推出的一种高速、同步、串行、全双工的通信技术,在嵌入式设备中广泛使用的接口协议。SPI支
SPI分为两种模式:主模式,从模式,当作为主模式时可以挂载多个从设备,每个设备都有单独的片选线。
图1.0 SPI一主多从
SPI接口共有四根通信线,分别为MOSI、MISO、CS(SSN)、SCLK,当采用4根通信线则为全双工通信,当采用3根通信线则为单工通信:
·MOSI(Master Output Slave Input):主设备数据输出,从设备数据输入
·MISO(Master Input Slave Output):主设备的数据输入,从设备数据输出
·SCLK(Serial Clock):时钟信号,由主设备产生
·CS(Chip Select):片选信号,拉低选择对应的从设备
SPI根据时钟相位(CPHA)与时钟极性(CPOL)的不同组合共有四种模式,它能决定数据是在什么时刻采样。
图1.1 SPI采样模式
SPI模式0,CPOL = 0,CPHA = 0,时钟空闲时为低电平,数据在时钟的偶数边沿采样(橙色线)
图1.2 SPI模式0
SPI模式1,CPOL = 0,CPHA = 1,时钟空闲时为低电平,数据在时钟的奇数边沿采样(橙色线)
图1.3 SPI模式1
SPI模式2,CPOL = 1,CPHA = 0,时钟空闲时为高电平,数据在时钟的奇数边沿采样(橙色线)
图1.4 SPI模式2
SPI模式3,CPOL = 1,CPHA = 1,时钟空闲时为高电平,数据在时钟的偶数边沿采样(橙色线)
图1.5 SPI模式3
二、程序
初始化SPI设备函数
extern CyU3PReturnStatus_t
CyU3PSpiInit (
void);
配置SPI函数
extern CyU3PReturnStatus_t
CyU3PSpiSetConfig (
CyU3PSpiConfig_t *config, /**< Pointer to the SPI config structure. */
CyU3PSpiIntrCb_t cb /**< Callback for receiving SPI events. */
);
设置片选信号函数
extern CyU3PReturnStatus_t
CyU3PSpiSetSsnLine (
CyBool_t isHigh /**< CyFalse: Pull down the SSN line, CyTrue: Pull up the SSN line. */
);
SPI发送函数(单位:字)
extern CyU3PReturnStatus_t
CyU3PSpiTransmitWords (
uint8_t *data, /**< Source data pointer. This needs to be padded to nearest
byte if the word length is not byte aligned. */
uint32_t byteCount /**< This needs to be a multiple of the word length aligned to the next
byte. */
);
SPI接收函数(单位:字)
extern CyU3PReturnStatus_t
CyU3PSpiReceiveWords (
uint8_t *data, /**< Buffer to read the data into. */
uint32_t byteCount /**< Amount of data to be read. This should be an integral multiple
of the SPI word length aligned to the next byte. */
);
SPI发送/接收函数(单位:字)
extern CyU3PReturnStatus_t
CyU3PSpiTransferWords (
uint8_t *txBuf, /**< Source buffer containing data to transmit. Can be NULL if txByteCount is 0. */
uint32_t txByteCount, /**< Number of data bytes to transmit. Needs to be a multiple of the word length
aligned to the next byte. */
uint8_t *rxBuf, /**< Destination buffer to receive data into. Can be NULL if rxByteCount is 0. */
uint32_t rxByteCount /**< Number of data bytes to receive. Needs to be a multiple of the word length
aligned to the next byte. */
);
SPI配置源文件
#include "cyfx3_spi.h"
#include "cyu3error.h"
#include "cyu3utils.h"static CyU3PReturnStatus_t CyFx3GpioConfig(void)
{CyU3PReturnStatus_t CyFx3Status;//GPIO时钟配置(整个工程中只需要初始化一次)CyU3PGpioClock_t GpioClkConifg = {.fastClkDiv = 2,.slowClkDiv = 0,.halfDiv = 0,.simpleDiv = CY_U3P_GPIO_SIMPLE_DIV_BY_2,.clkSrc = CY_U3P_SYS_CLK,};CyFx3Status = CyU3PGpioInit(&GpioClkConifg,NULL);if(CyFx3Status != CY_U3P_SUCCESS){return CyFx3Status;}#if !SPI_HARDWARECyU3PGpioSimpleConfig_t SpiMosiGpioConfig = {.outValue = CyTrue,.driveLowEn = CyTrue,.driveHighEn = CyTrue,.inputEn = CyFalse,.intrMode = CY_U3P_GPIO_NO_INTR,};CyFx3Status = CyU3PGpioSetSimpleConfig(SPI_MOSI_GPIO_PIN,&SpiMosiGpioConfig);if(CyFx3Status != CY_U3P_SUCCESS){return CyFx3Status;}CyU3PGpioSimpleConfig_t SpiMisoGpioConfig = {.outValue = CyTrue,.driveLowEn = CyFalse,.driveHighEn = CyFalse,.inputEn = CyTrue,.intrMode = CY_U3P_GPIO_NO_INTR,};CyFx3Status = CyU3PGpioSetSimpleConfig(SPI_MISO_GPIO_PIN,&SpiMisoGpioConfig);if(CyFx3Status != CY_U3P_SUCCESS){return CyFx3Status;}CyU3PGpioSimpleConfig_t SpiClkGpioConfig = {.outValue = CyTrue,.driveLowEn = CyTrue,.driveHighEn = CyTrue,.inputEn = CyFalse,.intrMode = CY_U3P_GPIO_NO_INTR,};CyFx3Status = CyU3PGpioSetSimpleConfig(SPI_CLK_GPIO_PIN,&SpiClkGpioConfig);if(CyFx3Status != CY_U3P_SUCCESS){return CyFx3Status;}CyU3PGpioSimpleConfig_t SpiSsnGpioConfig = {.outValue = CyTrue,.driveLowEn = CyTrue,.driveHighEn = CyTrue,.inputEn = CyFalse,.intrMode = CY_U3P_GPIO_NO_INTR,};return CyU3PGpioSetSimpleConfig(SPI_SSN_GPIO_PIN,&SpiSsnGpioConfig);#endif
}CyU3PReturnStatus_t CyFx3SpiInit(void)
{#if !SPI_HARDWAREreturn CyFx3GpioConfig();#elseCyU3PReturnStatus_t CyFx3Status;CyFx3Status = CyU3PSpiInit();if(CyFx3Status != CY_U3P_SUCCESS){return CyFx3Status;}CyU3PSpiConfig_t SpiConfig = {.isLsbFirst = CyFalse,.cpol = CyFalse,.cpha = CyFalse,.ssnPol = CyFalse,.ssnCtrl = CyFalse,.leadTime = CY_U3P_SPI_SSN_LAG_LEAD_HALF_CLK,.lagTime = CY_U3P_SPI_SSN_LAG_LEAD_HALF_CLK,.clock = SPI_FREQUENCY,.wordLen = 8,};CyFx3Status = CyU3PSpiSetConfig(&SpiConfig,NULL);if(CyFx3Status != CY_U3P_SUCCESS){return CyFx3Status;}return CyU3PSpiSetSsnLine(CyFalse);
#endif
}#if !SPI_HARDWAREstatic CyU3PReturnStatus_t SpiSetMosiValue(CyBool_t isHigh)
{return CyU3PGpioSetValue(SPI_MOSI_GPIO_PIN,isHigh);
}static CyBool_t SpiGetMisoValue(void)
{return CyFx3GpioReadBit(SPI_MISO_GPIO_PIN);
}static CyU3PReturnStatus_t SpiSetClkValue(CyBool_t isHigh)
{return CyU3PGpioSetValue(SPI_CLK_GPIO_PIN,isHigh);
}CyU3PReturnStatus_t SpiSetSsnValue(CyBool_t isHigh)
{return CyU3PGpioSetValue(SPI_SSN_GPIO_PIN,isHigh);
}//CPOL = 0, CPHA = 0, MSB first
uint64_t SpiReadWriteMode0(uint32_t write_dat1,uint32_t write_dat2,uint32_t len)
{uint32_t i;uint32_t read_dat;uint32_t testreadspi;if(len == 32){for(i = 0;i < 32;i++){if(write_dat1 & 0x80000000){SpiSetMosiValue(CyTrue);}else{SpiSetMosiValue(CyFalse);}SpiSetClkValue(CyTrue);read_dat <<= 1;write_dat1 <<= 1;CyU3PBusyWait(1);if(SpiGetMisoValue() == CyTrue){read_dat++;}SpiSetClkValue(CyFalse);}testreadspi = read_dat;}else if(len == 64){for(i = 0;i < 32;i++){if(write_dat1 & 0x80000000){SpiSetMosiValue(CyTrue);}else{SpiSetMosiValue(CyFalse);}SpiSetClkValue(CyTrue);write_dat1 <<= 1;//CyU3PBusyWait(1);read_dat <<= 1;CyU3PBusyWait(1);if(SpiGetMisoValue() == CyTrue){read_dat++;}SpiSetClkValue(CyFalse);}testreadspi = read_dat << 16;for(i = 0;i < 32;i++){if(write_dat2 & 0x80000000){SpiSetMosiValue(CyTrue);}else{SpiSetMosiValue(CyFalse);}SpiSetClkValue(CyTrue);write_dat2 <<= 1;read_dat <<= 1;CyU3PBusyWait(1);if(SpiGetMisoValue() == CyTrue){read_dat++;}//CyU3PBusyWait(1);SpiSetClkValue(CyFalse);}testreadspi += read_dat >> 16;}return testreadspi;
}uint8_t SpiReadWriteByte(uint8_t Byte)
{uint8_t i;for(i = 0;i < 8;i++){if(Byte & 0x80){SpiSetMosiValue(CyTrue);}else{SpiSetMosiValue(CyFalse);}Byte <<= 1;CyU3PBusyWait(1);SpiSetClkValue(CyFalse);if(SpiGetMisoValue() == CyTrue){Byte |= 0x01;}CyU3PBusyWait(1);SpiSetClkValue(CyTrue);}/*for(i = 0;i < 8;i++){SpiSetClkValue(CyTrue);if(Byte & 0x80){SpiSetMosiValue(CyTrue);}else{SpiSetMosiValue(CyFalse);}Byte <<= 1;CyU3PBusyWait(1);SpiSetClkValue(CyFalse);if(SpiGetMisoValue() == CyTrue){Byte |= 0x01;}CyU3PBusyWait(1);}*/return Byte;
}void CyFx3SpiReceiveTransmitBytes(uint8_t *WriteData,uint8_t *ReadData,uint16_t DataLen)
{for(uint16_t i = 0;i < DataLen;i++){ReadData[i] = SpiReadWriteByte(WriteData[i]);}
}#endif
SPI配置头文件
#ifndef CYFX3_SPI_H_
#define CYFX3_SPI_H_#include "cyu3spi.h"
#include "cyu3gpio.h"
#include "gpio_regs.h"#define SPI_HARDWARE 0
#define SPI_GPIO_REGS 0#define SPI_FREQUENCY 8000000U //8MHz#if !SPI_HARDWARE#define CyFx3GpioReadBit(GpioPin) ((GPIO->lpp_gpio_simple[GpioPin]& CY_U3P_LPP_GPIO_IN_VALUE) >> 1)
#define CyFx3GpioSetBit(GpioPin) ((*(uvint32_t *)&GPIO->lpp_gpio_simple[GpioPin]) |= CY_U3P_LPP_GPIO_OUT_VALUE)
#define CyFx3GpioResetBit(GpioPin) ((*(uvint32_t *)&GPIO->lpp_gpio_simple[GpioPin]) &= ~CY_U3P_LPP_GPIO_OUT_VALUE)#define SPI_MOSI_GPIO_PIN 51
#define SPI_MISO_GPIO_PIN 57
#define SPI_CLK_GPIO_PIN 50
#define SPI_SSN_GPIO_PIN 52CyU3PReturnStatus_t SpiSetSsnValue(CyBool_t isHigh);
uint8_t SpiReadWriteByte(uint8_t WriteData);
void CyFx3SpiReceiveTransmitBytes(uint8_t *WriteData,uint8_t *ReadData,uint16_t DataLen);
#endifCyU3PReturnStatus_t CyFx3SpiInit(void);
#endif /* CYFX3_SPI_H_ */
这篇关于八、赛普拉斯EZ-USB FX3 SPI的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!