第二十四章 AT32F403A基于V2库 spi读取spi flash w25q128

目录

概述

硬件

SPI

初始化    

初始化代码

测试

最后


概述

         本文主要是使用AT32F403A开发板,基于V2库实现spi 读取w25q128的功能。

         串口工具使用的Atlink-ez自带的串口功能。

         工程建立、调试工具配置在前面章节有详细介绍。


硬件

        硬件方面使用的是参考官方AT32F437 SURF板子而设计的一个AT32F403A开发板,板子上的芯片是AT32F403AVGT7的型号,开发板上面还板载了一个atlink-ez的仿真器,atlink-ez除了可以在线仿真和下载之外还有一个串口的功能,硬件上是通过跳线帽接到了MCU的串口1,pa9/10上面。

         如下图是开发板pcb图,以及硬件资源。(左边上角的就是atlink-ez,用usb线接到pc即可):


        实物如下图:

        本章是使用spi1读取w25q128的flash,相关原理图如下:


SPI

         SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,具体的SPI里就不说明,网上有很多的详细讲解的。

         AT32F403A多达4个SPI接口,在从或主模式下,全双工和半双工的通信速率可达50兆位/秒。3位的预分频器可 产生8种主模式频率,可配置成每帧8位或16位。


初始化    

         SPI的结构体参数:

         typedef struct

{

  spi_transmission_mode_type             transmission_mode;     /*!< transmission mode selection */

  spi_master_slave_mode_type             master_slave_mode;     /*!< master or slave mode selection */

  spi_mclk_freq_div_type                 mclk_freq_division;    /*!< master clock frequency division selection */

  spi_first_bit_type                     first_bit_transmission;/*!< transmit lsb or msb selection */

  spi_frame_bit_num_type                 frame_bit_num;         /*!< frame bit num 8 or 16 bit selection */

  spi_clock_polarity_type                clock_polarity;        /*!< clock polarity selection */

  spi_clock_phase_type                   clock_phase;           /*!< clock phase selection */

  spi_cs_mode_type                       cs_mode_selection;     /*!< hardware or software cs mode selection */

} spi_init_type;

         transmission_mode:传输模式,全双工,半双工

         master_slave_mode:主从模式

         mclk_freq_division:分频系数

         first_bit_transmission:大小端模式,高位在前还是在后

         frame_bit_num:数据帧位数,8bit/16bit

         clock_polarity:时钟空闲电平

         clock_phase:时钟采样

         cs_mode_selection:cs模式,硬件模式/软件模式

        AT32F403A的spi时钟最高是50M,所以分频也要注意,具体的时钟是spi所挂载的总线的时钟除以分频系数,当需要高的时钟的时候,对pcb要求布线也比较高,一般调试都是把时钟降低。Cs模式,一般常用的是软件cs模式,软件cs模式下可以任意设置一个IO来作为cs,只是需要手动的来拉高和拉低cs。其他的参数一般芯片的驱动都会给出参考。

         本文是通过spi1来对w25q128的读取和写入数据, w25q128是一颗16MB大小的spi falsh存储芯片,每页大小为4k字节,驱动部分从AT32F403A的BSP里面获取。

        Spi使用的软件的cs模式,所以配置PA15为推挽输出模式,在驱动中需要进行通讯的时候,拉低PA15,通讯完后拉高PA15即可,因为spi是cs低有效。当设置软件cs的时候,可以任意定义一个IO来做cs,不局限于PA15。

        PA15,PB3,PB4,PB5是spi1的重映射IO,所以软件上需要设置spi1的重映射。

        如下图宏定义:

        当需要改其他的spi时需要对应的修改上面的宏定义,IO口、时钟等,还需要dma时,还需要修改dma通道。   

初始化代码

void spiflash_init(void)
{
	gpio_init_type gpio_initstructure;
	spi_init_type spi_init_struct;

	crm_periph_clock_enable(SPI_CS_GPIO_GROUP_CLK, TRUE);						//开启spi cs gpio时钟
	crm_periph_clock_enable(SPI_CLK_GPIO_GROUP_CLK, TRUE);						//开启spi clk gpio时钟
	crm_periph_clock_enable(SPI_MISO_GPIO_GROUP_CLK, TRUE);						//开启spi iso gpio时钟
	crm_periph_clock_enable(SPI_MOSI_GPIO_GROUP_CLK, TRUE);						//开启spi osi gpio时钟
	
	crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);						//开启复用时钟
	gpio_pin_remap_config(SWJTAG_MUX_010,TRUE);									//关闭掉jtag,保留swd
	gpio_pin_remap_config(SPI1_MUX_01,TRUE);									//spi io复用到pa15,pb3,pb4,pb5
	
#if defined(SPI_TRANS_DMA)	

	crm_periph_clock_enable(DMA_PERIPH_CLK, TRUE);						//开启dma时钟

#endif
	/* software cs, pb12 as a general io to control flash cs */			//spi cs 脚配置,软件模式,配置为上拉推挽输出
	gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;		//推挽模式	
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;				//上拉
	gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;			//输出
	gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_initstructure.gpio_pins           = SPI_CS_PIN;				//cs pin
	gpio_init(SPI_CS_GPIO_GROUP, &gpio_initstructure);

	/* sck */
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;				//上拉
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;				//复用推挽
	gpio_initstructure.gpio_pins           = SPI_CLK_PIN;				//clk pin
	gpio_init(SPI_CLK_GPIO_GROUP, &gpio_initstructure);

	/* miso */
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;				//上拉
	gpio_initstructure.gpio_mode           = GPIO_MODE_INPUT;			//输入模式,配置为复用推挽也行,但是设置为输入比较规范些。
	gpio_initstructure.gpio_pins           = SPI_MISO_PIN;				//iso pin
	gpio_init(SPI_MISO_GPIO_GROUP, &gpio_initstructure);

	/* mosi */
	gpio_initstructure.gpio_pull           = GPIO_PULL_UP;				//上拉
	gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;				//复用推挽
	gpio_initstructure.gpio_pins           = SPI_MOSI_PIN;				//osi pin
	gpio_init(SPI_MOSI_GPIO_GROUP, &gpio_initstructure);

	FLASH_CS_HIGH();
	crm_periph_clock_enable(SPI_PERIPH_CLK, TRUE);						//开启spi时钟
	spi_default_para_init(&spi_init_struct);
	spi_init_struct.transmission_mode = SPI_TRANSMIT_FULL_DUPLEX;		//全双工模式
	spi_init_struct.master_slave_mode = SPI_MODE_MASTER;				//主模式
	spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_8;				//时钟8分频,120M/8=15M
	spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;			//大小端,高位在前
	spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;						//数据为8bit模式
	spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;			//配置 SPI 时钟空闲时为高电平
	spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;				//配置 SPI 在第二个时钟边沿采样
	spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;			//软件cs模式
	spi_init(SPIX, &spi_init_struct);									//spi结构体参数设置为以上参数
	spi_enable(SPIX, TRUE);												//使能spi
}

测试

        测试代码

        通过写入一段数据后,再读出来进行对比。

       

         测试结果

         对比数据成功通过,测试ok。

最后

         有问题的可以加QQ群技术交流,同时相关代码上传到QQ群中。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用STM32F427 HAL进行SPI3读写W25Q32的基本步骤: 1. 配置SPI3 ```c hspi3.Instance = SPI3; hspi3.Init.Mode = SPI_MODE_MASTER; hspi3.Init.Direction = SPI_DIRECTION_2LINES; hspi3.Init.DataSize = SPI_DATASIZE_8BIT; hspi3.Init.CLKPolarity = SPI_POLARITY_LOW; hspi3.Init.CLKPhase = SPI_PHASE_1EDGE; hspi3.Init.NSS = SPI_NSS_SOFT; hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi3.Init.TIMode = SPI_TIMODE_DISABLE; hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi3.Init.CRCPolynomial = 10; HAL_SPI_Init(&hspi3); ``` 2. 配置GPIO引脚 ```c GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); ``` 3. 读取ID ```c uint8_t rxData[2]; uint8_t txData[2]; txData[0] = 0x9F; // 发送读取ID命令 txData[1] = 0x00; HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_RESET); // 使能W25Q32 HAL_SPI_TransmitReceive(&hspi3, txData, rxData, 2, 100); // 发送命令并接收数据 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_SET); // 禁用W25Q32 ``` 4. 读取数据 ```c uint8_t rxData[256]; uint8_t txData[256]; txData[0] = 0x03; // 发送读取数据命令 txData[1] = 0x00; txData[2] = 0x00; txData[3] = 0x00; HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_RESET); // 使能W25Q32 HAL_SPI_Transmit(&hspi3, txData, 4, 1000); // 发送命令 HAL_SPI_Receive(&hspi3, rxData, 256, 1000); // 接收数据 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_SET); // 禁用W25Q32 ``` 5. 写入数据 ```c uint8_t txData[256]; txData[0] = 0x06; // 发送写使能命令 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_RESET); // 使能W25Q32 HAL_SPI_Transmit(&hspi3, txData, 1, 1000); // 发送命令 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_SET); // 禁用W25Q32 txData[0] = 0x02; // 发送写数据命令 txData[1] = 0x00; txData[2] = 0x00; txData[3] = 0x00; for (int i = 0; i < 256; i++) { txData[4 + i] = i; // 写入数据 } HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_RESET); // 使能W25Q32 HAL_SPI_Transmit(&hspi3, txData, 260, 1000); // 发送命令和数据 HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, GPIO_PIN_SET); // 禁用W25Q32 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值