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與其他兩個的區別;務必要檢測緩存區是否爲空。