16.HAL库之SPI和QSPI

2019-08-16来源: eefocus关键字:HAL库  SPI  QSPI

1.SPI协议(以RN8302为例)


SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线(SCSN,SCLK,SDI,SDO).


总结传输流程:


a.写时序


SCSN拉低,开启通讯。主机依次写入地址,命令,数据(高位在前,低位在后),CS校验。主机在SCLK下降沿将数据通过SDI写入从机。最后SCSN拉高结束通讯。


b.读时序


SCSN拉低开启通讯,主机先写入地址+命令共两个字节,随后在SCLK下降沿读取从机从SDO输出的数据(高位在前,低位在后)。最后SCSN拉高结束通讯。


驱动程序编写:头文件中需定义管脚控制命令,寄存器地址,芯片命令。c文件中依次编写读写字节,读写帧数据,读写寄存器,芯片初始化等函数。


RN8302具体驱动程序见: https://download.csdn.net/download/weixin_42480952/10772976


主机(STM32F746)只需配置SPI接口即可,具体流程为:开启时钟,GPIO管脚配置,SPI配置。


2.QSPI


QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI 是一种专用的通信接口,连接单、双或四(条数据线) SPI Flash 存储介质。共有SNCS,SCLK,BK0,BK1,BK2,BK3共6根接线,可以实现多种通信模式。


主机需进行QSPI接口的配置,QSPI协议主要通过发送命令来进行通讯,因此主机的配置包括管脚配置,QSPI初始化。


QUADSPI通过命令和FLASH通讯,命令包括:指令+地址+交替字节+空周期+数据五个阶段,并且各阶段可省略。


单线SPI模式:BK_IO0即SO,BK_IO1即SI,加上NCS和SCLK,类似于SPI模式。


双线SPI模式:BK_IO0和BK_IO1实现数据的双入双出。


四线SPI模式:BK_IO0,BK_IO1,BK_IO2,BK_IO3四根线实现数据的传输。


SDR模式:QSPI驱动IO0~IO3在SCLK的下降沿进行数据变化。


DDR模式:在该模式下,指令阶段在SCLK下降沿发送数据,而在地址,交替字节,数据阶段在SCLK上升沿和下降沿均发送数据。


双闪存模式:使用两个外部SPI四线,可将flash扩大一倍。


QSPI配置:


时钟使能,管脚定义,QSPI配置,flash初始化,QSPI读/写函数定义。


void Qspi_Config()

{

__HAL_RCC_QSPI_CLK_ENABLE();

__HAL_RCC_GPIOB_CLK_ENABLE();

__HAL_RCC_GPIOF_CLK_ENABLE();

Flash_GPIO.Pin=GPIO_PIN_2;

Flash_GPIO.Mode=GPIO_MODE_AF_PP;

Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;

Flash_GPIO.Pull=GPIO_NOPULL;

Flash_GPIO.Alternate=GPIO_AF9_QUADSPI;

HAL_GPIO_Init(GPIOB,&Flash_GPIO);   //QSPI_CLK, PB2

Flash_GPIO.Pin=GPIO_PIN_6;

Flash_GPIO.Mode=GPIO_MODE_AF_PP;

Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;

Flash_GPIO.Pull=GPIO_PULLUP;

Flash_GPIO.Alternate=GPIO_AF10_QUADSPI;

HAL_GPIO_Init(GPIOB,&Flash_GPIO);   //QSPI_NCS, PB6

Flash_GPIO.Pin=GPIO_PIN_8;

Flash_GPIO.Mode=GPIO_MODE_AF_PP;

Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;

Flash_GPIO.Pull=GPIO_NOPULL;

Flash_GPIO.Alternate=GPIO_AF10_QUADSPI;

HAL_GPIO_Init(GPIOF,&Flash_GPIO);   //QSPI_IO0, PF8

Flash_GPIO.Pin=GPIO_PIN_9;

Flash_GPIO.Mode=GPIO_MODE_AF_PP;

Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;

Flash_GPIO.Pull=GPIO_NOPULL;

Flash_GPIO.Alternate=GPIO_AF10_QUADSPI;

HAL_GPIO_Init(GPIOF,&Flash_GPIO);   //QSPI_IO1, PF9

Flash_GPIO.Pin=GPIO_PIN_7;

Flash_GPIO.Mode=GPIO_MODE_AF_PP;

Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;

Flash_GPIO.Pull=GPIO_NOPULL;

Flash_GPIO.Alternate=GPIO_AF9_QUADSPI;

HAL_GPIO_Init(GPIOF,&Flash_GPIO);   //QSPI_IO2, PF7

Flash_GPIO.Pin=GPIO_PIN_6;

Flash_GPIO.Mode=GPIO_MODE_AF_PP;

Flash_GPIO.Speed=GPIO_SPEED_FREQ_MEDIUM;

Flash_GPIO.Pull=GPIO_NOPULL;

Flash_GPIO.Alternate=GPIO_AF9_QUADSPI;

HAL_GPIO_Init(GPIOF,&Flash_GPIO);   //QSPI_IO3, PF6

  QSPI_Flash.Instance=QUADSPI;

QSPI_Flash.Init.ClockPrescaler=2;

QSPI_Flash.Init.FifoThreshold=4;

QSPI_Flash.Init.SampleShifting=QSPI_SAMPLE_SHIFTING_HALFCYCLE;

QSPI_Flash.Init.FlashSize=25;

QSPI_Flash.Init.ChipSelectHighTime=QSPI_CS_HIGH_TIME_8_CYCLE;

QSPI_Flash.Init.ClockMode=QSPI_CLOCK_MODE_0;

HAL_QSPI_Init(&QSPI_Flash);

}

 


void QSPI_Read(uint8_t *data,uint32_t addr, uint32_t size)

{

QSPI_CommandTypeDef flash_command;

flash_command.InstructionMode=QSPI_INSTRUCTION_1_LINE;

flash_command.Instruction=0x13;

flash_command.Address=addr;

flash_command.AddressMode=QSPI_ADDRESS_1_LINE;

flash_command.AddressSize=QSPI_ADDRESS_32_BITS;

flash_command.AlternateByteMode=QSPI_ALTERNATE_BYTES_NONE;

flash_command.DataMode=QSPI_DATA_1_LINE;

flash_command.DummyCycles=0;

flash_command.NbData=size;

flash_command.DdrMode=QSPI_DDR_MODE_DISABLE;

flash_command.DdrHoldHalfCycle=QSPI_DDR_HHC_ANALOG_DELAY;

flash_command.SIOOMode=QSPI_SIOO_INST_EVERY_CMD;

HAL_QSPI_Command(&QSPI_Flash,&flash_command,HAL_QPSI_TIMEOUT_DEFAULT_VALUE);

  HAL_QSPI_Receive(&QSPI_Flash,data,1000); //读取的数据放入*data中,共size个字节

  QSPI_AutoPollingMemReady();

}

 

void QSPI_WritePage(uint8_t *pData,uint32_t WriteAddr, uint32_t Size)

{

QSPI_CommandTypeDef flash_command;

QSPI_WriteEnable();

flash_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;

  flash_command.Instruction       = 0x12;

  flash_command.AddressMode       = QSPI_ADDRESS_1_LINE;

  flash_command.AddressSize       = QSPI_ADDRESS_32_BITS;

flash_command.Address           = WriteAddr;

  flash_command.NbData            = Size;

  flash_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;

  flash_command.DataMode          = QSPI_DATA_1_LINE;

  flash_command.DummyCycles       = 0;

  flash_command.DdrMode           = QSPI_DDR_MODE_DISABLE;

  flash_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;

  flash_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;

HAL_QSPI_Command(&QSPI_Flash, &flash_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);

  HAL_QSPI_Transmit(&QSPI_Flash, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE);

QSPI_AutoPollingMemReady();

}


关键字:HAL库  SPI  QSPI

编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic471332.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:HAL库之485+DMA通信(STM32F746)
下一篇:stm32矩阵键盘输入多位数据

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

使用stm32的HAL库完成pwm输入模式测量频率和占空比的详细教程

。 然后使能TIM2的中断接下来添加代码:main.c 中开启捕获中断    /* USER CODE BEGIN 2 */    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);//如果不需要占空比和频率数据就只开通道2即可。第一次的数据是不正确的,实际工作中要将第一次的数据丢弃    /* USER CODE END 2 */      
发表于 2019-08-21
使用stm32的HAL库完成pwm输入模式测量频率和占空比的详细教程

HAL库之485+DMA通信(STM32F746)

(uint32_t bound){  __HAL_RCC_GPIOD_CLK_ENABLE();  __HAL_RCC_USART2_CLK_ENABLE();   GPIO_InitTypeDef GPIO_Init2;   GPIO_Init2.Pin = GPIO_PIN_4;              //485_RTS  GPIO_Init2.Mode =GPIO_MODE_OUTPUT_PP;  GPIO_Init2.Pull = GPIO_NOPULL;  GPIO_Init2.Speed
发表于 2019-08-16
HAL库之485+DMA通信(STM32F746)

15-HAL库之定时器学习

RepetitionCounter;   //重复计数,高级控制定时器所用   uint32_t AutoReloadPreload;   //自动预装载值}TIM_Base_InitTypeDef;应用例子如下:#include "basic_tim.h"TIM_HandleTypeDef Basic_Tim6;void Basic_Tim_Config(void){ HAL_TIM_Base_MspInit(&Basic_Tim6); __HAL_RCC_TIM6_CLK_ENABLE(); Basic_Tim6.Instance=TIM6
发表于 2019-08-16
15-HAL库之定时器学习

14-HAL库之I2C通信

发送停止传输信号P。读数据时,主机向从机发应答信号,当主机希望停止接收数据时,发送非应答信号。起始信号和停止信号见上图。数据有效性见上图。2.基于HAL库的I2C配置步骤:时钟使能—GPIO管脚配置—I2C配置初始化:void MyI2C_Init(void){ __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_6;  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;  GPIO_InitStruct.Pull
发表于 2019-08-16
14-HAL库之I2C通信

13-HAL库DMA系统总结

。2.DMA相关函数解析关于DMA,ST官方提供了HAL库(封装函数)和LL库(直接操作寄存器)。和GPIO定义类似,需要先使能相关时钟,定义句柄结构体DMA_HandleTypeDef mydma2,随后进行DMA的各项配置,最后进行初始化。typedef struct __DMA_HandleTypeDef{    DMA_Stream_TypeDef          *Instance;                       
发表于 2019-08-16
13-HAL库DMA系统总结

初探STM32 SPI2中断接收多组数据的处理方式

一、描述        两块STM32板子之间进行SPI通讯,都使用的是SPI2。主机连续发送多组数据(数据的格式为半字,即16位),从机采用SPI2中断方式接受主机发过来的多组数据。针对从机中断接受方法我尝试了两种方案:方案一:从机每接收主机发来的一组数据就进入中断一次,即主机发来几组数据从机就进入几次中断。方案二:仅当主机发来第一组数据时,从机才触发一次中断,然后关闭中断,以循环接受的方式接受主机发过来的剩下几组数据,当所有数据接受完后,再打开从机的接受中断。二、程序        因为两种方案的主机程序是一样的,如下:uint16_t 
发表于 2019-08-15

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved