天天看点

简析SPI,对SPI的简单代码编写,模拟SPI

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;
}
           

注:本人初学代码,如编写有错误,欢迎指正交流

继续阅读