⑥,spi的发送顺序:高位先发送,低位先发送
举例如下:
void SPI2_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//开启GPIOA时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//开启GPIOB时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//开启SPI2时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉输入 GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2); //PB13引脚复用到SPI2 GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2); //PB14引脚复用到SPI2 GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2); //PB15引脚复用到SPI2 RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);//使能SPI2时钟 RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);//不使能SPI2时钟 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI为双向双线全双工模式 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置为spi主模式 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI为8位数据格式 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为低电平 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //设置SPI在SCLK的前一边沿采样,后一边沿输出。 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //配置CS引脚为软件控制 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; //设置SPI的波特率预分频值为256 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定SPI传输从高位开始 SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式 SPI_Init(SPI2, &SPI_InitStructure); SPI_Cmd(SPI2, ENABLE); //使能SPI2 } 5,SPI读写数据流程 ①,CS引脚拉低,使能spi从设备 ②,等待spi-buffer为空 ③,把需要发送的数据放入spi-buffer(若为读数据,则发送0xff) ④,等待接收完一个数据,把spi-buffer数据放入内存(若为写数据,则接收的数据无用,可丢弃) ⑤,CS引脚拉高,失能spi从设备举例如下:
u8 SPI2_ReadWriteByte(u8 TxData) { u16 retry = 0; u8 ret; SPI2_NSS(0); //拉低CS电平 while(0 == (SPI2->SR & 1 << 1)) //等待发送区空 { retry++; if(retry > SPI_REG_TIMEOUT) { SPI_PRINT("debug SPI Send Data TIMEOUT\r\n"); return 0; } } SPI2->DR = TxData; //发送一个byte retry = 0; while(0 == (SPI2->SR & 1 << 0)) //等待接收完一个byte { retry++; if(retry > SPI_REG_TIMEOUT) { SPI_PRINT("debug SPI Send Data TIMEOUT\r\n"); return 0; } } ret = SPI2->DR; //保存接收到的数据 SPI2_NSS(1); //拉高CS电平 return ret; } 6,SPI配置心得 在主设备这边配置SPI接口时钟的时候一定要弄清楚从设备的时钟要求,因为主设备这边的时钟极性和相位都是以从设备为基准的。因此在时钟极性的配置上一定要搞清楚从设备是在时钟的上升沿还是下降沿接收数据,是在时钟的下降沿还是上升沿输出数据。但要注意的是,由于主设备的SDO连接从设备的SDI,从设备的SDO连接主设备的SDI,从设备SDI接收的数据是主设备的SDO发送过来的,主设备SDI接收的数据是从设备SDO发送过来的,所以主设备这边SPI时钟极性的配置(即SDO的配置)跟从设备的SDI接收数据的极性是相反的,跟从设备SDO发送数据的极性是相同的。