首页天道酬勤SPI模式,fpga程序

SPI模式,fpga程序

张世龙 05-13 00:51 119次浏览

1、什么是SPI?

SPI是串行外围接口的缩写。 是摩托罗拉公司推出的同步串行接口技术,是一种高速、全双工、同步的通信总线。

2、SPI优点

全双工通信、通信简单,支持数据传输速率块

3、缺点

由于没有指定的流控制,没有确认是否接收到数据的响应机制,因此与IIC总线协议相比,数据的可靠性存在一定的缺陷。

4、特点

1 )高速、同步、全双工、非差分、总线式

2 )主从通信模式

5、协议通信时序详解

1 ) SPI通信原理简单,采用主从方式工作。 该模式通常包括一个主设备和一个或多个从设备,需要至少四条线路,实际上可以是三条(对于单向传输)。 所有基于SPI的设备都通用。 那些是

数据输入(SDI )、SDO、SCLK和CS )芯片选择。

)1) 3358 www.Sina.com/(masteroutslaverin ) -主数据输出、从数据输入;

)2) 3358 www.Sina.com /主数据输入、从站数据输出;

)3) 3358 www.Sina.com /时钟信号来自主设备;

)4) 3358www.Sina.com/-从站设备的使能信号由主站设备控制。 有多个从设备时,各从设备的芯片选择端子与主机连接,因此主设备和某个从设备通信时,需要降低或提高与从设备对应的芯片选择端子的电平

SPI时序图示例:四线制,高位在前、下降沿跳、上升沿采样。

2 )此外,SDO/MOSI的不同从站设备在出厂时可能已设定为某种模式,无法变更。 但是,我们的通信必须在两者相同的模式下工作,所以可以配置我们主设备的SPI模式,用时钟极性(CPOL )和CPHA时钟相位(CPOL )控制我们主设备的通信模式。 具体如下。

Mode0:CPOL=0,CPHA=0

模式1:cpol=0,CPHA=1

模式2:cpol=1,CPHA=0

模式3:cpol=1,CPHA=1

时钟极性CPOL用于设定SCLK电平从哪个状态变为空闲状态或活动状态,时钟相位CPHA用于设定数据样本位于第几个边缘:

CPOL=0表示SCLK=0时处于空闲状态,有效状态是SCLK为高电平时

CPOL=1表示SCLK=1时处于空闲状态,有效状态是SCLK为低电平时

CPHA=0指示数据采样在第一个边缘且数据传输在第二个边缘

CPHA=1指示数据采样在第二个边缘且数据传输在第一个边缘

SDI/MISO

程序模拟:

/* SPI1gpioconfigurationpa5--- SPI1_ sck pa6----SPI1_ mis opa7----SPI1_ MoSi */# defines pi defines pi _ ss defines pi _ MoSi _ gpio _ portgpioa # defines pi _ MoSi _ gpio _ portgpioa # define defines pi _ miso _ gpio _ portgpioa defines pi _ NSS _ gpio _ portgpiod # defines pi _ NSS _ gpio _ portgpiod # define _ _ Hal _ RCC _ gpioa _ clk _ enar

__HAL_RCC_GPIOD_CLK_ENABLE() #define MOSI_H HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET) #define MOSI_L HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_RESET) #define SCK_H HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET) #define SCK_L HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_RESET) #define MISO HAL_GPIO_ReadPin(SPI_MISO_GPIO_PORT, SPI_MISO_PIN) #define NSS_H HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET) #define NSS_L HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_RESET) · void SPI_Init(void){ /*##-1- Enable peripherals and GPIO Clocks #########################*/ /* Enable GPIO TX/RX clock */ SPI_SCK_GPIO_CLK_ENABLE(); SPI_MISO_GPIO_CLK_ENABLE(); SPI_MOSI_GPIO_CLK_ENABLE(); SPI_NSS_GPIO_CLK_ENABLE(); /*##-2- Configure peripheral GPIO #######################*/ /* SPI SCK GPIO pin configuration */ GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = SPI_SCK_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStruct); HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET); /* SPI MISO GPIO pin configuration */ GPIO_InitStruct.Pin = SPI_MISO_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(SPI_MISO_GPIO_PORT, &GPIO_InitStruct); /* SPI MOSI GPIO pin configuration */ GPIO_InitStruct.Pin = SPI_MOSI_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStruct); HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET); GPIO_InitStruct.Pin = SPI_NSS_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(SPI_NSS_GPIO_PORT, &GPIO_InitStruct); HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET); }

模拟SPI4种工作模式:

/* CPOL = 0, CPHA = 0, MSB first */uint8_t SOFT_SPI_RW_MODE0( uint8_t write_dat ){ uint8_t i, read_dat; for( i = 0; i < 8; i++ ) { if( write_dat & 0x80 ) MOSI_H; else MOSI_L; write_dat <<= 1; delay_us(1); SCK_H; read_dat <<= 1; if( MISO ) read_dat++; delay_us(1); SCK_L; __nop(); } return read_dat;} /* CPOL=0,CPHA=1, MSB first */uint8_t SOFT_SPI_RW_MODE1(uint8_t byte) { uint8_t i,Temp=0; for(i=0;i<8;i++) // 循环8次{SCK_H; //拉高时钟if(byte&0x80) {MOSI_H; //若最到位为高,则输出高 }else {MOSI_L; //若最到位为低,则输出低}byte <<= 1; // 低一位移位到最高位delay_us(1);SCK_L; //拉低时钟Temp <<= 1; //数据左移 if(MISO)Temp++; //若从从机接收到高电平,数据自加一delay_us(1); }return (Temp); //返回数据} /* CPOL=1,CPHA=0, MSB first */uint8_t SOFT_SPI_RW_MODE2(uint8_t byte) { uint8_t i,Temp=0; for(i=0;i<8;i++) // 循环8次{if(byte&0x80) {MOSI_H; //若最到位为高,则输出高 }else {MOSI_L; //若最到位为低,则输出低}byte <<= 1; // 低一位移位到最高位delay_us(1);SCK_L; //拉低时钟Temp <<= 1; //数据左移 if(MISO)Temp++; //若从从机接收到高电平,数据自加一delay_us(1);SCK_H; //拉高时钟}return (Temp); //返回数据} /* CPOL = 1, CPHA = 1, MSB first */uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat ){ uint8_t i, read_dat; for( i = 0; i < 8; i++ ) {SCK_L; if( write_dat & 0x80 ) MOSI_H; else MOSI_L; write_dat <<= 1; delay_us(1); SCK_H; read_dat <<= 1; if( MISO ) read_dat++; delay_us(1); __nop(); } return read_dat;}
, i2c转串口芯片,linux spi驱动实例