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;
}
posted @ 2018-08-19 00:47  HintLee  阅读(7810)  评论(0编辑  收藏  举报