STM32—SPI通信(下)

本节为STM32内部硬件外设—SPI。通过stm32内部SPI 硬件读写W25Q64.

  1. STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担
  2. 可配置8位/16位数据帧、高位先行/低位先行
  3. 时钟频率: fPCLK / (2, 4, 8, 16, 32, 64, 128, 256) 支持多主机模型、主或从操作
  4. 可精简为半双工/单工通信
  5. 支持DMA 兼
  6. 容I2S协议

SPI1、SPI2挂载在不同的APB总线。

一、SPI硬件介绍

1.1、SPI硬件框图

其中LSBFIRST 是用于配置高位先行还是低位先行。  

1.2、SPI硬件传输模式

1.2.1、非连续传输

在TNX标志位置1,TDR为空,软件写入数据至SPI_DR,随后TDR(SPI_DR)值为1,TNX值为0,此时发送缓存数据区也为空,数据立即转入发送数据寄存器进行发送;波形产生,TNX值重新置为1(表示下一个数据可以写入TDR等待),但此时并不急于写入数据,而是等待第一个字节时序结束(意味接收一个字节也完成了),此时RXNE=1,读取一个字节完成后,在写入下一个数据。

二、SPI相关代码简介

2.1、SPI_Init()*

//根据SPI_InitStruct中指定的参数初始化SPIx外围设备。

SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

2.2、SPI_StructInit()*

//用默认值填充每个SPI_InitStruct成员

SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct);

2.3、SPI_Cmd()*

//启用或禁用指定的SPI外围设备。

SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);

2.4、SPI_I2S_ITConfig()

SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);

//启用或禁用指定的SPI/I2S中断

SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

2.5、SPI_I2S_DMACmd()

//启用或禁用SPIx/I2Sx DMA接口。

SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);

2.6、SPI_I2S_SendData()*

//通过SPIx/I2Sx外围设备传输数据

SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);

2.7、SPI_I2S_ReceiveData()*

//返回SPIx/I2Sx外围设备最近接收到的数据。

SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

2.8、SPI_I2S_GetFlagStatus()*

//检查指定的SPI/I2S标志是否已设置

SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);

2.9、SPI_I2S_ClearFlag()*

//清除SPIx CRC错误(CRCERR)标志。

SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);

2.10、SPI_I2S_GetITStatus()

//检查指定的SPI/I2S中断是否已发生

SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);

三、现象代码

这是STM32 SPI的配置流程图。主要配置内容有以下几点:

【1】开启GPIO、SPI 的时钟

【2】初始化 GPIO、SPI ,

【3】开关控制 Cmd

3.1、MySPI.c文件

由于 SPI 硬件读取 W25Q64 功能代码相较于 软件读写,主要差异体现在SPI 通信底层代码的不同,软件主要通过手动翻转引脚电平,而硬件主要通过自身硬件电路实现电平自由 翻转,因此以下代码主要是MySPI.C文件的更改,其余文件代码无变动 。

void MySPI_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ;//SS
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//MISO
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;//SCLK&MOSI
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	SPI_InitTypeDef SPI_InitStrycture;
	SPI_InitStrycture.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_128;
	SPI_InitStrycture.SPI_CPHA=SPI_CPHA_1Edge;	//CPHA=0
	SPI_InitStrycture.SPI_CPOL=SPI_CPOL_Low;  //CPOL=0
	SPI_InitStrycture.SPI_CRCPolynomial=7;
	SPI_InitStrycture.SPI_DataSize=8;//8为数据帧
	SPI_InitStrycture.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//全双工通信
	SPI_InitStrycture.SPI_FirstBit=SPI_FirstBit_MSB;//高位输出
	SPI_InitStrycture.SPI_Mode=SPI_Mode_Master;//主设备
	SPI_InitStrycture.SPI_NSS=SPI_NSS_Soft;//软件控制
	SPI_Init(SPI1,&SPI_InitStrycture);
	SPI_Cmd(SPI1,ENABLE );
	
	
}

由于SCLK 与MOSI SHI 是有硬件外设控制输出信号,因此 引脚配置为复用推挽输出 AF_PP 

【1】SPI_BaudRatePrescaler:指定波特率预分频器值,用于配置发送和接收SCK时钟

【2】SPI_CPHA:指定位捕获的时钟活动边沿,即选择CPHA的值(CPHA=0  or CPHA=1)
【3】.SPI_CPOL:指定串行时钟稳定状态。即选择 CLOP值   (CLOP=0 or CLOP=1)
【4】SPI_CRCPolynomial:指定用于CRC计算的多项式


【5】SPI_DataSize:用于配置SPI通信中每个数据帧的数据位数的参数。即决定收发数据是8位还是16位
【6】SPI_Direction:用于配置SPI通信的数据传输方向的参数。
【7】SPI_FirstBit:指定数据传输是从MSB位开始还是从LSB位开始。即LSBFIRST 位觉得高位先行还是低位先行。
【8】SPI_Mode:用于配置SPI通信的工作模式,即选择设备室主设备还是从设备
【9】SPI_NSS 指定NSS信号是由硬件(NSS引脚)管理还是由使用SSI位的软件管理

3.2、 引脚控制&基本时序

void MySPI_W_SS(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOA ,GPIO_Pin_4,(BitAction)BitValue);
}

void MySPI_Star(void)
{
	MySPI_W_SS(0);

}

void MySPI_Stop(void)
{
	MySPI_W_SS(1);
}

uint8_t MySPI_WriteRead_0(uint8_t Bytesend)
{
	while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) != SET);
	SPI_I2S_SendData(SPI1,Bytesend);
	while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) != SET);
	return  SPI_I2S_ReceiveData(SPI1);

}

【1】相较于上节 内容,本文件实例代码删除了  MySPI_W_SCLK()、MySPI_W_MOSI()、MySPI_R_MISO(),如下图所示。

【2】MySPI_WriteRead_0 函数考虑使用 if 语句实现,但是发现其逻辑与 while 语句逻辑存在不同,且无法实现设想功能,因此使用while 语句。

更新:可以使用以下语句

uint8_t MySPI_WriteRead_0(uint8_t Bytesend)
{
	uint8_t i=0x00;
	if(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == SET)
	{
		SPI_I2S_SendData(SPI1,Bytesend);
		while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);
	}
	
	return SPI_I2S_ReceiveData(SPI1);;
}

本节内容到此结束,如有补充将及时更新。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
stm32spi通信是指在STM32微控制器中使用SPI(串行外设接口)进行通信的一种方式。SPI是一种全双工、同步的串行通信协议,适用于芯片间的高速数据传输。在STM32中,可以通过引脚配置和SPI相关的寄存器设置来实现SPI通信。 在SPI通信中,通常有一个主设备和一个或多个从设备。主设备负责发起通信并控制数据传输的时序,而从设备则根据主设备的指令进行响应。 在STM32中,可以使用相关的库函数和头文件来实现SPI通信。例如,可以使用W25Q64.h和MySPI.h这两个头文件来初始化SPI接口和定义相关的函数。其中,W25Q64.h中定义了一些函数,如W25Q64_Init()用于初始化W25Q64芯片,W25Q64_ReadID()用于读取芯片的ID,W25Q64_PageProgram()用于向芯片写入数据,W25Q64_SectorErase()用于擦除扇区,W25Q64_ReadData()用于读取数据。而MySPI.h中定义了MySPI_Init()用于初始化SPI接口,MySPI_Start()用于启动SPI传输,MySPI_Stop()用于停止SPI传输,MySPI_SwapByte()用于交换数据字节。 通过调用这些函数和使用SPI的相关寄存器,我们可以实现STM32与其他设备之间的SPI通信。例如,可以使用W25Q64芯片进行数据存储和读取,通过SPI接口与STM32进行通信。 总结起来,stm32spi通信是一种使用SPI接口进行通信的方法,通过在STM32中使用相应的库函数和头文件,我们可以初始化SPI接口并实现与其他设备之间的数据传输。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [STM32——SPI通信](https://blog.csdn.net/NRWHF/article/details/129482253)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘洲青年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值