STM32F030 使用硬件 SPI


前言

以前玩過一點 STM32 單片機(主要是 STM32F103 系列),去年(2017)STM32F1 漲到不知哪里去了,今年好像降下來了。F0 系列相比 F1 系列少了一些功能,最高主頻只到 48M(F1 是 72M),但是價格便宜啊,剛好最近工作需要重新接觸了 STM32F030,記錄一下。PS:研究了幾天覺得 STM32 的各個組成部分還是很精妙的,雖然繁雜但是庫函數化解了這個問題。

步驟

SPI 初始化

STM32F030 默認的 SPI1 接口如下,其中 CSN 由軟件控制,所以可以改為其他 IO 口

#define SPI1_PORT       GPIOA
#define PIN_SPI1_CSN    GPIO_Pin_4
#define PIN_SPI1_SCK    GPIO_Pin_5
#define PIN_SPI1_MISO   GPIO_Pin_6
#define PIN_SPI1_MOSI   GPIO_Pin_7

#define SPI1_CSN_L  (SPI1_PORT->BRR  = PIN_SPI1_CSN)
#define SPI1_CSN_H  (SPI1_PORT->BSRR = PIN_SPI1_CSN)

初始化

void SPI1_INIT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	SPI_InitTypeDef   SPI_InitStructure;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;    //復用功能
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    //推挽輸出
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;    //下拉
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;    //中速
	GPIO_InitStructure.GPIO_Pin = PIN_SPI1_SCK | PIN_SPI1_MOSI | PIN_SPI1_MISO;
	GPIO_Init(SPI1_PORT, &GPIO_InitStructure);

	GPIO_PinAFConfig(SPI1_PORT, GPIO_PinSource5, GPIO_AF_0);
	GPIO_PinAFConfig(SPI1_PORT, GPIO_PinSource6, GPIO_AF_0);
	GPIO_PinAFConfig(SPI1_PORT, GPIO_PinSource7, GPIO_AF_0);

	GPIO_InitStructure.GPIO_Pin = PIN_SPI1_CSN;    //配置 CSN
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    //高速
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;    //輸出模式
	GPIO_Init(SPI1_PORT, &GPIO_InitStructure);

	SPI_I2S_DeInit(SPI1);    //將寄存器重設為缺省值
	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;    //通信空閑時 SCK 為低電平
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;    //第一個時鍾沿捕獲
	SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;    //軟件控制 NSS
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;    //SPI 速度 8 分頻
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //數據傳輸從 MSB 開始
	SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC 校驗
	SPI_Init(SPI1, &SPI_InitStructure);
	SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_QF);    //重要,把應答數據位設置為 8 位
	SPI_Cmd(SPI1, ENABLE);
}

傳輸數據

讀取和發送數據需要檢查標志位

void SPI1_WriteByte(uint8_t TxData)
{
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);    //檢查發送是否完成 
	SPI_SendData8(SPI1, TxData);
}

uint8_t SPI1_ReadByte(void)
{
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);    //檢查接收標志位
	return(SPI_ReceiveData8(SPI1));
}

uint8_t SPI1_Transfer(uint8_t data)
{
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
	SPI_SendData8(SPI1, data);
	while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
	return SPI_ReceiveData8(SPI1);
}

例子

用 SPI 與 NRF24L01 模塊通信

void NRF24L01_Write_Register(uint8_t reg, uint8_t data)
{
	SPI1_CSN_L;
	SPI1_Transfer(reg);
	SPI1_Transfer(data);
	SPI1_CSN_H;
}

uint8_t NRF24L01_Read_Register(uint8_t reg)
{
	uint8_t tmp;
	SPI1_CSN_L;
	SPI1_Transfer(reg);
	tmp = SPI1_Transfer(0);
	SPI1_CSN_H;
	return tmp;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM