STM32LL库使用——SPI通信

STM32使用前的准备

对于要使用的每个STM32芯片,首先我们手上必备的两本手册(ST官网有pdf版):

  1. 参考手册(Reference manual)
  2. 数据手册(Datasheet)

其中参考手册包括各个功能模块的具体信息、原理、各种工作模式介绍、配置方法以及寄存器相关信息;数据手册包括芯片的基本参数、引脚数量与各自功能、电气特性、封装信息等内容。一般在选型与硬件设计阶段,参考数据手册多一些,而到了程序设计阶段,参考手册就是必须的了。

以下是STM32G4系列的参考手册的“自我介绍”:

This reference manual targets application developers. It provides complete information on how to use the STM32G4 Series microcontroller memory and peripherals.

本参考手册的目标是应用程序开发人员。 它提供了关于的完整信息如何使用STM32G4系列单片机的内存和外设。  

SPI相关设置

我们以STM32G系列为例,直接翻到SPI章节,SPI结构示意图如下:

一共4个引脚可与外设连接:

  • MISO(Master In / Slave Out data:该引脚在从模式下发送数据,在主模式下接收数据
  • MOSI(Master Out / Slave In data):该引脚在主模式下发送数据,在从模式下接收数据
  • SCK(Serial Clock):主设备往从设备传输的时钟信号
  • NSS(Slave select):用于主设备选择从设备

 单个主设备与单个从设备全双工通信模式示意图如下:

我们采用STM32CubeMX可以方便的完成基础配置,实际只需要编写如下实际通讯需要的代码

基础通讯代码

Tx:发送缓冲区;Rx:接收缓冲区;DR:数据寄存器

状态指示标志:

  • Tx buffer empty flag (TXE):发送缓冲区为空
  • Rx buffer not empty (RXNE):接收缓冲区非空
  • Busy flag (BSY):SPI数据正在传输中

基本工作原理:主机向从机发送一个值(指令),然后从机依据接收到的指令返回一个值

常见情况我们用STM32作为主机

  1.  等待TXE标志置1(Tx空),表明此时发送缓冲区Tx中无待发送的值
  2. 将数据写入SPIx_DR寄存器,对DR的写操作将把数据写入Tx末尾
  3. 等待BSY标志置0(即busy,置1表明Tx中的数据正在传输中)。期间数据通过MOSI发送给从机,从机返回的信息通过MISO回到主机接收缓冲区Rx
  4. 等待RXNE标志置1(Rx非空),表明此时Rx存在接收到的值
  5. 读取SPIx_DR寄存器,对DR的读操作将返回Rx中最早的值
// data_in:待发送的值
// data_out:接收到的值
static int spi_transmit_receive(uint16_t data_in, uint16_t *data_out){
	int state = 0;
	*data_out = 0;
	uint32_t timeout_cnt;
	static const uint32_t timeout_cnt_num = 10000;
	
	// Wait until TXE flag is set to send data 
	timeout_cnt = 0;
	while(!LL_SPI_IsActiveFlag_TXE(SPI1)){
		timeout_cnt ++;
		if(timeout_cnt > timeout_cnt_num){
			state = -1;
			break;
		}
	}
	
	// Transmit data in 16 Bit mode
	LL_SPI_TransmitData16(SPI1, data_in);
	
	// Check BSY flag 
	timeout_cnt = 0;
	while(LL_SPI_IsActiveFlag_BSY(SPI1)){
		timeout_cnt ++;
		if(timeout_cnt > timeout_cnt_num){
			state = -1;
			break;
		}
	}
	
	// Check RXNE flag 
	timeout_cnt = 0;
	while(!LL_SPI_IsActiveFlag_RXNE(SPI1)){
		timeout_cnt ++;
		if(timeout_cnt > timeout_cnt_num){
			state = -1;
			break;
		}
	}
	
	// Read 16-Bits in the data register
	*data_out = LL_SPI_ReceiveData16(SPI1);
	
	return state;
}

 所涉及的LL库相关函数:

/**
  * @brief  Write 16-Bits in the data register
  * @rmtoll DR           DR            LL_SPI_TransmitData16
  * @param  SPIx SPI Instance
  * @param  TxData Value between Min_Data=0x00 and Max_Data=0xFFFF
  * @retval None
  */
__STATIC_INLINE void LL_SPI_TransmitData16(SPI_TypeDef *SPIx, uint16_t TxData)
{
#if defined (__GNUC__)
  __IO uint16_t *spidr = ((__IO uint16_t *)&SPIx->DR);
  *spidr = TxData;
#else
  SPIx->DR = TxData;
#endif /* __GNUC__ */
}

/**
  * @brief  Read 16-Bits in the data register
  * @rmtoll DR           DR            LL_SPI_ReceiveData16
  * @param  SPIx SPI Instance
  * @retval RxData Value between Min_Data=0x00 and Max_Data=0xFFFF
  */
__STATIC_INLINE uint16_t LL_SPI_ReceiveData16(SPI_TypeDef *SPIx)
{
  return (uint16_t)(READ_REG(SPIx->DR));
}

/**
  * @brief  Check if Tx buffer is empty
  * @rmtoll SR           TXE           LL_SPI_IsActiveFlag_TXE
  * @param  SPIx SPI Instance
  * @retval State of bit (1 or 0).
  */
__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_TXE(SPI_TypeDef *SPIx)
{
  return ((READ_BIT(SPIx->SR, SPI_SR_TXE) == (SPI_SR_TXE)) ? 1UL : 0UL);
}

/**
  * @brief  Get busy flag
  * @note   The BSY flag is cleared under any one of the following conditions:
  * -When the SPI is correctly disabled
  * -When a fault is detected in Master mode (MODF bit set to 1)
  * -In Master mode, when it finishes a data transmission and no new data is ready to be
  * sent
  * -In Slave mode, when the BSY flag is set to '0' for at least one SPI clock cycle between
  * each data transfer.
  * @rmtoll SR           BSY           LL_SPI_IsActiveFlag_BSY
  * @param  SPIx SPI Instance
  * @retval State of bit (1 or 0).
  */
__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_BSY(SPI_TypeDef *SPIx)
{
  return ((READ_BIT(SPIx->SR, SPI_SR_BSY) == (SPI_SR_BSY)) ? 1UL : 0UL);
}

/**
  * @brief  Check if Rx buffer is not empty
  * @rmtoll SR           RXNE          LL_SPI_IsActiveFlag_RXNE
  * @param  SPIx SPI Instance
  * @retval State of bit (1 or 0).
  */
__STATIC_INLINE uint32_t LL_SPI_IsActiveFlag_RXNE(SPI_TypeDef *SPIx)
{
  return ((READ_BIT(SPIx->SR, SPI_SR_RXNE) == (SPI_SR_RXNE)) ? 1UL : 0UL);
}

 实际使用spi_transmit_receive函数时,一般需要在函数前后设置以下片选NSS输出,通讯前选中当前从机,通讯后再关闭,防止多主机或者多从机模式时的冲突。

	// NSS片选引脚置0,开启当前主从关系
	LL_GPIO_ResetOutputPin(GPIOx, LL_GPIO_PIN_x);
	
	spi_transmit_receive(controlword, &recbuff);
	
	// NSS置1,关闭当前主从关系
	LL_GPIO_SetOutputPin(GPIOx, LL_GPIO_PIN_x);
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: STM32 LL是一种低级别的驱动,提供了对STM32微控制器底层寄存器的访问。SPI DMA(直接内存访问)是一种高效的数据传输方式,可以在通信过程中减少CPU的负担。 STM32 LL中提供了SPI和DMA的驱动函数,用户可以使用这些函数来实现SPI DMA传输。具体步骤如下: 1. 配置SPI口,设置传输速度、数据位数、时钟极性、时钟相位等参数。 2. 配置DMA,设置数据缓冲区、数据长度、传输方向等参数。接收数据时需要将DMA的传输方向设置为从外设到内存。 3. 启动DMA传输,并等待传输完成。传输完成后,可以通过DMA中断或查询方式来获取传输结果。 使用STM32 LLSPI DMA传输可以提高数据传输的效率,并减少CPU的负担。在实际应用中,用户需要根据实际需求进行配置和调试,以实现更好的性能和稳定性。 ### 回答2: STM32系列芯片是一款广泛应用于嵌入式系统中的微控制器,而LL则是ST公司开发的一套轻量级固件,提供了一系列的低级驱动,并结合HAL使用,方便开发者进行芯片驱动的编写。 SPI (Serial Peripheral Interface)总线是一种同步串行通信协议,在通信中分为一主多从的结构,可同时连接多个设备。SPI总线传输的数据速率快,适合短距离以高速率进行数据传输。SPI总线传输协议中有一种DMA模式,即在传输时使用DMA进行高速且低开销的数据传输。 在STM32芯片中使用LL编写SPI DMA的驱动程序,首先要初始化所需的GPIO引脚,设置SPI的时序及工作模式。LM中提供了LL_SPI_Init()函数,方便控制SPI总线通信的初始化。接着,设置DMA请求的方向与传输模式,即将SPI的数据缓存区作为数据的源头或数据的接收端。 在使用STM32 LL编写SPI DMA的驱动程序时,需要首先学习一些关于LLSPI和DMA的相关知识。SPI总线传输速度快、传输距离短,因此在嵌入式系统控制中应用广泛。同时,使用DMA模式进行数据传输可以减少CPU的使用率,提高数据传输效率,提高嵌入式系统的性能。 总之,LL提供了开发SPI DMA功能的方便工具,可以帮助开发者减轻编写驱动程序的负担,提高系统调试与运行的效率和可靠性。 ### 回答3: STM32是一系列由ST公司推出的ARM Cortex-M处理器,LL则是其官方提供的低级驱动,用于管理STM32芯片的外设。其中,SPI和DMA是两个重要的外设,下面将介绍STM32 LLSPI DMA的应用。 SPI,全称Serial Peripheral Interface,是一种串行接口协议,它的主要特点是简单易用、高效可靠、传输速率快等。在STM32中,SPI是一种重要的外设,它可以进行多种模式的数据传输,比如全双工、半双工、主从等。SPI通常用于与外部器件进行数据交互,比如存储器、传感器、LCD等。 而DMA,全称Direct Memory Access,是一种直接存储器访问技术,它可以实现数据的高速传输,减轻CPU的负担。在STM32中,DMA是一种独立的硬件模块,可以提高数据传输效率,尤其在处理大批量数据时更为明显。 在STM32使用SPI+DMA,可以提高数据传输的效率,减少CPU的占用率,提高系统的稳定性。在LL中,进行SPI+DMA传输可以分为以下步骤: 1. 初始化SPI和DMA模块:包括SPI的时钟配置、传输速率、工作模式,以及DMA的通道配置、数据长度等。 2. 启动DMA传输:首先将SPI的数据发送寄存器与DMA的内存地址关联,然后通过启动DMA传输,实现大批量数据的快速传输。 3. 等待传输完成:在DMA传输完成前,可以通过中断方式或轮询方式判断传输是否完成,等待传输完成后,即可进行下一步操作。 在使用SPI DMA传输时,需要注意以下几点: 1. SPI的数据传输模式必须是DMA模式,可以通过LLSPI_ClearFlag_DMATransfer完成。 2. DMA传输完成后,必须及时禁用DMA传输中断和DMA通道,以确保数据不会重复传输。 3. 在初始化SPI DMA时,要根据实际情况选择合适的传输模式和缓冲区大小,以确保数据传输的稳定性和可靠性。 总之,SPI和DMA是STM32中重要的外设,在LL的支持下,可以实现快速、高效、稳定的数据传输,提高系统的性能和可靠性。同时,在使用过程中,需要合理配置、正确使用,才能发挥它们的优势。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值