您的位置:首页 > 其它

STM32之SPI的使用

2016-12-13 23:05 281 查看

通常SPI通过4个引脚与外部器件相连:

● MISO:主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。

● MOSI:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。

● SCK:串口时钟,作为主设备的输出,从设备的输入

●NSS:从设备选择。这是一个可选的引脚,用来选择主/从设备。它的功能是用来作为“片选引脚”,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。从设备的NSS引脚可以由主设备的一个标准I/O引脚来驱动。一旦被使能(SSOE位),NSS引脚也可以作为输出引脚,并在SPI处于主模式时拉低;此时,所有的SPI设备,如果它们的NSS引脚连接到主设备的NSS引脚,则会检测到低电平,如果它们被设置为NSS硬件模式,就会自动进入从设备状态。当配置为主设备、NSS配置为输入引脚(MSTR=1,SSOE=0)时,如果NSS被拉低,则这个SPI设备进入主模式失败状态:即MSTR位被自动清除,此设备进入从模式。

注意:

在改变CPOL/CPHA位之前,必须清除SPE位将SPI禁止。

主和从必须配置成相同的时序模式。

3.SCK的空闲状态必须和SPI_CR1寄存器指定的极性一致(CPOL为’1’时,空闲时应上拉SCK为高电平;CPOL为’0’时,空闲时应下拉SCK为低电平)。

数据帧格式(8位或16位)由SPI_CR1寄存器的DFF位选择,并且决定发送/接收的数据长度。

编程实现:

#define SPI1_SCK_PORT   GPIOA
#define SPI1_SCK_PIN    GPIO_Pin_5
#define SPI1_MISO_PORT   GPIOA
#define SPI1_MISO_PIN    GPIO_Pin_6                 //MISO 主设备输入从设备输出
#define SPI1_MOSI_PORT   GPIOA
#define SPI1_MOSI_PIN    GPIO_Pin_7             //MOSI 主设备输出 从设备输入
#define SPI1_APB2_GPIO   RCC_APB2Periph_GPIOA   //SPI1所在管脚时钟

#define SPI2_SCK_PORT   GPIOB
#define SPI2_SCK_PIN    GPIO_Pin_13
#define SPI2_MISO_PORT   GPIOB
#define SPI2_MISO_PIN    GPIO_Pin_14
#define SPI2_MOSI_PORT   GPIOB
#define SPI2_MOSI_PIN    GPIO_Pin_15
#define SPI2_APB1_GPIO   RCC_APB2Periph_GPIOB   //SPI2所在管脚时钟

class SPI
{
private:
SPI_TypeDef *spiX;
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
public:
SPI();
~SPI();
SPI(SPI_TypeDef *spi);
uint8_t SPISendByte(uint8_t sendByte);

};

// 函数:SPI
// 功能:初始化SPI外设
// 返回:
// 参数: SPIX
//
SPI::SPI(SPI_TypeDef *spi)
{
spiX = spi;
if (spi==SPI1)
{
SPI_Cmd(SPI1, DISABLE);                                             //禁用SPI外设
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);                //使能SPI外设APB2
RCC_APB2PeriphClockCmd(SPI1_APB2_GPIO | RCC_APB2Periph_AFIO, ENABLE);   //使能复用时钟AFIO SPI1所在管脚时钟

GPIO_InitStructure.GPIO_Pin = SPI1_MOSI_PIN;                        // MOSI(主设备输出 从设备输入)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                     //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                   //输出速度
GPIO_Init(SPI1_MOSI_PORT, &GPIO_InitStructure);                     //初始化GPIO

GPIO_InitStructure.GPIO_Pin = SPI1_SCK_PIN;                     //配置SCK 输出
GPIO_Init(SPI1_SCK_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;               //MISO浮空输入
GPIO_InitStructure.GPIO_Pin = SPI1_MISO_PIN;                        //
GPIO_Init(SPI1_MISO_PORT, &GPIO_InitStructure);

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //双线全双工模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                       //主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                   //SPI数据大小8BIT
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                          //SPI串行时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                        //SPI数据捕获第一个上升沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                           //内部产生NSS信号
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;  //8分频
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                  //数据传输从高位开始
SPI_InitStructure.SPI_CRCPolynomial = 7;                            //CRC校验生成多项式
SPI_Init(SPI1, &SPI_InitStructure);                                 //初始化SPI寄存器
SPI_Cmd(SPI1, ENABLE);                                              //使能SPI外设
}
else if (spi==SPI2)
{
SPI_Cmd(SPI2, DISABLE);                                             //禁用SPI外设
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);                //使能SPI外设APB2
RCC_APB1PeriphClockCmd(SPI2_APB1_GPIO | RCC_APB2Periph_AFIO, ENABLE);   //使能复用时钟AFIO SPI2所在管脚时钟

GPIO_InitStructure.GPIO_Pin = SPI2_MOSI_PIN;                        // MOSI(主设备输出 从设备输入)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                     //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                   //输出速度
GPIO_Init(SPI2_MOSI_PORT, &GPIO_InitStructure);                     //初始化GPIO

GPIO_InitStructure.GPIO_Pin = SPI2_SCK_PIN;                     //配置SCK 输出
GPIO_Init(SPI2_SCK_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;               //MISO浮空输入
GPIO_InitStructure.GPIO_Pin = SPI2_MISO_PIN;                        //
GPIO_Init(SPI2_MISO_PORT, &GPIO_InitStructure);

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //双线全双工模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                       //主机模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                   //SPI数据大小8BIT
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                          //SPI串行时钟悬空低
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                        //SPI数据捕获第一个上升沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                           //内部产生NSS信号
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;  //8分频
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                  //数据传输从高位开始
SPI_InitStructure.SPI_CRCPolynomial = 7;                            //CRC校验生成多项式
SPI_Init(SPI2, &SPI_InitStructure);                                 //初始化SPI寄存器
SPI_Cmd(SPI2, ENABLE);                                              //使能SPI外设
}
}
//
// 函数:    SPISendByte
// 功能:   发送一个字节数据
// 返回:   uint8_t 返回的数据
// 参数: sendByte:发送的数据
//
uint8_t SPI::SPIReadWriteByte(uint8_t sendByte)
{
uint8_t i;
while (SPI_I2S_GetFlagStatus(spiX, SPI_I2S_FLAG_TXE) == RESET)          //发射缓冲区非空时等待
{
i++;
if (i >= 200)return 0;
}                                                                       //超时返回
SPI_I2S_SendData(spiX,sendByte);                                        //SPI发送数据
i = 0;
while (SPI_I2S_GetFlagStatus(spiX, SPI_I2S_FLAG_RXNE) == RESET)         //接收缓冲器空等待
{
i++;
if (i >= 200)return 0;
}                                                                       //超时返回
return SPI_I2S_ReceiveData(spiX);                                       //返回收到的数据

}
//
// 函数:SPIReadRegister
// 功能:读寄存器值
// 返回:registerValue:寄存器值
// 参数:regitsterAdress:寄存器地址
//
uint8_t SPI::SPIReadRegister(uint8_t regitsterAdress)
{
uint8_t registerValue;
SPIReadWriteByte(regitsterAdress);                  //写寄存器地址
registerValue = SPIReadWriteByte(READ_ADDRESS);     //读寄存器值
return registerValue;                                   //返回寄存器值
}
//
// 函数:SPIWriteRegister
// 功能:写寄存器值
// 返回: registerStatus:寄存器状态
// 参数: registerAdress:寄存器地址 registerValue:值
//
uint8_t SPI::SPIWriteRegister(uint8_t registerAdress, uint8_t registerValue)
{
uint8_t registerStatus;
registerStatus = SPIReadWriteByte(registerAdress);      //读寄存器值
SPIReadWriteByte(registerValue);                            //写寄存器值
return registerStatus;                              //返回寄存器状态
}
//
// 函数:   SPIReadBufferRegister
// 功能:读寄存器指定长度数据
// 返回: 寄存器状态
// 参数: registerAddress:寄存器地址 buffer:数据 length:长度
//
uint8_t SPI::SPIReadBufferRegister(uint8_t registerAddress,uint8_t *buffer, uint8_t length)
{
uint8_t registerStatus;
uint8_t i;
registerStatus = SPIReadWriteByte(registerAddress);     //读取寄存器状态
for (i = 0; i < length;i++)
{
buffer[i] = SPIReadWriteByte(READ_ADDRESS);         //读数据
}
return registerStatus;
}
//
// 函数:   SPIWriteBufferRegister
// 功能:写寄存器指定长度数据
// 返回: 寄存器状态值
// 参数: registerAddress:寄存器地址 buffer:数据 length:长度
//
uint8_t SPI::SPIWriteBufferRegister(uint8_t registerAddress, uint8_t *buffer, uint8_t length)
{
uint8_t registerStatus;
uint8_t i;
registerStatus = SPIReadWriteByte(registerAddress);     //读取寄存器状态
for (i = 0; i < length; i++)
{
SPIReadWriteByte(*buffer);                              //写数据
buffer++;
}
return registerStatus;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  stm32