|
SPI通信协议,时序图祥解
物理层:
1》SPI是一种4线串行同步的通信方式,MCLK(同步时钟线),MOSI(主机输出从机输入线),MISO(主机输入从机输出线),NSS/CS(片选信号线)
2》SPI一般是单主机多从机的通信方式
3》SPI是一种高低位先行可选择的(MSB高位先行,LSB低位先行),8bit和16bit数据位可编辑的通信方式
4》SPI是摩托罗拉公司研发的通信总线协议
5》SPI通信速率最大可以达到18MHZ
6》SPI的时钟线一般由主机控制,由主机发起SPI通信
协议层:
CPOL(时钟极性):用于确定时钟空闲时的时钟状态
CPHA(时钟相位):用于确定数据采样和输出是在哪个时钟边沿(采样:数据稳定,输出:允许发生数据改变)
SPI的4种工作模式
CPOL CPHA
0 0 0 时钟线空闲时为低电平,在时钟的前沿采样,时钟后沿输出
1 0 1 时钟线空闲时为低电平,在时钟的前沿输出,时钟后沿采样
2 1 0 时钟线空闲时为高电平,在时钟的前沿采样,时钟后沿输出
3 1 1 时钟线空闲时为高电平,在时钟的前沿输出,时钟后沿采样
读取w25qxx的制造商和ID编程步骤:
1》打开时钟-----GPIOA,AFIO,SPI1
2》初始化GPIOA
-----GPIO_Pin_4
-----通用推挽输出
-----输出速度50MHZ
-----GPIO_Pin_567
-----复用推挽输出
-----输出速度50MHZ
3》SPI1初始化
-----双线双向全双工模式
-----主机模式
-----数据位8bit
-----CPOL----时钟悬空高
-----CPHA----数据捕获于第二个时钟边沿
-----NSS由软件控制
-----CRC----7
-----预分频器----4
-----高位先行
4》使能SPI
5》发送和接收数据
SPI时序图详解

代码
#define CS_LOW GPIO_ResetBits(GPIOA,GPIO_Pin_4)
#define CS_HIGH GPIO_SetBits(GPIOA,GPIO_Pin_4)
void SPI1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
SPI_InitTypeDef SPI_InitStruct;
// 1》打开时钟-----GPIOA,AFIO,SPI1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|RCC_APB2Periph_SPI1,ENABLE);
// 2》初始化GPIOA
GPIO_InitStruct.GPIO_Pin =GPIO_Pin_4;
GPIO_InitStruct.GPIO_Mode =GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin =GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
// 3》SPI1初始化
SPI_InitStruct.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_4;
SPI_InitStruct.SPI_CPHA =SPI_CPHA_2Edge;
SPI_InitStruct.SPI_CPOL =SPI_CPOL_High;
SPI_InitStruct.SPI_CRCPolynomial =7;
SPI_InitStruct.SPI_DataSize =SPI_DataSize_8b;
SPI_InitStruct.SPI_Direction =SPI_Direction_2Lines_FullDuplex;
SPI_InitStruct.SPI_FirstBit =SPI_FirstBit_MSB;
SPI_InitStruct.SPI_Mode =SPI_Mode_Master;
SPI_InitStruct.SPI_NSS =SPI_NSS_Soft;
SPI_Init(SPI1,&SPI_InitStruct);
// 4》使能SPI
SPI_Cmd(SPI1,ENABLE);
}
uint8_t SPI_Rx_Tx_ByteData(uint8_t txdata)
{
while(SET!=SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE));
SPI_I2S_SendData(SPI1,txdata);
while(SET!=SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE));
return (uint8_t)SPI_I2S_ReceiveData(SPI1);
} |
|