玩转STM32CubeMX | SPI总线

最新更新时间:2021-10-14来源: eefocus关键字:STM32CubeMX  SPI总线  W25QXX 手机看文章 扫描二维码
随时随地手机看文章

1.SPI总线及W25QXX芯片

1.1 SPI总线简介

SPI全称Serial Peripheral Interface,即串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在EEPROM、FLASH、实时时钟、AD转换器,还有数字信号处理器和数字信号解码器之间。SPI是一种高速的、全双工、同步通讯总线,在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局节省空间提供了方便,正是这种简单易用的特性,如今越来越多的芯片集成了这种通讯协议。下图是SPI内部结构简易图

从上图可以看出,主设备和从设备都有一个串行移位寄存器,主设备通过向它的SPI串行寄存器写入一个字节来发起一次传输,寄存器通过MOSI信号线将字节传送给从设备,从设备也将自已的移位寄存器中的内容通过MISO信号线返回给主设备。这样两个移位寄存器中的内容就被交换。外设的写操作和读操作时同步完成的,如果只进行写操作,主设备只需要忽略接收到的字节,如果主设备要进行读操作,就必须发送一个空字节来引发从设备的传输。


SPI接口一般使用4条线通讯,单向传输时也可以使用3条线,其中3条线为SPI总线(MISO,MOSI,SCLK),1条为SPI片选信号线(CS),它们的作用如下:


*MISO:主设备数据输入,从设备数据输出


*MOSI:主设备数据输出,从设备数据输入


*SCLK:时钟信号,由主设备产生


*CS:从设备片选信号,由主设备控制


SPI使用MOSI/MISO信号线来传输数据,使用SCLK信号线进行数据同步。MOSI/MISO数据线在SCLK的每个时钟周期传输1位数据,且数据输入输出是同时进行的。数据传输时,MSB先行或LSB先行没有硬性规定,但是两个SPI通讯设备之间必须使用同样的协定,一般都会采用MSB先行模式。


当有多个SPI从设备与SPI主设备相连时,设备的MOSI/MISO/SCLK信号线并联到相同的SPI总线上,即无论有多少个从设备,都共同使用者3条总线;而每个从设备都有独立的1条CS信号线,该信号线独占主设备的一个引脚,即有多少个从设备就有多少条片选信号线。当主设备要选择从设备时,把该从设备的CS信号线设置为低电平,该从设备即被选中(片选有效),接着主设备开始与从设备进行SPI通讯。


SPI总线根据时钟极性(CPOL)和时钟相位(CPHA)的配置不同,可以有四种工作方式:

*MISO:主设备数据输入,从设备数据输出


*MOSI:主设备数据输出,从设备数据输入


*SCLK:时钟信号,由主设备产生


*CS:从设备片选信号,由主设备控制



1.2 W25QXX芯片简介

W25QXX芯片是华邦公司推出的大容量SPI FLASH产品,该系列有W25Q16/32/62/128等。本例程使用W25Q64,W25Q64容量为64Mbits(8M字节):8MB的容量分为128个块(Block)(块大小为64KB),每个块又分为16个扇区(Sector)(扇区大小为4KB);W25Q64的最小擦除单位为一个扇区即4KB,因此在选择芯片的时候必须要有4K以上的SRAM(可以开辟4K的缓冲区)。W25Q64的擦写周期多达10万次,具有20年的数据保存期限。下表是W25QXX的常用命令表

2.硬件设计

D1指示灯用来提示系统运行状态,K_UP按键用来控制W25Q64数据写入,K_DOWN按键用来控制W25Q64数据读取,串口1用来打印写入和读取的数据信息


*指示灯D1


*USART1串口


*W25Q64


*K_UP和K_DOWN按键


3.软件设计

3.1 STM32CubeMX设置

➡️ RCC设置外接HSE,时钟设置为72M

➡️ PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

➡️ USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位

➡️ PA0设置为GPIO输入模式、下拉模式;PE3设置为GPIO输入模式、上拉模式

➡️ PG13设置为GPIO推挽输出模式、上拉、高速(片选引脚)

➡️ 激活SPI2,不开启NSS,数据长度8位,MSB先输出,分频因子256,CPOL为HIGH,CPHA为第二个边沿,不开启CRC检验,NSS为软件控制

➡️输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码


3.2 MDK-ARM软件编程


➡️ 在spi.c文件下可以看到SPI2的初始化函数,片选管脚的初始化在gpio.c中


void MX_SPI2_Init(void){

  hspi2.Instance = SPI2;

  hspi2.Init.Mode = SPI_MODE_MASTER;//设置为主模式

  hspi2.Init.Direction = SPI_DIRECTION_2LINES;//双线模式

  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;//8位数据长度

  hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;//串行同步时钟空闲状态为高电平

  hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;//第二个跳变沿采样

  hspi2.Init.NSS = SPI_NSS_SOFT;//NSS软件控制

  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;//分配因子256

  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;//MSB先行

  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;//关闭TI模式

  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验

  hspi2.Init.CRCPolynomial = 10;

  if (HAL_SPI_Init(&hspi2) != HAL_OK){

    Error_Handler();

  }

}


void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle){

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  if(spiHandle->Instance==SPI2){

  __HAL_RCC_SPI2_CLK_ENABLE();  

  __HAL_RCC_GPIOB_CLK_ENABLE();

  /**SPI2 GPIO Configuration    

  PB13     ------> SPI2_SCK

  PB14     ------> SPI2_MISO

  PB15     ------> SPI2_MOSI */

  GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15;

  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_14;

  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

  GPIO_InitStruct.Pull = GPIO_NOPULL;

  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  }

}


➡️ 创建按键驱动文件key.c 和相关头文件key.h,参考按键输入例程


➡️ 创建包含W25Q64芯片的相关操作函数及驱动函数的文件w25qxx.c和w25qxx.h,这里仅介绍几个重要的函数,源文件下载方式见文末介绍


//这里仅介绍几个重要的函数

void W25QXX_Init(void){

  W25Qx_Disable();

  W25QXX_TYPE = W25QXX_ReadID();//读取芯片ID

  printf("FLASH ID:%Xrn",W25QXX_TYPE);

  if(W25QXX_TYPE == 0xc816)

    printf("FLASH TYPE:W25Q64rn");

}


uint16_t W25QXX_ReadID(void){

  uint16_t ID;

  uint8_t id[2]={0};

  uint8_t cmd[4] = {W25X_ManufactDeviceID,0x00,0x00,0x00};//读取ID命令

  W25Qx_Enable();//使能器件

  HAL_SPI_Transmit(&hspi2,cmd,4,1000);

  HAL_SPI_Receive(&hspi2,id,2,1000);

  W25Qx_Disable();//取消片选

  ID = (((uint16_t)id[0])<<8)|id[1];

  return ID;

}


void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead){

  uint8_t cmd[4] = {0};

  cmd[0] = W25X_ReadData;//读取命令

  cmd[1] = ((uint8_t)(ReadAddr>>16));

  cmd[2] = ((uint8_t)(ReadAddr>>8));

  cmd[3] = ((uint8_t)ReadAddr);


  W25Qx_Enable();//使能器件

  HAL_SPI_Transmit(&hspi2,cmd,4,1000);

  HAL_SPI_Receive(&hspi2,pBuffer,NumByteToRead,1000);

  W25Qx_Disable();//取消片选

}


void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite){

  uint32_t secpos;

  uint16_t secoff;

  uint16_t secremain;

  uint16_t i;

  uint8_t *W25QXX_BUF;

  W25QXX_BUF = W25QXX_BUFFER;

  secpos = WriteAddr/4096; //扇区地址

  secpos = WriteAddr%4096; //在扇区里的偏移

  secremain = 4096-secoff; //扇区剩余空间大小

  printf("WriteAddr:0x%X,NumByteToWrite:%drn",WriteAddr,NumByteToWrite);

  if(NumByteToWrite <= secremain)  //不大于4K字节

    secremain = NumByteToWrite;

  while(1){

    W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//读取整个扇区内容

    for(i=0;i      if(W25QXX_BUF[secoff+i] != 0xff)//需要擦除

break;

    }

    if(i < secremain){//需要擦除

      W25QXX_Erase_Sector(secpos);//擦除扇区

      for(i=0;i W25QXX_BUF[i+secoff] = pBuffer[i];

      }

      W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区

    }

    else{

      W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//写入扇区剩余空间

    }

    if(NumByteToWrite == secremain){//写入结束了

      break;

    }

    else{ //写入未结束

      secpos++; //扇区地址增1

      secoff = 0; //偏移位置为0

      pBuffer += secremain; //指针偏移

      WriteAddr += secremain; //写地址偏移

      NumByteToWrite -= secremain;//字节数递减

      if(NumByteToWrite > 4096)

secremain = 4096; //下个扇区还没是写不完

      else

secremain = NumByteToWrite;//下个扇区可以写完了

    }

  }

}


➡️ 在main.c文件下编写SPI测试代码


/* USER CODE BEGIN PV */

uint8_t wData[0x100];

uint8_t rData[0x100];

uint32_t i;

/* USER CODE END PV */

int main(void){

  /* USER CODE BEGIN 1 */

  uint8_t key;

  /* USER CODE END 1 */

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();

  MX_SPI2_Init();

  MX_USART1_UART_Init();

  /* USER CODE BEGIN 2 */

  W25QXX_Init();

  for(i=0;i<0x100;i++){

    wData[i] = i;

    rData[i] = 0;

  }

  /* USER CODE END 2 */

  while (1){

    key = KEY_Scan(0);

    if(key == KEY_UP_PRES){

      printf("KEY_UP_PRES write data...rn");

      W25QXX_Erase_Sector(0);

      W25QXX_Write(wData,0,256);

    }

    if(key == KEY_DOWN_PRES){

      printf("KEY_DOWN_PRES read data...rn");

      W25QXX_Read(rData,0,256);

      for(i=0;i<256;i++){

printf("0x%02X ",rData[i]);

      }

    }

    HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0);

    HAL_Delay(200);

  }

}


4.下载验证

编译无误下载到开发板后,可以看到D1指示灯不断闪烁,当按下K_UP按键后数据写入到W25Q64芯片内,当按下K_DOWN按键后读取W25Q64芯片的值,同时串口打印出相应信息

关键字:STM32CubeMX  SPI总线  W25QXX 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic546423.html

上一篇:玩转STM32CubeMX | 红外遥控
下一篇:玩转STM32CubeMX | DAC数模转换

推荐阅读

