服务器上的网站不能访问,电子商务网站建设清华大学,八年级做网站,项目网络计划一、SPI的简介#xff1a; SPI 是英语Serial Peripheral interface的缩写#xff0c;顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。 SPI#xff0c;是一种高速的#xff0c;全双工#xff0c;同步的通信总线#xff0c;并且在芯片的管脚…一、SPI的简介 SPI 是英语Serial Peripheral interface的缩写顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。 SPI是一种高速的全双工同步的通信总线并且在芯片的管脚上占用四根线SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISI(Master Input Slave Output)、SS(Slave Select) 其支持总线挂载多设备一主多从。主要应用在 EEPROMFLASH实时时钟AD转换器还有数字信号处理器和数字信号解码器之间。 SPI接口一般使用4条线通信 MISO 主机输入从机输出。主机通过MOSI输入从机通过MOSI输出。 MOSI 主机输出从机输入。主机通过MOSI输出从机通过MOSI输入。 SCLK时钟线完全由主机掌握主要是产生时钟信号由主设备产生。对于主机来说时钟线为输出对于从机来说所有时钟线为输入。 CS从设备片选信号由主设备控制低电平有效。主机选择从机时只需要将连接对应的ss线置0就可以选择此从机了。相较于IIC这种方法更简单但会浪费更多引脚但无需IIC一样先进行寻址SS线置0相当于寻址了。
二、SPI时序介绍
1. spi四种模式详解 在spi的模式配置中有两个很关键的东西即SPI_CR1的第0和1位
模式0CPOL 0、CPHA 0 由于CPOL为0也就是空闲状态下SCK为低电平CPHA 0也就是从第一个边沿开始采样也就是上升沿采样。下图是截取NRF24l01的读写时序图为模式0起始SCK为低电平上升沿采样。下降沿移出数据为下一次采样做准备。 由于第一个上升沿就要采样数据所以得在第一个上升沿就要把数据移出也就是把CSN的下降沿当作时钟的一部分了。从图中可以看见CSN下降沿时数据变化主机输出数据最高位将数据放于MOSI线上然后第一个上升沿采样主机和从机读取数据主机读从机的最高位从机读主机的数据最高位第一个下降沿主机输出次高位当然从机也会动作但从机不需要我们操作再第二上升沿采样......即先有了下降沿才能有数据变换的条件。
第一个时序代码如下CSN 在选择从机时会拉低所以这里没写拉低SS后主机移出数据方便从机在下一个上升沿读。此时拉高SCK主机读从机发来的数据从机也会读主机发来的数据注意为高位先行。然后拉低SCK主机和从机输出数据方便下个上升沿读取数据这样第一个周期时序就完成了接下来只需for循环8次就可以了这样就完成了一次数据交换。和IIC不同的是IIC有读写函数而SPI读写是同时进行的。
uint8_t MySPI_SW_Byte(uint8_t Byte)
{uint8_t receivebyte 0x00;for(uint8_t i0;i8;i){SPI_MOSI((BitAction)(Byte 0x80));SPI_SCK(1);if(Read_MOSI 1)receivebyte | 0x80;SPI_SCK(0);}return receivebyte;
}模式1CPOL 0、CPHA 1 由于CPOL为0也就是空闲状态下SCK为低电平CPHA 1也就是从第一个边沿开始移出数据。此时主机将数据最高位放到MOSI线上从机将数据放到MISO上也就是上升沿输出。第二个边沿下降沿移入数据即读取数据主机读MISO从机读MOSI到这里完成了一个时序周期。
模式2CPOL 1、CPHA 0 由于CPOL为0也就是空闲状态下SCK为高电平CPHA 0也就是从第一个边沿开始移入数据注由于空闲时为高电平所以第一个边沿变成了下降沿。此时读取数据主机读MISO从机读MOSI。第二个边沿上升沿移出数据主机将数据最高位放到MOSI线上从机将数据放到MISO上也就是上升沿输出。到这里完成了一个时序周期即。
模式3CPOL 1、CPHA 1 由于CPOL为1也就是空闲状态下SCK为高电平CPHA 1也就是从第一个边沿下降沿开始移出数据。此时主机将数据最高位放到MOSI线上从机将数据放到MISO上也就是下降沿输出。第二个边沿上升沿移入数据即读取数据主机读MISO从机读MOSI到这里完成了一个时序周期。
三、SPI的初始化
下面进行SPI的初始化 由于我们采用的是软件SPI所以MOSI和SCK配置为推挽输出而MISO是从机输出线从机掌握主动权所以配置为上拉输入。
void MySPI_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO端口时钟GPIO_InitStructure.GPIO_PinGPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_ModeGPIO_Mode_Out_PP;//通用推挽输出GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;//引脚速率50MHZGPIO_Init(GPIOA, GPIO_InitStructure);GPIO_InitStructure.GPIO_PinGPIO_Pin_6; GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;//上拉输入GPIO_Init(GPIOA, GPIO_InitStructure);SPI_SCK(0);
}
即SPI代码如下
spi.c
#include spi.hvoid MySPI_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的结构体RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIO端口时钟GPIO_InitStructure.GPIO_PinGPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_ModeGPIO_Mode_Out_PP;//通用推挽输出GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;//引脚速率50MHZGPIO_Init(GPIOA, GPIO_InitStructure);GPIO_InitStructure.GPIO_PinGPIO_Pin_6; GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU;//上拉输入GPIO_Init(GPIOA, GPIO_InitStructure);SPI_SCK(0);
}uint8_t MySPI_SW_Byte(uint8_t Byte)
{uint8_t receivebyte 0x00;for(uint8_t i0;i8;i){SPI_MOSI((BitAction)(Byte (0x80i)));SPI_SCK(1);if(Read_MOSI 1)receivebyte | (0x80i);SPI_SCK(0);}return receivebyte;
}spi.h
#ifndef __SPI_H
#define __SPI_H#include stm32f10x.h // Device header
#include sys.h#define SPI_MOSI(x) GPIOA-BSRR GPIO_Pin_7(16*(!x))
#define SPI_SCK(x) GPIOA-BSRR GPIO_Pin_5(16*(!x))
#define Read_MOSI PAin(7) //输入MOSIvoid MySPI_Init(void);
uint8_t MySPI_SW_Byte(uint8_t Byte);#endif下一章将讲如何使用2.4G模块。