SPI工作模式时序分析
SPI工作模式时序分析
SPI共用4种模式,通过SCK的CPOL(时钟极性)和CPHA(时钟相位)来控制同步,此处利用IO口软件模拟W25Q128的SPI模式0与模式3通信过程中的时序。且SPI是通过MISO和MOSI来收发数据因此得知SPI是全双工的。下面代码使用W25Q128_SCK(n)来模拟CPOL的波形。
- 模式0:CPOL = 0,CPHA = 0,第一个边沿收发
- 模式1:CPOL = 0,CPHA = 1,第二个边沿收发
- 模式2:CPOL = 1,CPHA = 0,第一个边沿收发
- 模式3:CPOL = 1,CPHA = 1,第二个边沿收发
SPI模式0
/*************************************************************
*
* file name: 1.c
* author : lu.ciana.598393@gmail.com
* date : 2024/07/16
* function : 利用IO口模拟SPI时序实现对存储IC进行读取操作,掌握SPI工作模式和时序分析
* note : none
* CopyRight (c) 2024 lu.ciana.598393@gmail.com All Right Reserved
* SCK -- PB3 输出模式
* MOSI -- PB5 输出模式
* MISO -- PB4 输入模式
* CS -- PB14 输出模式
*****************************************************************/
#define W25Q128_CS(n) (n) ? GPIO_SetBits(GPIOB, GPIO_Pin_14) : GPIO_ResetBits(GPIOB, GPIO_Pin_14)
#define W25Q128_SCK(n) (n) ? GPIO_SetBits(GPIOB, GPIO_Pin_3) : GPIO_ResetBits(GPIOB, GPIO_Pin_3) //使用这个函数来模拟CPOL的波形
#define W25Q128_MOSI(n) (n) ? GPIO_SetBits(GPIOB, GPIO_Pin_5) : GPIO_ResetBits(GPIOB, GPIO_Pin_5)
#define W25Q128_MISO GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4)
uint8_t W25Q128_SendByte(uint8_t byte)
{
int i= 0;
uint8_t data= 0;
//1. SCK引脚输出低电平
W25Q128_SCK(0);
delay_us(5);
//循环发送8次,每次发送一个bit遵循MSB高位先出
for(i=0;i<8;i++)
{
//2.判断待发送的字节的最高位
if(byte & 0x80)
{
W25Q128_MOSI(1);
}else
{
W25Q128_MOSI(0);
}
byte <<= 1;
delay_us(5);
//3.SCK引脚输出高电平,此时第一个边沿出现
W25Q128_SCK(1);
delay_us(5);
//4.此时从机会响应一个bit,主机需要接收!
data <<= 1;
data |= W25Q128_MISO;
delay_us(5);
//5.SCK引脚输出低电平,此时第二个边沿出现
W25Q128_SCK(0);
delay_us(5);
}
return data;
}
SPI模式3
/*************************************************************************************
*
* file name: 1.c
* author : lu.ciana.598393@gmail.com
* date : 2024/07/16
* function : 利用IO口模拟SPI时序实现对存储IC进行读取操作,掌握SPI工作模式和时序分析
* note : none
* CopyRight (c) 2024 lu.ciana.598393@gmail.com All Right Reserved
* SCK -- PB3 输出模式
* MOSI -- PB5 输出模式
* MISO -- PB4 输入模式
* CS -- PB14 输出模式
******************************************************************/
#define W25Q128_CS(n) (n) ? GPIO_SetBits(GPIOB, GPIO_Pin_14) : GPIO_ResetBits(GPIOB, GPIO_Pin_14)
#define W25Q128_SCK(n) (n) ? GPIO_SetBits(GPIOB, GPIO_Pin_3) : GPIO_ResetBits(GPIOB, GPIO_Pin_3)
#define W25Q128_MOSI(n) (n) ? GPIO_SetBits(GPIOB, GPIO_Pin_5) : GPIO_ResetBits(GPIOB, GPIO_Pin_5)
#define W25Q128_MISO GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4)
uint8_t W25Q128_SendByte(uint8_t byte) {
int i = 0;
uint8_t data = 0;
//1. SCK引脚输出高电平
W25Q128_SCK(1);
delay_us(5);
//循环发送8次, 每次发送一个bit遵循MSB高位先出
for (i = 0; i < 8; i++) {
//2.SCK引脚输出低电平,此时第一个边沿出现
W25Q128_SCK(0);
delay_us(5);
//3.判断待发送的字节的最高位
if (byte & 0x80) {
W25Q128_MOSI(1);
} else {
W25Q128_MOSI(0);
}
byte <<= 1;
delay_us(5);
//4.SCK引脚输出高电平,此时第二个边沿出现
W25Q128_SCK(1);
delay_us(5);
//5.此时从机会响应一个bit,主机需要接收!
data <<= 1;
data |= W25Q128_MISO;
delay_us(5);
}
return data;
}