STM32CubeMX知识点
System CoreRCC高速外部时钟(HSE)选择:旁路时钟源(BYPASS Clock Source) : 也就是外部时钟源石英/陶瓷 晶振(Crystal/Ceramic Resonator)SYSSYS模块主要为调试选项Serial Wire : 通过SWD协议下载调试JTAG : 通过JTAG协议下载调试Trace Asynchonous Sw : SWD协议追踪功能JTAG with Trace Synchro : JTAG协议追踪功能
发表于 2022-08-08
<font color='red'>STM32CubeMX</font>知识点
AVR基础知识:ATMEGA的SPI总线 - 第1部分
当AVR与其他器件进行数据交互时,我们需要选择采用哪种方式。这里可以使用UART、I2C等经典的串口方式,也可以选择串行外设接口(SPI)。我比较喜欢SPI总线方式。那么让我们来聊一聊这种总线形式。关系在SPI中的一个重要的概念就是主从关系。一个设备作为主机,负责产生时钟信号并启动每次通信。除了时钟之外,其他设备在很多方面都像主机一样操作,而且只有在被呼叫时才会回应。一般情况下,SPI总线至少由四条线组成 - 也就是说,它需要每个器件的四个引脚。 他们是:● MOSI:主机输出,从机输入 - 数据从主机传输到从机。● MISO:主机输入,从机输出 - 用于从从机到主机的数据传输。● SCK:时钟线,有时也被标记为CLK。● SS:从
发表于 2022-07-28
AVR基础知识:ATMEGA的<font color='red'>SPI总线</font> - 第1部分
AVR基础知识:ATMEGA的SPI总线 - 第2部分
在第1部分中,我们在AVR ATMEGA328P微控制器上已经设置好SPI总线。现在我们就可以开始使用SPI了。设置相关引脚在开始之前,我们需要在AVR上设置SPI总线的引脚(在主机模式下使用)。我在这里使用的是ATMEGA328P,所以需要定义一些宏来使代码变得更清晰。如果您使用不同的微控制器,则可以根据您的需要进行调整。#define SPI_SS_GPIO PB2#define SPI_SS_PORT PORTB#define SPI_SS_DDR DDRB#define SPI_MOSI_GPIO PB3#define SPI_MOSI_PORT PORTB#define SPI_MOSI_DDR DDRB#define S
发表于 2022-07-28
AVR基础知识:ATMEGA的<font color='red'>SPI总线</font> - 第2部分
STM32基础1--STM32CubeMx项目配置
1.0:选择STM芯片 启动STM32CubeMx之后,点击File->New Project ,本人使用的是正点原子探索者STM32F407的开发版,因此在搜索栏输入芯片STM32F407ZGT6,然后双击,然后完成新建项目。 注:如果不知道开发板的芯片,可以查看供应商给的原理图或者直接看芯片的标识,建议最好看直接看芯片的标识。2.0:设置RCC3.0:设置SYS 注:在BUG里面有很多选项,根据自己开发板的接口选择,由于SWD(Serial Wire Debug)接线简单,现在市场的上开发板基本都是由于这个接口。4.0:硬件配置 正点原子探索者开发板中,有两个LED与4个按键5.0:配置引脚1)设置
发表于 2022-07-25
STM32基础1--STM32CubeMx项目配置
STM32CubeMX-多通道ADC-DMA-circular 传输
一,CubeMX生成工程1,配置ADC引脚2,时钟配置3,ADC配置4,打开中断5,DMA配置(这里选择 halfword 应该也可以,程序里面对应存储adc数据的变量也为halfword u16即可)6,中断配置红色标注为注意点,不清楚原理,ADC中断和DMZ的关系有待探明。7,生成代码二,添加代码数字标注处为添加部分/** ****************************************************************************** * File Name : main.c * Date : 12/07/2018 09:41:40 * Description
发表于 2022-07-18
STM32CubeMX-多通道ADC-DMA-circular 传输
第31章 STM32F429的SPI总线基础知识和HAL库API
31.1 初学者重要提示STM32H7的SPI支持4到32bit数据传输,而STM32F1和F4系列仅支持8bit或者16bit。STM3F429的主频168MHz时,SPI1、4、5、6最高通信时钟是42MHz,而SPI2和SPI3是21MHz。SPI总线的片选引脚SS在单一的主从器件配置下是可选的,一般情况下可以不使用。搜集了几篇质量比较高的SPI总线介绍帖:http://www.armbbs.cn/forum.php?mod=viewthread&tid=96788。31.2 SPI总线基础知识31.2.1 SPI总线的硬件框图认识一个外设,最好的方式就是看它的框图,方便我们快速的了解SPI的基本功能,然后再看手册了解细节。通
发表于 2022-04-06
第31章 STM32F429的<font color='red'>SPI总线</font>基础知识和HAL库API

推荐帖子

请教高手 wdm中,什么是重入?或者说什么情况导致重入?
请教高手wdm中,什么是重入?或者说什么情况导致重入?请教高手wdm中,什么是重入?或者说什么情况导致重入?
lg7412374123 嵌入式系统
STOP的器件应该怎么焊啊?
STOP的器件应该怎么焊啊? 有没有高手出来讲讲, 或都有没有什么好的视频看看STOP的器件应该怎么焊啊?
安_然 模拟电子
散粉了。。。。。。。。。。。。
大家好,我的笔记本昨天关机之后再重新启动就黑屏了,出现bos的命令,不知道这个是怎么回事,最近机子温度挺高的,不过要是不玩游戏就正常温度,昨天下载了一个驱动人生安装上了,然后下载了一个360安装上了,之后重启就不行了,安全模式都进不去了。。。。。。。各位大侠帮帮忙讨论一下是怎么回事呢?散粉了。。。。。。。。。。。。
zhaonash 嵌入式系统
TVS管阵列厂家
TVS管阵列有哪些厂家做得比较好?TVS管阵列厂家
bluestar09 综合技术交流
S6SAE101A00SA1002 PSOC BLE GPIO测试
打开EH_Motherboard.cyprj工程拖动右边PortsandPins下的DigtalBidirectional到左边区域 打开开发板原理图C:\ProgramFiles(x86)\Cypress\Solar-PoweredIoTDeviceKit\1.0\Hardware\EHMotherboard\EHMotherboard
littleshrimp 单片机
IQmath中IQNatan2PU中公式理解
如图所示,想请问一下,cos(PI/5)X2^29=0X19E37FA8, 以及sin(PI/5)x2^29=0X12CF17EF这些十六进制数十怎么得出来的 Accuracy=20log2(1x2^29)-20log2(6)=27bits这个精度是怎么算出来的 非常感谢! IQmath中IQNatan2PU中公式理解
bingLVyu 微控制器 MCU
小广播
实战 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved