/** ****************************************************************************** * File Name : SPI.c * Description : This file provides code for the configuration * of the SPI instances. ****************************************************************************** * This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * * Copyright (c) 2019 STMicroelectronics International N.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted, provided that the following conditions are met: * * 1. Redistribution of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of other * contributors to this software may be used to endorse or promote products * derived from this software without specific written permission. * 4. This software, including modifications and/or derivative works of this * software, must execute solely and exclusively on microcontroller or * microprocessor devices manufactured by or for STMicroelectronics. * 5. Redistribution and use of this software other than as permitted under * this license is void and will automatically terminate your rights under * this license. * * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "spi.h" /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ SPI_HandleTypeDef hspi4; /* SPI4 init function */ void MX_SPI4_Init(void) { hspi4.Instance = SPI4; hspi4.Init.Mode = SPI_MODE_MASTER;//主模式 hspi4.Init.Direction = SPI_DIRECTION_2LINES;//全双工 hspi4.Init.DataSize = SPI_DATASIZE_8BIT;//数据位为8位 hspi4.Init.CLKPolarity = SPI_POLARITY_LOW;//CPOL=0,low hspi4.Init.CLKPhase = SPI_PHASE_1EDGE;//CPHA为数据线的第一个变化沿 hspi4.Init.NSS = SPI_NSS_SOFT;//软件控制NSS hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;//256分频,54M/256=Hz hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB;//最高位先发送 hspi4.Init.TIMode = SPI_TIMODE_DISABLE;//TIMODE模式关闭 hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;//CRC关闭 hspi4.Init.CRCPolynomial = 7;//CRC值计算的多项式 hspi4.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi4.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; if (HAL_SPI_Init(&hspi4) != HAL_OK) { Error_Handler(); } } void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(spiHandle->Instance==SPI2) { /* USER CODE BEGIN SPI2_MspInit 0 */ __HAL_RCC_SPI2_CLK_ENABLE();//使能SPI4时钟 #if 0 extern void HAL_SPI_MspInit_flash(void); HAL_SPI_MspInit_flash(); #elif 1 extern void HAL_SPI_MspInit_w25qxx(SPI_HandleTypeDef *hspi); HAL_SPI_MspInit_w25qxx(spiHandle); #else extern void HAL_SPI_MspInit_SDCARD(SPI_HandleTypeDef *hspi); HAL_SPI_MspInit_SDCARD(spiHandle); #endif /* USER CODE BEGIN SPI2_MspInit 1 */ /* USER CODE END SPI2_MspInit 1 */ } if(spiHandle->Instance==SPI4) { /* USER CODE BEGIN SPI4_MspInit 0 */ /* USER CODE END SPI4_MspInit 0 */ /* SPI4 clock enable */ __HAL_RCC_SPI4_CLK_ENABLE();//使能SPI4时钟 __HAL_RCC_GPIOE_CLK_ENABLE(); /**SPI4 GPIO Configuration PE12 ------> SPI4_SCK PE13 ------> SPI4_MISO PE14 ------> SPI4_MOSI */ GPIO_InitStruct.Pin = SPI4_FM25_SCK_Pin|SPI4_FM25_MISO_Pin|SPI4_FM25_MOSI_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;//复用推挽输出 GPIO_InitStruct.Pull = GPIO_PULLUP;//上拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;//快速 GPIO_InitStruct.Alternate = GPIO_AF5_SPI4; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);//配置SPI的数据线和时钟线 /* USER CODE BEGIN SPI4_MspInit 1 */ /* USER CODE END SPI4_MspInit 1 */ } } void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle) { if(spiHandle->Instance==SPI2) { /* USER CODE BEGIN SPI2_MspDeInit 0 */ /* USER CODE END SPI2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI2_CLK_DISABLE(); /**SPI2 GPIO Configuration PB12 ------> SPI2_NSS PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO PB15 ------> SPI2_MOSI */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15); /* SPI2 interrupt DeInit */ HAL_NVIC_DisableIRQ(SPI2_IRQn); /* USER CODE BEGIN SPI2_MspDeInit 1 */ /* USER CODE END SPI2_MspDeInit 1 */ } if(spiHandle->Instance==SPI4) { /* USER CODE BEGIN SPI4_MspDeInit 0 */ /* USER CODE END SPI4_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI4_CLK_DISABLE(); /**SPI4 GPIO Configuration PE12 ------> SPI4_SCK PE13 ------> SPI4_MISO PE14 ------> SPI4_MOSI */ HAL_GPIO_DeInit(GPIOE, SPI4_FM25_SCK_Pin|SPI4_FM25_MISO_Pin|SPI4_FM25_MOSI_Pin); /* USER CODE BEGIN SPI4_MspDeInit 1 */ /* USER CODE END SPI4_MspDeInit 1 */ } } /* USER CODE BEGIN 1 */ //SPI4 读写一个字节 //TxData:要写入的字节 //返回值:读取到的字节 uint8_t SPI4_ReadWriteByte(uint8_t TxData) { uint8_t Rxdata; HAL_SPI_TransmitReceive(&hspi4,&TxData,&Rxdata,1, 1000); return Rxdata; //返回收到的数据 } void FM25L16B_Init(void) { FM_CS_1; MX_SPI4_Init(); } /**************************************************** ****函数名称:void FM25L16B_WriteByte(uint16_t addr,uint8_t data) ****函数作用:向指定地址写入一个字节数据 ****输入参数:addr,指定地址 data 要写入的数据 ****输出参数: ****************************************************/ void FM25L16B_WriteByte(uint16_t addr,uint8_t data) { uint8_t addr_h,addr_l; addr_h=addr>>8; addr_l=addr&0xff; FM_CS_0; SPI4_ReadWriteByte(FM_WREN); //写使能命令 FM_CS_1; FM_CS_0; SPI4_ReadWriteByte(FM_WRITE); //写数据命令 SPI4_ReadWriteByte(addr_h); //起始地址高8位 SPI4_ReadWriteByte(addr_l); //起始地址低8位 SPI4_ReadWriteByte(data); FM_CS_1; } /**************************************************** ****函数名称:uint8_t FM25L16B_ReadByte(uint16_t addr) ****函数作用:读取指定地址的一个字节数据 ****输入参数:addr 要读取的地址 ****输出返回:当前地址数据值 ****添加说明:没写入的地址数据默认是0x00. ****************************************************/ uint8_t FM25L16B_ReadByte(uint16_t addr) { uint8_t addr_h,addr_l; uint8_t data=0; addr_h=addr>>8; addr_l=addr&0xff; FM_CS_0; SPI4_ReadWriteByte(FM_READ); //读数据命令 SPI4_ReadWriteByte(addr_h); //起始地址高8位 SPI4_ReadWriteByte(addr_l); //起始地址低8位 data=SPI4_ReadWriteByte(0xff); FM_CS_1; return data; } /**************************************************** ****函数名称:uint8_t FM25L16B_ReadStatus(void) ****函数作用:读取状态寄存器 ****输入参数: ****输出参数:状态寄存器值 ****************************************************/ uint8_t FM25L16B_ReadStatus(void) { uint8_t data=0; FM_CS_0; SPI4_ReadWriteByte(FM_RDSR); //读状态寄存器命令 data=SPI4_ReadWriteByte(0xff); FM_CS_1; return data; } /**************************************************** ****函数名称:void FM25L16B_WriteStatus(uint8_t data) ****函数作用:写状态寄存器 ****输入参数:要写入的数据 ****输出参数: ****************************************************/ void FM25L16B_WriteStatus(uint8_t data) { FM_CS_0; SPI4_ReadWriteByte(FM_WREN); //写使能命令 FM_CS_1; FM_CS_0; SPI4_ReadWriteByte(FM_WRSR); //写状态寄存器命令 SPI4_ReadWriteByte(data); //起始地址高8位 FM_CS_1; } /**************************************************** ****函数名称:void FM25L16B_Write_N_Bytes(uint16_t addr,uint8_t *data,uint16_t num) ****函数作用:写数据到指定地址 ****输入参数:addr 起始地址;data 要写入的数据;num 数据长度 ****输出参数: ****************************************************/ void FM25L16B_Write_N_Bytes(uint16_t addr,uint8_t *data,uint16_t num) { uint16_t i=0; FM_CS_0; SPI4_ReadWriteByte(FM_WREN); //写使能命令 FM_CS_1; FM_CS_0; SPI4_ReadWriteByte(FM_WRITE); //写数据命令 SPI4_ReadWriteByte(addr>>8); //起始地址高8位 SPI4_ReadWriteByte(addr&0xff); //起始地址低8位 for(i=0;i>8); //起始地址高8位 SPI4_ReadWriteByte(addr&0xff); //起始地址低8位 for(i=0;i