1、定义:SPI是一种通信接口,串行外围设备接口
2、作用:主要负责Flash和单片机之间的通信
3、通信方式:高速的串行同步全双工
4、结构:环形总线结构,发送一个数据的同时还需要接收一个数据
5、四线结构:CLK、CS、MISO、MOSI
6、SPI有四种工作模式,由时钟极性(CPOL)和时钟相位(CPHA)决定
SPI0和SPI3是一样的,上升沿采样,下降沿输出
SPI1和SPI2是一样的,下降沿采样,上升沿输出
简单代码编写如下:
// CS -- PA4、CLK -- PA5、MISO -- PA6、MOSI -- PA7
void spi_Config(void)
{
RCC->APB2ENR |=(0x01<<2)|(0x01<<12); //打开时钟
GPIOA->CRL &=~(0xf<<20);
GPIOA->CRL |=(0xB<<20); //PA5(CLK)复用推挽,速率50MHz
GPIOA->CRL &=~(0xf<<24);
GPIOA->CRL |=(0x04<<24); //PA6(MISO)浮空输入
GPIOA->CRL &=~(0xf<<28);
GPIOA->CRL |=(0xB<<28); //PA7(MOSI)复用推挽,速率50MHz
GPIOA->CRL &=~(0xf<<16);
GPIOA->CRL |=(0x02<<16);//PA4(CS)推挽输出,速率2MHz
SPI1->CR1 &=~(0X03<<0);//时钟极性0和相位0
SPI1->CR1 |=(0X01<<2);//主设备
SPI1->CR1 &=~(0X07<<3);//波特率
SPI1->CR1 &=~(0X01<<7);//先发送高位
SPI1->CR1 |=(0X01<<9);//软件从设备管理
SPI1->CR1 |=(0X01<<8);
SPI1->CR1 &=~(0X01<<11);//8位数据传输
SPI1->CR1 |=(0X01<<6);//使能
}
uint8_t SP1_ReadWriteData(uint8_t data)
{
while(!(SPI1->SR &(0x01<<1)));//等待发送缓冲区非空
SPI1->DR=data;
while(!(SPI1->SR &(0x01<<0)));//等待接收缓冲区非空
return (SPI1->DR);
}
下面是用GPIO口模拟SPI的核心代码:
//模拟SPI(参考SPI时序图)
uint8_t Touch_ReadAndWrite(uint8_t s_data)
{
uint8_t r_data;//接收的数据
uint8_t i = 0;
for(i=0;i<8;i++) //按位发送和接收
{
T_CLK = 0; //将CLK拉低
if(s_data & (0x80 >> i)) T_MOSI = 1;
else T_MOSI = 0; //按位判断要发送的数据
Delay_us(1); //微秒级延时
T_CLK = 1; //将CLK拉低
Delay_us(1);
r_data<<=1; //第一个沿是上升沿
if(T_MISO) r_data++; //SPI为环形结构,发送一位的同时要接收一位
}
return r_data;
}
注:本人初学代码,如编写有错误,欢迎指正交流