STM32的SPI1、SPI2、SPI3初始化及RF1101的应用(标准库与HAL库)
——基于STM32F103RCT6
---- 标准库:
说明:相关文件共有两个:bsp_spi_cc1101.h;bsp_spi_cc1101.c;以SPI2为例。
1、“bsp_spi_cc1101.h”中的参数定义:
#ifndef _BSP_SPI_1101_H_
#define _BSP_SPI_1101_H_
#include 《stdio.h》
#include “stm32f10x.h”
#include “misc.h”
#include “os_cfg_app.h”
#include “os.h”
#include “core_cm3.h”
#include “bsp.h”
#include “stm32f10x_spi.h”
#define CSN_CC1101_GPIO GPIOB
#define CSN_CC1101_GPIO_PIN GPIO_Pin_12
#define SPI_CC1101_GPIO GPIOB
#define SCK_CC1101_GPIO_PIN GPIO_Pin_13
#define MISO_CC1101_GPIO_PIN GPIO_Pin_14
#define MOSI_CC1101_GPIO_PIN GPIO_Pin_15
#define GDO0_CC1101_GPIO GPIOA
#define GDO0_CC1101_GPIO_PIN GPIO_Pin_11
#define SPI_GPIO_RCC_1 RCC_APB2Periph_GPIOB
#define SPI_GPIO_RCC_2 RCC_APB2Periph_GPIOA
#define CC1101_SPI SPI2
#define CSN_SET GPIO_SetBits(GPIOB,GPIO_Pin_12)
#define CSN_RESET GPIO_ResetBits(GPIOB,GPIO_Pin_12)
void SPI_CC1101_Init(void);
u8 SPI2_ReadWriteByte(u8 TxData);
#endif
2、“bsp_spi_cc1101.c”中的引脚及SPI功能初始化:
#include “bsp_spi_cc1101.h”
void SPI_CC1101_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(SPI_GPIO_RCC_1 | SPI_GPIO_RCC_2,ENABLE); //初始化GPIO时钟
/*********SPI1初始化内容****
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); //初始化SPI1时钟
******SPI1初始化内容******/
/*********SPI2初始化内容************/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); //初始化SPI2时钟
/********SPI3需要初始化的内容********
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); //初始化SPI3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //初始化复用IO时钟,重定向IO口
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //由于SPI3占用JTAG口,所以需要关闭JTAG
******SPI3需要初始化的内容*******/
//片选设定成通用IO模式
GPIO_InitStructure.GPIO_Pin=CSN_CC1101_GPIO_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(CSN_CC1101_GPIO,&GPIO_InitStructure);
//SCK时钟IO初始化
GPIO_InitStructure.GPIO_Pin=SCK_CC1101_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);
//MISO的IO初始化
GPIO_InitStructure.GPIO_Pin=MISO_CC1101_GPIO_PIN;
GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);
//MOSI的IO初始化
GPIO_InitStructure.GPIO_Pin=MOSI_CC1101_GPIO_PIN;
GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);
//RF1101中用到的GDO0的IO初始化
GPIO_InitStructure.GPIO_Pin=GDO0_CC1101_GPIO_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GDO0_CC1101_GPIO,&GPIO_InitStructure);
//SPI模式设置
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex; //全双工模式
SPI_InitStructure.SPI_Mode=SPI_Mode_Master; //主设备模式
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b; //8字节数据通信
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟空闲时为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //时钟奇数边沿采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件控制NSS(CSN)位
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //通信速率设定,波特率预分频值
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC计算多项式
SPI_Init(CC1101_SPI, &SPI2_InitStructure); //初始化
SPI_Cmd(CC1101_SPI, ENABLE); //使能
SPI2_ReadWriteByte(0xFF); //RF1101启动传输
}
u8 SPI2_ReadWriteByte(u8 TxData)
{
u8 Rxdata;
uint32_t SPITimeout =0x1000;
while (SPI_I2S_GetFlagStatus(CC1101_SPI , SPI_I2S_FLAG_TXE) == RESET) //检测发送缓存区是否为空
{
if((SPITimeout--) == 0)
return 0;
}
SPI_I2S_SendData(CC1101_SPI,TxData); //发送一个字节
while (SPI_I2S_GetFlagStatus(CC1101_SPI , SPI_I2S_FLAG_RXNE) == RESET) //检测接收缓存区是否为空
{
if((SPITimeout--) == 0) return 0;
}
Rxdata = SPI_I2S_ReceiveData(CC1101_SPI); //存储一个字节
return Rxdata;
}
}
---- HAL库:
以SPI1为例:
SPI_HandleTypeDef SPI1_Handler;
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_SPI1_CLK_ENABLE(); //使能SPI1时钟
//NSS配置成通用IO口
GPIO_Initure.Pin=GPIO_PIN_4;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
//SPI引脚初始化
GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_Initure.Mode=GPIO_MODE_AF_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
//SPI功能配置
SPI1_Handler.Instance=SPI1; //SPI1
SPI1_Handler.Init.Mode=SPI_MODE_MASTER; //主模式
SPI1_Handler.Init.Direction=SPI_DIRECTION_2LINES; //双线模式
SPI1_Handler.Init.DataSize=SPI_DATASIZE_8BIT; //发送接收8位帧结构
SPI1_Handler.Init.CLKPolarity=SPI_POLARITY_LOW; //时钟的空闲状态为高电平
SPI1_Handler.Init.CLKPhase=SPI_PHASE_1EDGE; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI1_Handler.Init.NSS=SPI_NSS_SOFT; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI1_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256; //定义波特率预分频的值:波特率预分频值为256
SPI1_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI1_Handler.Init.TIMode=SPI_TIMODE_DISABLE; //关闭TI模式
SPI1_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE; //关闭硬件CRC校验
SPI1_Handler.Init.CRCPolynomial=7; //CRC值计算的多项式
HAL_SPI_Init(&SPI1_Handler); //初始化
__HAL_SPI_ENABLE(&SPI1_Handler); //使能SPI1
SPI1_ReadWriteByte(0xFF); //RF1101启动传输
}
//SPI底层驱动,时钟使能,引脚配置
//此函数会被HAL_SPI_Init()调用
//hspi:SPI句柄
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_SPI1_CLK_ENABLE(); //使能SPI1时钟
//PB13,14,15
GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_Initure.Mode=GPIO_MODE_AF_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}
void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler)); //判断有效性
__HAL_SPI_DISABLE(&SPI1_Handler); //关闭SPI
SPI1_Handler.Instance-》CR1&=0XFFC7; //位3~5清零,用来设置波特率
SPI1_Handler.Instance-》CR1|=SPI_BaudRatePrescaler; //设置SPI速度
__HAL_SPI_ENABLE(&SPI1_Handler); //使能SPI
}
u8 SPI1_ReadWriteByte(u8 TxData)
{
u8 Rxdata;
HAL_SPI_TransmitReceive(&SPI1_Handler,&TxData,&Rxdata,1, 1000);
return Rxdata;
}
注:与HAL库有一定的区别;重点注意SPI3与其他两个的区别;务必要检测缓存区是否为空。
STM32的SPI1、SPI2、SPI3初始化及RF1101的应用(标准库与HAL库)
——基于STM32F103RCT6
---- 标准库:
说明:相关文件共有两个:bsp_spi_cc1101.h;bsp_spi_cc1101.c;以SPI2为例。
1、“bsp_spi_cc1101.h”中的参数定义:
#ifndef _BSP_SPI_1101_H_
#define _BSP_SPI_1101_H_
#include 《stdio.h》
#include “stm32f10x.h”
#include “misc.h”
#include “os_cfg_app.h”
#include “os.h”
#include “core_cm3.h”
#include “bsp.h”
#include “stm32f10x_spi.h”
#define CSN_CC1101_GPIO GPIOB
#define CSN_CC1101_GPIO_PIN GPIO_Pin_12
#define SPI_CC1101_GPIO GPIOB
#define SCK_CC1101_GPIO_PIN GPIO_Pin_13
#define MISO_CC1101_GPIO_PIN GPIO_Pin_14
#define MOSI_CC1101_GPIO_PIN GPIO_Pin_15
#define GDO0_CC1101_GPIO GPIOA
#define GDO0_CC1101_GPIO_PIN GPIO_Pin_11
#define SPI_GPIO_RCC_1 RCC_APB2Periph_GPIOB
#define SPI_GPIO_RCC_2 RCC_APB2Periph_GPIOA
#define CC1101_SPI SPI2
#define CSN_SET GPIO_SetBits(GPIOB,GPIO_Pin_12)
#define CSN_RESET GPIO_ResetBits(GPIOB,GPIO_Pin_12)
void SPI_CC1101_Init(void);
u8 SPI2_ReadWriteByte(u8 TxData);
#endif
2、“bsp_spi_cc1101.c”中的引脚及SPI功能初始化:
#include “bsp_spi_cc1101.h”
void SPI_CC1101_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(SPI_GPIO_RCC_1 | SPI_GPIO_RCC_2,ENABLE); //初始化GPIO时钟
/*********SPI1初始化内容****
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); //初始化SPI1时钟
******SPI1初始化内容******/
/*********SPI2初始化内容************/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); //初始化SPI2时钟
/********SPI3需要初始化的内容********
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE); //初始化SPI3时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //初始化复用IO时钟,重定向IO口
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //由于SPI3占用JTAG口,所以需要关闭JTAG
******SPI3需要初始化的内容*******/
//片选设定成通用IO模式
GPIO_InitStructure.GPIO_Pin=CSN_CC1101_GPIO_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(CSN_CC1101_GPIO,&GPIO_InitStructure);
//SCK时钟IO初始化
GPIO_InitStructure.GPIO_Pin=SCK_CC1101_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);
//MISO的IO初始化
GPIO_InitStructure.GPIO_Pin=MISO_CC1101_GPIO_PIN;
GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);
//MOSI的IO初始化
GPIO_InitStructure.GPIO_Pin=MOSI_CC1101_GPIO_PIN;
GPIO_Init(SPI_CC1101_GPIO,&GPIO_InitStructure);
//RF1101中用到的GDO0的IO初始化
GPIO_InitStructure.GPIO_Pin=GDO0_CC1101_GPIO_PIN;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GDO0_CC1101_GPIO,&GPIO_InitStructure);
//SPI模式设置
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex; //全双工模式
SPI_InitStructure.SPI_Mode=SPI_Mode_Master; //主设备模式
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b; //8字节数据通信
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟空闲时为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //时钟奇数边沿采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //软件控制NSS(CSN)位
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //通信速率设定,波特率预分频值
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC计算多项式
SPI_Init(CC1101_SPI, &SPI2_InitStructure); //初始化
SPI_Cmd(CC1101_SPI, ENABLE); //使能
SPI2_ReadWriteByte(0xFF); //RF1101启动传输
}
u8 SPI2_ReadWriteByte(u8 TxData)
{
u8 Rxdata;
uint32_t SPITimeout =0x1000;
while (SPI_I2S_GetFlagStatus(CC1101_SPI , SPI_I2S_FLAG_TXE) == RESET) //检测发送缓存区是否为空
{
if((SPITimeout--) == 0)
return 0;
}
SPI_I2S_SendData(CC1101_SPI,TxData); //发送一个字节
while (SPI_I2S_GetFlagStatus(CC1101_SPI , SPI_I2S_FLAG_RXNE) == RESET) //检测接收缓存区是否为空
{
if((SPITimeout--) == 0) return 0;
}
Rxdata = SPI_I2S_ReceiveData(CC1101_SPI); //存储一个字节
return Rxdata;
}
}
---- HAL库:
以SPI1为例:
SPI_HandleTypeDef SPI1_Handler;
void SPI1_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_SPI1_CLK_ENABLE(); //使能SPI1时钟
//NSS配置成通用IO口
GPIO_Initure.Pin=GPIO_PIN_4;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
//SPI引脚初始化
GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_Initure.Mode=GPIO_MODE_AF_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
//SPI功能配置
SPI1_Handler.Instance=SPI1; //SPI1
SPI1_Handler.Init.Mode=SPI_MODE_MASTER; //主模式
SPI1_Handler.Init.Direction=SPI_DIRECTION_2LINES; //双线模式
SPI1_Handler.Init.DataSize=SPI_DATASIZE_8BIT; //发送接收8位帧结构
SPI1_Handler.Init.CLKPolarity=SPI_POLARITY_LOW; //时钟的空闲状态为高电平
SPI1_Handler.Init.CLKPhase=SPI_PHASE_1EDGE; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI1_Handler.Init.NSS=SPI_NSS_SOFT; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI1_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256; //定义波特率预分频的值:波特率预分频值为256
SPI1_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI1_Handler.Init.TIMode=SPI_TIMODE_DISABLE; //关闭TI模式
SPI1_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE; //关闭硬件CRC校验
SPI1_Handler.Init.CRCPolynomial=7; //CRC值计算的多项式
HAL_SPI_Init(&SPI1_Handler); //初始化
__HAL_SPI_ENABLE(&SPI1_Handler); //使能SPI1
SPI1_ReadWriteByte(0xFF); //RF1101启动传输
}
//SPI底层驱动,时钟使能,引脚配置
//此函数会被HAL_SPI_Init()调用
//hspi:SPI句柄
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟
__HAL_RCC_SPI1_CLK_ENABLE(); //使能SPI1时钟
//PB13,14,15
GPIO_Initure.Pin=GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_Initure.Mode=GPIO_MODE_AF_PP;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
}
void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler)); //判断有效性
__HAL_SPI_DISABLE(&SPI1_Handler); //关闭SPI
SPI1_Handler.Instance-》CR1&=0XFFC7; //位3~5清零,用来设置波特率
SPI1_Handler.Instance-》CR1|=SPI_BaudRatePrescaler; //设置SPI速度
__HAL_SPI_ENABLE(&SPI1_Handler); //使能SPI
}
u8 SPI1_ReadWriteByte(u8 TxData)
{
u8 Rxdata;
HAL_SPI_TransmitReceive(&SPI1_Handler,&TxData,&Rxdata,1, 1000);
return Rxdata;
}
注:与HAL库有一定的区别;重点注意SPI3与其他两个的区别;务必要检测缓存区是否为空。
举报