STM32驱动SPI接口FLASH
stm32 SPI 接口

stm32 SPI 接口1、SPI 简介SPI 是英语Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接口。
是Motorola 首先在其MC68HCXX 系列处理器上定义的。
SPI 接口主要应用在EEPROM,FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信号解码器之间。
SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB 的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,STM32 也有SPI 接口。
SPI 接口一般使用4 条线:MISO 主设备数据输入,从设备数据输出。
MOSI 主设备数据输出,从设备数据输入。
SCLK 时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。
SPI 主要特点有:可以同时发出和接收串行数据;可以当作主机或从机工作;提供频率可编程时钟;发送结束中断标志;写冲突保护;总线竞争保护等。
SPI 总线四种工作方式SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。
如果CPOL=0,串行同步时钟的空闲状态为低电平;如果CPOL=1,串行同步时钟的空闲状态为高电平。
时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。
如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。
SPI 主模块和与之通信的外设备时钟相位和极性应该一致。
从选择(NSS)脚管理有2 种NSS 模式:图211●软件NSS 模式:可以通过设置SPI_CR1 寄存器的SSM 位来使能这种模式(见)。
在这种模式下NSS 引脚可以用作它用,而内部NSS 信号电平可以通过写SPI_CR1 的SSI 位来驱动●硬件NSS 模式,分两种情况:─NSS 输出被使。
【STM32】如何将资源烧写至外部flash,如spi-flash

【STM32】如何将资源烧写⾄外部flash,如spi-flashSTM32将资源烧写⾄外部flash⽅式⼤致分为通过IDE与应⽤程序⼀起和通过CubeProgranmmer单独烧写两种:⽅式⼀、使⽤IDE加载烧写算法,烧录应⽤程序时⼀并写⼊,具体就是修改分散加载链接脚本将部分常量数据移⾄外部flash,烧写算法制作⼯程如下主要实现两个⽂件,接⼝实现⽂件 <FLashPrg.c> 和设备描述⽂件 <FLashPrg.c>FLashPrg.c1/**************************************************************************//**2 * @file FlashDev.c3 * @brief Flash Device Description for New Device Flash4 * @version V1.0.05 * @date 10. January 20186 ******************************************************************************/7/*8 * Copyright (c) 2010-2018 Arm Limited. All rights reserved.9 *10 * SPDX-License-Identifier: Apache-2.011 *12 * Licensed under the Apache License, Version 2.0 (the License); you may13 * not use this file except in compliance with the License.14 * You may obtain a copy of the License at15 *16 * /licenses/LICENSE-2.017 *18 * Unless required by applicable law or agreed to in writing, software19 * distributed under the License is distributed on an AS IS BASIS, WITHOUT20 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.21 * See the License for the specific language governing permissions and22 * limitations under the License.23*/2425 #include "..\FlashOS.H"// FlashOS Structures262728struct FlashDevice const FlashDevice = {29 FLASH_DRV_VERS, // Driver Version, do not modify!30"STM32F429_W25Q128", // Device Name31 EXTSPI, // Device Type320x90000000, // Device Start Address330x01000000, // Device Size in Bytes (256kB)34256, // Programming Page Size350, // Reserved, must be 0360xFF, // Initial Content of Erased Memory37100, // Program Page Timeout 100 mSec383000, // Erase Sector Timeout 3000 mSec3940// Specify Size and Address of Sectors410x001000, 0x000000, // Sector Size 8kB (8 Sectors)42// 0x010000, 0x010000, // Sector Size 64kB (2 Sectors)43// 0x002000, 0x030000, // Sector Size 8kB (8 Sectors)44 SECTOR_END45 };FLashPrg.c1/**************************************************************************//**2 * @file FlashPrg.c3 * @brief Flash Programming Functions adapted for New Device Flash4 * @version V1.0.05 * @date 10. January 20186 ******************************************************************************/7/*8 * Copyright (c) 2010-2018 Arm Limited. All rights reserved.9 *10 * SPDX-License-Identifier: Apache-2.011 *12 * Licensed under the Apache License, Version 2.0 (the License); you may13 * not use this file except in compliance with the License.14 * You may obtain a copy of the License at15 *16 * /licenses/LICENSE-2.017 *18 * Unless required by applicable law or agreed to in writing, software19 * distributed under the License is distributed on an AS IS BASIS, WITHOUT20 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.21 * See the License for the specific language governing permissions and22 * limitations under the License.23*/2425 #include "..\FlashOS.H"// FlashOS Structures26 #include ".\flash\bsp_spi_flash.h"272829#define PAGE_SIZE SPI_FLASH_PageSize303132 uint8_t auxBuf[PAGE_SIZE];33 uint32_t baseAddr;3435/*36 Mandatory Flash Programming Functions (Called by FlashOS):37 int Init (unsigned long adr, // Initialize Flash38 unsigned long clk,39 unsigned long fnc);40 int UnInit (unsigned long fnc); // De-initialize Flash41 int EraseSector (unsigned long adr); // Erase Sector Function42 int ProgramPage (unsigned long adr, // Program Page Function43 unsigned long sz,44 unsigned char *buf);4546 Optional Flash Programming Functions (Called by FlashOS):47 int BlankCheck (unsigned long adr, // Blank Check48 unsigned long sz,49 unsigned char pat);50 int EraseChip (void); // Erase complete Device51 unsigned long Verify (unsigned long adr, // Verify Function52 unsigned long sz,53 unsigned char *buf);5455 - BlanckCheck is necessary if Flash space is not mapped into CPU memory space56 - Verify is necessary if Flash space is not mapped into CPU memory space57 - if EraseChip is not provided than EraseSector for all sectors is called58*/596061/*62 * Initialize Flash Programming Functions63 * Parameter: adr: Device Base Address64 * clk: Clock Frequency (Hz)65 * fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)66 * Return Value: 0 - OK, 1 - Failed67*/6869int Init (unsigned long adr, unsigned long clk, unsigned long fnc)70 {71/* Add your Code */72 baseAddr = adr;73 SPI_FLASH_Init();74return (0); // Finished without Errors75 }767778/*79 * De-Initialize Flash Programming Functions80 * Parameter: fnc: Function Code (1 - Erase, 2 - Program, 3 - Verify)81 * Return Value: 0 - OK, 1 - Failed82*/8384int UnInit (unsigned long fnc)85 {86/* Add your Code */87return (0); // Finished without Errors88 }899091/*92 * Erase complete Flash Memory93 * Return Value: 0 - OK, 1 - Failed94*/9596int EraseChip (void)97 {98/* Add your Code */99 SPI_FLASH_BulkErase();100return (0); // Finished without Errors101 }102103104/*105 * Erase Sector in Flash Memory106 * Parameter: adr: Sector Address107 * Return Value: 0 - OK, 1 - Failed108*/109110int EraseSector (unsigned long adr)111 {112/* Add your Code */113 SPI_FLASH_SectorErase(adr - baseAddr);114return (0); // Finished without Errors115 }116117118/*119 * Program Page in Flash Memory120 * Parameter: adr: Page Start Address121 * sz: Page Size122 * buf: Page Data123 * Return Value: 0 - OK, 1 - Failed124*/125126int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf)127 {128/* Add your Code */129 SPI_FLASH_PageWrite(buf, adr - baseAddr, sz);130return (0); // Finished without Errors131 }132133/*134 * Verify Flash Contents135 * Parameter: adr: Start Address136 * sz: Size (in bytes)137 * buf: Data138 * Return Value: (adr+sz) - OK, Failed Address139*/140141/*142 Verify function is obsolete because all other function leave143 the SPIFI in memory mode so a memory compare could be used.144*/145 unsigned long Verify (unsigned long adr, unsigned long sz, unsigned char *buf)146 {147int i;148 SPI_FLASH_BufferRead(auxBuf, adr - baseAddr, sz);149for (i = 0; i < PAGE_SIZE; i++) {150if (auxBuf[i] != buf[i]) {151return (adr + i); // Verification Failed (return address)152 }153 }154return (adr + sz); // Done successfully155 }修改好适配⾃⼰的硬件接⼝,编译会⽣成 .FLM格式的烧写算法⽂件,实际是通过如下命令⽣成的⽤法:烧写程序时选择刚才⽣成的算法⽂件即可⽅式⼆、使⽤编程⼯具STM32CubeProgrammer,将数据直接烧写⾄外部flash,烧写算法制作⼯程如下主要实现两个⽂件,接⼝实现⽂件 <Loader_Src.c> 和设备描述⽂件 <Dev_Inf.c>Dev_Inf.c1 #include "Dev_Inf.h"23/* This structure containes information used by ST-LINK Utility to program and erase the device */4#if defined (__ICCARM__)5 __root struct StorageInfo const StorageInfo = {6#else7struct StorageInfo const StorageInfo = {8#endif9"M25P64_STM3210E-EVAL", // Device Name + version number10 SPI_FLASH, // Device Type110x00000000, // Device Start Address120x00800000, // Device Size in Bytes (8MBytes/64Mbits)130x00000100, // Programming Page Size 16Bytes140xFF, // Initial Content of Erased Memory15// Specify Size and Address of Sectors (view example below)160x00000080, 0x00010000, // Sector Num : 128 ,Sector Size: 64KBytes170x00000000, 0x00000000,18 };1920/* Sector coding example21 A device with succives 16 Sectors of 1KBytes, 128 Sectors of 16 KBytes,22 8 Sectors of 2KBytes and 16384 Sectors of 8KBytes2324 0x00000010, 0x00000400, // 16 Sectors of 1KBytes25 0x00000080, 0x00004000, // 128 Sectors of 16 KBytes26 0x00000008, 0x00000800, // 8 Sectors of 2KBytes27 0x00004000, 0x00002000, // 16384 Sectors of 8KBytes28 0x00000000, 0x00000000, // end29*/Loader_Src.c1 #include "stm32f10x.h"2 #include "stm32_eval_spi_flash.h"3 #include "stm3210e_eval.h"456/**7 * Description :8 * Initilize the MCU Clock, the GPIO Pins corresponding to the9 * device and initilize the FSMC with the chosen configuration10 * Inputs :11 * None12 * outputs :13 * R0 : "1" : Operation succeeded14 * "0" : Operation failure15 * Note: Mandatory for all types of device16*/17int Init (void)18 {19 SystemInit();20 sFLASH_Init();21return1;22 }232425/**26 * Description :27 * Read data from the device28 * Inputs :29 * Address : Write location30 * Size : Length in bytes31 * buffer : Address where to get the data to write32 * outputs :33 * R0 : "1" : Operation succeeded34 * "0" : Operation failure35 * Note: Mandatory for all types except SRAM and PSRAM36*/37int Read (uint32_t Address, uint32_t Size, uint8_t* buffer)38 {39 sFLASH_ReadBuffer(buffer, Address, Size);40return1;41 }424344/**45 * Description :46 * Write data from the device47 * Inputs :48 * Address : Write location49 * Size : Length in bytes50 * buffer : Address where to get the data to write51 * outputs :52 * R0 : "1" : Operation succeeded53 * "0" : Operation failure54 * Note: Mandatory for all types except SRAM and PSRAM55*/56int Write (uint32_t Address, uint32_t Size, uint8_t* buffer)57 {58 sFLASH_WriteBuffer(buffer, Address, Size);59return1;60 }616263/**64 * Description :65 * Erase a full sector in the device66 * Inputs :67 * None68 * outputs :69 * R0 : "1" : Operation succeeded70 * "0" : Operation failure71 * Note: Not Mandatory for SRAM PSRAM and NOR_FLASH72*/73int MassErase (void)74 {75 sFLASH_EraseBulk();76return1;77 }7879/**80 * Description :81 * Erase a full sector in the device82 * Inputs :83 * SectrorAddress : Start of sector84 * Size : Size (in WORD)85 * InitVal : Initial CRC value86 * outputs :87 * R0 : "1" : Operation succeeded88 * "0" : Operation failure89 * Note: Not Mandatory for SRAM PSRAM and NOR_FLASH90*/91int SectorErase (uint32_t EraseStartAddress, uint32_t EraseEndAddress)92 {93 EraseStartAddress = EraseStartAddress - EraseStartAddress % 0x10000; 9495while (EraseEndAddress >= EraseStartAddress) {96 sFLASH_EraseSector(EraseStartAddress);97 EraseStartAddress += 0x10000;98 }99100return1;101 }102103/**104 * Description :105 * Calculates checksum value of the memory zone106 * Inputs :107 * StartAddress : Flash start address108 * Size : Size (in WORD)109 * InitVal : Initial CRC value110 * outputs :111 * R0 : Checksum value112 * Note: Optional for all types of device113*/114 uint32_t CheckSum(uint32_t StartAddress, uint32_t Size, uint32_t InitVal)115 {116 uint8_t missalignementAddress = StartAddress % 4;117 uint8_t missalignementSize = Size ;118int cnt;119 uint32_t Val;120 uint8_t value;121122 StartAddress -= StartAddress % 4;123 Size += (Size % 4 == 0) ? 0 : 4 - (Size % 4);124125for(cnt = 0; cnt < Size ; cnt += 4) {126 sFLASH_ReadBuffer(&value, StartAddress, 1);127 Val = value;128 sFLASH_ReadBuffer(&value, StartAddress + 1, 1);129 Val += value << 8;130 sFLASH_ReadBuffer(&value, StartAddress + 2, 1);131 Val += value << 16;132 sFLASH_ReadBuffer(&value, StartAddress + 3, 1);133 Val += value << 24;134135if(missalignementAddress) {136switch (missalignementAddress) {137case1:138 InitVal += (uint8_t) (Val >> 8 & 0xff);139 InitVal += (uint8_t) (Val >> 16 & 0xff);140 InitVal += (uint8_t) (Val >> 24 & 0xff);141 missalignementAddress -= 1;142break;143144case2:145 InitVal += (uint8_t) (Val >> 16 & 0xff);146 InitVal += (uint8_t) (Val >> 24 & 0xff);147 missalignementAddress -= 2;148break;149150case3:151 InitVal += (uint8_t) (Val >> 24 & 0xff);152 missalignementAddress -= 3;153break;154 }155 } else if((Size - missalignementSize) % 4 && (Size - cnt) <= 4) {156switch (Size - missalignementSize) {157case1:158 InitVal += (uint8_t) Val;159 InitVal += (uint8_t) (Val >> 8 & 0xff);160 InitVal += (uint8_t) (Val >> 16 & 0xff);161 missalignementSize -= 1;162break;163164case2:165 InitVal += (uint8_t) Val;166 InitVal += (uint8_t) (Val >> 8 & 0xff);167 missalignementSize -= 2;168break;169170case3:171 InitVal += (uint8_t) Val;172 missalignementSize -= 3;173break;174 }175 } else {176 InitVal += (uint8_t) Val;177 InitVal += (uint8_t) (Val >> 8 & 0xff);178 InitVal += (uint8_t) (Val >> 16 & 0xff);179 InitVal += (uint8_t) (Val >> 24 & 0xff);180 }181182 StartAddress += 4;183 }184185return (InitVal);186 }187188189/**190 * Description :191 * Verify flash memory with RAM buffer and calculates checksum value of192 * the programmed memory193 * Inputs :194 * FlashAddr : Flash address195 * RAMBufferAddr : RAM buffer address196 * Size : Size (in WORD)197 * InitVal : Initial CRC value198 * outputs :199 * R0 : Operation failed (address of failure)200 * R1 : Checksum value201 * Note: Optional for all types of device202*/203 uint64_t Verify (uint32_t MemoryAddr, uint32_t RAMBufferAddr, uint32_t Size, uint32_t missalignement) 204 {205 uint32_t InitVal = 0;206 uint32_t VerifiedData = 0;207 uint8_t TmpBuffer = 0x00;208 uint64_t checksum;209 Size *= 4;210211 checksum = CheckSum((uint32_t)MemoryAddr + (missalignement & 0xf), Size - ((missalignement >> 16) & 0xF), InitVal);212213while (Size > VerifiedData) {214 sFLASH_ReadBuffer(&TmpBuffer, MemoryAddr + VerifiedData, 1);215216if (TmpBuffer != *((uint8_t*)RAMBufferAddr + VerifiedData))217return ((checksum << 32) + MemoryAddr + VerifiedData);218219 VerifiedData++;220 }221222return (checksum << 32);223 }修改好适配⾃⼰的硬件接⼝,编译会⽣成 .stldr格式的烧写算法⽂件,实际是通过如下命令⽣成的⽤法:烧写程序时选择刚才⽣成的算法⽂件即可。
STM32的常用外设驱动程序的开发

设计研发2021.01STM32的常用外设驱动程序的开发沈镐哲(绍兴文理学院数理信息学院,浙江绍兴,312000)摘要:围绕不同应用场景的嵌入式芯片应用是国内外电子行业的研究热点,在人工智能、物联网、工业互联网等领域有着广泛的应用。
基于Cortex-M3内核的STM32微控制器由于其功能众多、易于应用、家族齐全,受到业界的广泛欢迎。
本文讨论了STM32常用外设驱动库的结构,并在实例基础上分析了驱动开发,可以作为初学者的参考。
关键字:STM32;Cortex-M;常用外设驱动开发;应用拓展Developme n t of comm o n peripheral drivers for STM32Shen Haozhe(Department of Physics and Electrical Engineering,Shaoxing College of Arts and Sciences,Shaoxing Zhejiang,312000)Abstract:Embedded chip application around different application scenarios is a research hotspot inthe electronics industry at home and abroad,and it has a wide range of applications in artificial intelligence,Internet of Things,industrial Internet and other fields.The STM32microcontroller based on Cortex-M3kernel is widely welcomed in the industry due to its numerous functions,easy application and complete family.This paper discusses the strueture of the common peripheral driver library of STM32,and analyzes the driver development on the basis of an example,which can be used asa reference for beginners.Keywords:STM32:Cortex-M;Commonperipherals drive development;Application development0引言科技发展日益迅猛,具有低成本、低功耗、高性能、可裁剪、功能多等优势ARM结构的STM32系列单片机成为市场主流的芯片。
spi_flash (stm32 spi_flash的编程)

本帖最后由orange-208 于2012-5-28 10:05 编辑void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite) SPI_FLASH_Write_SR(0x02);//使能状态寄存器中的写存储器SST25V_DBSY();SPI_FLASH_Write_SR(0x02);//使能状态寄存器中的写存储器 SST25V_DBSY();实验目的:将数据写入外部FLASH中,然后再读出来显示在LCD上实验平台:基于STM32F103C8T6的彩屏开发板FLASH:SST25VF016Bflash_SST.c#include "flash_SST.h"#include "spi.h"#include "delay.h"//4Kbytes为一个Sector//16个扇区为1个Block//SST25VF016B//容量为2M字节,共有32个Block(块),512个Sector(扇区)//初始化SPI FLASH的IO口//修改状态寄存器,允许芯片存储器被写void SPI_Flash_Init(void){RCC->APB2ENR|=1<<2; //PORTA时钟使能GPIOA->CRH&=0XFFFFFF0F;GPIOA->CRH|=0X00000030; //PA9 推挽GPIOA->ODR|=1<<9; //PA9上拉SPIx_Init(); //初始化SPISPI_FLASH_Write_SR(0x02); //使能状态寄存器中的写存储器SST25V_DBSY();}//读取SPI_FLASH的状态寄存器//BIT7 6 5 4 3 2 1 0//SPR RV TB BP2 BP1 BP0 WEL BUSY//SPR:默认0,状态寄存器保护位,配合WP使用//TB,BP2,BP1,BP0:FLASH区域写保护设置//WEL:写使能锁定//BUSY:忙标记位(1,忙;0,空闲)//默认:0x00u8 SPI_Flash_ReadSR(void){u8 byte=0;SPI_FLASH_CS=0; //使能器件SPIx_ReadWriteByte(SST25_ReadStatusReg); //发送读取状态寄存器命令byte=SPIx_ReadWriteByte(0Xff); //读取一个字节SPI_FLASH_CS=1; //取消片选return byte;}//写SPI_FLASH状态寄存器//只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!!void SPI_FLASH_Write_SR(u8 sr){SPI_FLASH_CS=0; //片选SPIx_ReadWriteByte(SST25_EnableWriteStatusReg); //使能写状态寄存器命令SPI_FLASH_CS=1; //取消片选SPI_FLASH_CS=0; //片选SPIx_ReadWriteByte(SST25_WriteStatusReg); //发送写取状态寄存器命令SPIx_ReadWriteByte(sr); //写入一个字节SPI_FLASH_CS=1; //取消片选}//SPI_FLASH写使能//将WEL置位void SPI_FLASH_Write_Enable(void){SPI_FLASH_CS=0; //使能器件SPIx_ReadWriteByte(SST25_WriteEnable); //发送写使能SPI_FLASH_CS=1; //取消片选}//SPI_FLASH写禁止//将WEL清零void SPI_FLASH_Write_Disable(void){SPI_FLASH_CS=0; //使能器件SPIx_ReadWriteByte(SST25_WriteDisable); //发送写禁止指令SPI_FLASH_CS=1; //取消片选}//读取芯片ID SST25VF016的是0XBF41u16 SPI_Flash_ReadID(void){u16 Temp = 0;SPI_FLASH_CS=0;//发送读取ID命令SPIx_ReadWriteByte(0x90);//发送24位的地址SPIx_ReadWriteByte(0x00);SPIx_ReadWriteByte(0x00);SPIx_ReadWriteByte(0x00);//读取返回的16位值Temp=SPIx_ReadWriteByte(0xFF)<<8; //高8位数据Temp+=SPIx_ReadWriteByte(0xFF); //底八位数据SPI_FLASH_CS=1;return Temp;}//读取SPI FLASH//在指定地址开始读取指定长度的数据//pBuffer:数据存储区//ReadAddr:开始读取的地址(24bit)//NumByteToRead:要读取的字节数(最大65535即64k)void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead) {u16 i;SPI_FLASH_CS=0; //使能器件SPIx_ReadWriteByte(SST25_ReadData); //发送读取命令//发送24bit地址SPIx_ReadWriteByte((u8)((ReadAddr)>>16));SPIx_ReadWriteByte((u8)((ReadAddr)>>8));SPIx_ReadWriteByte((u8)ReadAddr);for(i=0;i<NumByteToRead;i++){pBuffer=SPIx_ReadWriteByte(0XFF); //循环读数}SPI_FLASH_CS=1; //取消片选}//地址自动增加的写数据Avoid AutoAddressIncrement_WordProgramA(u8 Byte1, u8 Byte2, u32 Addr) {SPI_FLASH_Write_Enable();SPI_FLASH_CS=0;SPIx_ReadWriteByte(SST25_AAI_WordProgram);//输入所要写数据的起始地址SPIx_ReadWriteByte((Addr & 0xFF0000) >> 16);SPIx_ReadWriteByte((Addr & 0xFF00) >> 8);SPIx_ReadWriteByte(Addr & 0xFF); //发送最初的两个数据SPIx_ReadWriteByte(Byte1);SPIx_ReadWriteByte(Byte2);SPI_FLASH_CS=1;SPI_Flash_Wait_Busy();}//地址自动增加的写数据Bvoid AutoAddressIncrement_WordProgramB(u8 state,u8 Byte1, u8 Byte2){SPI_FLASH_Write_Enable();SPI_FLASH_CS=0;SPIx_ReadWriteByte(SST25_AAI_WordProgram);SPIx_ReadWriteByte(Byte1);SPIx_ReadWriteByte(Byte2);SPI_FLASH_CS=1;SPI_Flash_Wait_Busy();if(state==1){SPI_FLASH_Write_Disable();}SPI_Flash_Wait_Busy();}//结合AB构成的地址自动增加的连续数据的写入//具有先擦除待写区域的功能//pBuffer:为待写数据组//WriteAddr:所写数据的起始地址//NumByteToWrite:所要写的数据的长度void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite){u16 i,temp;u32 secpos;u16 secoff;u16 secremain;//以下代码为擦除待写区域的代码secpos=WriteAddr/4096; //扇区(4K)地址0~511 for SST25VF016secoff=WriteAddr@96; //在扇区内的偏移secremain=4096-secoff; //扇区剩余空间大小if(NumByteToWrite<secremain) //剩余空间大于所存数据{temp=1;}else //剩余空间小于所存数据{i=NumByteToWrite-secremain; //判断还占了几个扇区if(i%96==0)temp=i/4096+1;elsetemp=i/4096+2;}for(i=0;i<temp;i++){SPI_Flash_Erase_Sector((secpos+i)*4096); //擦除将要写入数据的扇区}//以下代码为将数据写入指定地址的代码if(NumByteToWrite%2==0){temp=NumByteToWrite/2-1;}else{temp=NumByteToWrite/2;}AutoAddressIncrement_WordProgramA(pBuffer[0], pBuffer[1],WriteAddr ); //开始写数据for(i=1;i<temp;i++){AutoAddressIncrement_WordProgramB(0,pBuffer[2*i], pBuffer[2*i+1]);}if(NumByteToWrite%2==0){AutoAddressIncrement_WordProgramB(1,pBuffer[NumByteToWrite-2], pBuffer[NumByteToWrite-1]); //结束写数据}else{AutoAddressIncrement_WordProgramB(1,pBuffer[NumByteToWrite-1],0); //结束写数据}//写入1Byte数据//pBuffer:待写的数据//WriteAddr:待写数据的地址void Flash_WriteByte(u8* pBuffer,u32 WriteAddr){u32 secpos;secpos=WriteAddr/4096; //扇区地址0~511 for w25x16 4096=4k SPI_Flash_Erase_Sector(secpos); //擦除这个扇区SPI_FLASH_Write_Enable(); //SET WELSPI_FLASH_CS=0; //使能器件SPIx_ReadWriteByte(SST25_ByteProgram ); //发送写页命令//发送24bit地址SPIx_ReadWriteByte((u8)((WriteAddr)>>16));SPIx_ReadWriteByte((u8)((WriteAddr)>>8));SPIx_ReadWriteByte((u8)WriteAddr); //发送待写的数据SPIx_ReadWriteByte(pBuffer[0]);SPI_FLASH_CS=1;SPI_Flash_Wait_Busy(); //等待写完成}//擦除整个芯片//整片擦除时间://W25X16:25s//W25X32:40s//W25X64:40s//等待时间超长...void SPI_Flash_Erase_Chip(void){SPI_FLASH_Write_Enable(); //SET WELSPI_Flash_Wait_Busy();SPI_FLASH_CS=0; //使能器件SPIx_ReadWriteByte(SST25_ChipErase); //发送片擦除命令SPI_FLASH_CS=1; //取消片选SPI_Flash_Wait_Busy(); //等待芯片擦除结束}//擦除一个扇区//Dst_Addr:扇区地址0~511 for w25x16//擦除一个山区的最少时间:150msvoid SPI_Flash_Erase_Sector(u32 Dst_Addr){SPI_FLASH_Write_Enable(); //SET WELSPI_Flash_Wait_Busy();SPI_FLASH_CS=0; //使能器件SPIx_ReadWriteByte(SST25_4KByte_BlockERASE); //发送扇区擦除指令SPIx_ReadWriteByte((u8)((Dst_Addr)>>16)); //发送24bit地址SPIx_ReadWriteByte((u8)((Dst_Addr)>>8));SPIx_ReadWriteByte((u8)Dst_Addr);SPI_FLASH_CS=1; //取消片选SPI_Flash_Wait_Busy(); //等待擦除完成}//等待空闲void SPI_Flash_Wait_Busy(void){while ((SPI_Flash_ReadSR()&0x01)==0x01); // 等待BUSY位清空}void SST25V_EBSY(void){SPI_FLASH_CS=0;SPIx_ReadWriteByte( SST25_EBSY);SPI_FLASH_CS=1;}void SST25V_DBSY(void){SPI_FLASH_CS=0;SPIx_ReadWriteByte( SST25_DBSY);SPI_FLASH_CS=1;}Flash.h#ifndef __FLASH_SST_H#define __FLASH_SST_H#include "sys.h"#define SPI_FLASH_CS PAout(9) //选中FLASH#define FLASH_ID 0XBF41 //SST25VF016读写//指令表#define SST25_ReadData 0x03#define SST25_FastReadData 0x0B#define SST25_4KByte_BlockERASE 0x20#define SST25_32KByte_BlockErase 0x52#define SST25_64KByte_BlockErase 0xD8#define SST25_ChipErase 0xC7#define SST25_ByteProgram 0x02#define SST25_AAI_WordProgram 0xAD#define SST25_ReadStatusReg 0x05#define SST25_EnableWriteStatusReg 0x50#define SST25_WriteStatusReg 0x01#define SST25_WriteEnable 0x06#define SST25_WriteDisable 0x04#define SST25_ManufactDeviceID 0x90#define SST25_JedecDeviceID 0x9F#define SST25_EBSY 0x70#define SST25_DBSY 0x80void SPI_Flash_Init(void);u16 SPI_Flash_ReadID(void); //读取FLASH IDu8 SPI_Flash_ReadSR(void); //读取状态寄存器void SPI_FLASH_Write_SR(u8 sr); //写状态寄存器void SPI_FLASH_Write_Enable(void); //写使能void SPI_FLASH_Write_Disable(void); //写保护void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead); //读取flashvoid SPI_Flash_Erase_Chip(void); //整片擦除void SPI_Flash_Erase_Sector(u32 Dst_Addr); //扇区擦除void SPI_Flash_Wait_Busy(void); //等待空闲void SST25V_EBSY(void);void SST25V_DBSY(void);void Flash_WriteByte(u8* pBuffer,u32 WriteAddr); //写入1Byte数据void AutoAddressIncrement_WordProgramA(u8 Byte1, u8 Byte2, u32 Addr); //地址自动增加的写数据Avoid AutoAddressIncrement_WordProgramB(u8 state,u8 Byte1, u8 Byte2); //地址自动增加的写数据Bvoid SPI_Flash_Write(u8 pBuffer[],u32 WriteAddr,u16 NumByteToWrite); //结合AB构成的地址自动增加的连续数据的写入#endifmain.c主函数:#include<stm32f10x_lib.h>#include"common.h"#include"TFTLCD.h"#include"spi.h"#include"key.h"#include"flash.h"const u8 TEXT_Buffer[]={"Chen An SST25VF"}; //待写入flash的数据#define SIZE sizeof(TEXT_Buffer) //计算待写入数据的长度int main(void){u8 key;u8 datatemp[SIZE]; //开辟空间用于存放从flash读回的数据Stm32_Clock_Init(9); //系统时钟初始化delay_init(72); //延时函数的初始化LCD_Init(); //LCD初始化KEY_Init(); //按键初始化SPI_Flash_Init(); //SPI关于flash的硬件接口初始化POINT_COLOR=RED; //设置字体颜色while(SPI_Flash_ReadID()!=FLASH_ID) //检验flash是否存在{LCD_ShowString(60,130,"SST25VF Check Failed!");delay_ms(500);}LCD_ShowString(60,130,"SST25VF Ready!");LCD_ShowString(60,150,"KEY1:Write KEY2:Read");POINT_COLOR=BLUE;while(1){key=KEY_Scan(); //按键扫描if(key==1) //按键1按下,开始写数据到flash{LCD_Fill(0,170,239,319,WHITE);LCD_ShowString(60,170,"Start Write SST25V");SPI_Flash_Write((u8*)TEXT_Buffer,1000,SIZE); //写数据LCD_ShowString(60,170,"SST25V Write Finished");}if(key==2) //按键2按下,开始从flash读回数据{LCD_ShowString(60,170,"Start Read SST25V");SPI_Flash_Read(datatemp,1000,SIZE); //读数据LCD_ShowString(60,170,"The Data Is");LCD_ShowString(60,190,datatemp);}}}总结:1.开始的时候,读取FLASH的ID成功,我觉得芯片一切正常,但是写入数据后读回来的全是“满屏”,纠结了一天才发现原来是FLASH没有进行初始化,没有写(SPI_FLASH_Write_SR(0x02);//使能状态寄存器中的写存储器 SST25V_DBSY() )这两句导致数据无法写入FLASH。
STM32-SPI

4月25日---- 4月27日SPI总线经过两天的学习,哈哈SPI终于搞定,用STM32控制IIC EEPORM,将EEPROM中的数据读到SPI的FLASH中。
---------------------------------------------------------------------------------------------------------------------- SPI(Serial Peripheral Interface)总线:串行外围总线接口一、SPI总线的简介:SPI是由摩托罗拉公司开发的全双工同步串行总线,没有总线仲裁机制,所以工作在单主机系统中。
主设备启动与从设备的同步通讯,从而完成数据的交换。
对于只能做从机的器件接口来说,SPI接口由SDI(串行数据输入),SDO(串行数据输出),SCK(串行移位时钟)和CS(从使能信号)。
通讯时,数据由SDO输出,SDI输入,数据在时钟的上升沿或者下降沿由SDO输出,在紧接着的下降沿或者上升沿由SDI读入,这样经过8/16帧,以完成8/16位数据的传输。
对于有的微控制器来说,它的硬件SPI即可做主机,也可以做从机,即可实现主从配置,MOSI:主出从入、MISO:主入从出、SCK:串行时钟、SS:从属选择。
(当做主机输出时,该信号用于选中需要访问的从机,SS输入高电平,外部决定其为主机;当做从机时,SS为输入或者一般的IO口使用)。
常用的SPI接法:在软件配置的条件下SS不使用。
1、SPI总线的通信时序(1)在SPI通信中,在全双工模式下,发送和接收是同事进行的(2)数据传输的时钟基来自主控制器的时钟脉冲;摩托罗拉没有定义任何通用的SPI 时钟的规范,最常用的时钟设置是基于时钟极性CPOL和时钟相位CPHA两个参数。
a)CPOL=0,表示时钟的空闲状态为低电平b)CPOL=1,表示时钟的空闲状态为高电平c)CPHA=0,表示同步始终的第一个边沿(上升或者下降)数据被采样d)CPHA=1,表示同步始终的第二个边沿(上升或者下降)数据被采样即CPOL和CPHA的设置决定了数据采样的时钟沿。
STM32----8----SPI(下)与FLASH通信

STM32----8----SPI(下)与FLASH通信文章发表于:2011-05-09 15:04[attach]150356[/attach]STM32----8----SPI(下)与FLASH通信----------------------------------------------------------------------------------------------------------------------------------------- 关于W25X16 SPI型FLASH的手册在附件中,这里主要是W25X16的驱动程序的书写,通过配合STM3 2主机的SPI模式,读写FLASHw25x16.h#ifndef __W25X16_H#define __W25X16_H#include "stm32f10x_lib.h"/****************************************************************************-W25X16的宏定义-片选信号CS-PA2的宏定义****************************************************************************/#define SPI_FLASH_CS_PORT GPIOA#define SPI_FLASH_CS_CLK RCC_APB2Periph_GPIOA#define SPI_FLASH_CS_PIN GPIO_Pin_2#define Set_SPI_FLASH_CS {GPIO_SetBits(SPI_FLASH_CS_PORT,SPI_FLASH_CS_PIN);}#define Clr_SPI_FLASH_CS {GPIO_ResetBits(SPI_FLASH_CS_PORT,SPI_FLASH_CS_PIN);}//W25X16读写#define FLASH_ID 0XEF14/*********************************************- W25X16的操作指令表,STM32通过向W25X16发送以下指令就可以对W25X16进行以下的操作*********************************************/#define W25X_WriteEnable 0x06#define W25X_WriteDisable 0x04#define W25X_ReadStatusReg 0x05#define W25X_WriteStatusReg 0x01#define W25X_ReadData 0x03#define W25X_FastReadData 0x0B#define W25X_FastReadDual 0x3B#define W25X_PageProgram 0x02#define W25X_BlockErase 0xD8#define W25X_SectorErase 0x20#define W25X_ChipErase 0xC7#define W25X_PowerDown 0xB9#define W25X_ReleasePowerDown 0xAB#define W25X_DeviceID 0xAB#define W25X_ManufactDeviceID 0x90#define W25X_JedecDeviceID 0x9F/*********************************************- STM32操作W25X16的操作函数*********************************************/void SPI_Flash_Init(void);u16 SPI_Flash_ReadID(void); //读取FLASH IDu8 SPI_Flash_ReadSR(void); //读取状态寄存器void SPI_FLASH_Write_SR(u8 sr); //写状态寄存器void SPI_FLASH_Write_Enable(void); //写使能void SPI_FLASH_Write_Disable(void); //写保护void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead); //读取flash void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite);//写入flash void SPI_Flash_Erase_Chip(void); //整片擦除void SPI_Flash_Erase_Sector(u32 Dst_Addr);//扇区擦除void SPI_Flash_Wait_Busy(void); //等待空闲void SPI_Flash_PowerDown(void); //进入掉电模式void SPI_Flash_WAKEUP(void); //唤醒#endifw25x16.c#include "w25x16.h"#include "spi.h"#include "delay.h"/*************************************************************************** - 功能描述:w25x16 Flash的初始化函数- 隶属模块:w25x16 Flash操作- 函数属性:外部,使用户使用- 参数说明:无- 返回说明:无- 说明:w25x16 Flash作为从机,由stm32进行读写操作- 每256bytes为一个Page,每4Kbytes为一个Sector,每16个扇区为1个Block- W25X16容量为2M字节,共有32个Block, 512个Sector , 8192个Page- W25X32容量为4M字节,共有64个Block, 1024个Sector ,16384个Page- W25X64容量为8M字节,共有128个Block,2048个Sector ,32768个Page***************************************************************************/void SPI_Flash_Init(void){SPIx_Init(); //初始化SPI}/*************************************************************************** - 功能描述:读w25x16 Flash状态寄存器的函数- 隶属模块:w25x16 Flash操作- 函数属性:外部,使用户使用- 参数说明:无- 返回说明:返回w25x16 Flash的当前状态------------------------------------------------------| 7 6 5 4 3 2 1 0 || SPR RV TB BP2 BP1 BP0 WEL BUSY || SPR:默认0,状态寄存器保护位,配合WP使用|| TB,BP2,BP1,BP0:FLASH区域写保护设置|| WEL:写使能锁定|| BUSY:忙标记位(1,忙;0,空闲) || 默认:0x00 || 只有SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)可以写!!! |------------------------------------------------------ 操作说明:CS电平先拉低、STM32利用SPI发送读FLASH状态寄存器命令、STM32读取数据、CS拉高,发送的命令被采集如果CS不拉高,则FLASH的状态会不断发送出来。
关于STM32的FLASH操作

关于STM32的FLASH操作STM32是一款由意法半导体(STMicroelectronics)推出的32位精简型单片机系列。
它采用了ARM Cortex-M内核,并在Flash和内存等方面进行了优化,提供了强大的性能和丰富的外设功能。
FLASH是STM32芯片上的一种非易失性存储器,可以用于存储应用程序代码、数据、配置信息等。
在STM32中进行FLASH操作可以通过编程和标准库函数两种方式实现。
下面将依次介绍这两种方法的使用。
一、编程方式编程方式是直接对FLASH进行底层的读写操作,需要对相关寄存器进行配置和控制。
1.写入数据在STM32的FLASH中写入数据的操作需要经历以下步骤:1) 解锁FLASH:通过FLASH_Unlock(函数解锁FLASH,使其可写入。
2) 擦除FLASH:通过FLASH_ErasePage(函数擦除要写入的FLASH扇区。
3) 写入数据:通过FLASH_ProgramByte(、FLASH_ProgramHalfWord(、FLASH_ProgramWord(等函数对FLASH进行数据写入。
4) 上锁FLASH:通过FLASH_Lock(函数上锁FLASH,防止误操作。
以下是一个简单的例子,演示如何通过编程方式对STM32的FLASH进行数据写入:```c#include "stm32f10x_flash.h"void ConfigureFlash(void)FLASH_Unlock(; // 解锁FlashFLASH_ClearFlag(FLASH_FLAG_EOP , FLASH_FLAG_PGERR ,FLASH_FLAG_WRPRTERR); // 清除状态标志FLASH_ErasePage(FLASH_START_ADDR); // 擦除扇区FLASH_Lock(; // 上锁Flash```2.读取数据读取STM32的FLASH数据需要通过指针的方式直接读取存储器的地址,如下所示:```c#define READ_FLASH(addr) (*(volatile uint32_t*)(addr))void ReadFlash(void)uint32_t data = READ_FLASH(FLASH_START_ADDR);//在这里对读取的数据进行处理```二、标准库函数方式STM32提供了一套标准库函数,方便开发者进行FLASH操作。
基于STM32F0的SPI通信的FLASH程序分析

基于STM32F0的SPI通信的FLASH程序分析Ⅰ、概述关于SPI(Serial Peripheral Interface)串行外设接口可以说是单片机或者嵌入式软件开发人员必须掌握的一项通信方式,就是你在面试相关工作的时候都可能会问及这个问题。
在这里问一个简单的问题:硬件SPI和软件模拟SPI的区别是有哪些?估计这个问题会问倒很多人。
SPI通信中分为SPI主机和从机,在实际应用中作为主机是比较常见的一种,因为SPI的通信速度远比I2C的通信速度大,所以现在市面上有很多SPI从设备。
本文SPI读写操作,以SPI通信的FLASH(25Q16)为从设备进行举例。
串口发送10字节数据,接收满10字节自动保存,间隔500ms读写数据,通过串口打印出来。
Ⅱ、下载文章提供的“软件工程”都是在硬件板子上进行多次测试、并保证没问题才上传至360云盘,请放心下载测试,如有问题请检查一下你的板子是否有问题。
ST标准外设库和参考手册、数据手册等都可以在ST官网下载,你也可以到我的360云盘下载。
关于F0系列芯片的参考手册有多个版本(针对F0不同芯片),但有一个通用版本,就是“STM32F0x128参考手册V8(英文)2015-07”建议参考该手册,以后如果你换用一种型号芯片也方便了解。
Ⅲ、准备工作建议准备F0的参考手册和数据手册,方便查阅相关知识,没有的请到ST官网或到我360云盘下载。
今天总结的软件工程是基于“TIM基本延时配置详细过程”修改而来,因此需要将该软件工程下载准备好。
我每次都是提供整理好的软件工程供大家下载,但是,如果你是一位学习者,建议自己亲手一步一步操作:打开工程->新建文件(spi.c spi.h) ->添加到工程中->添加源代码。
Ⅳ、SPI原理。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/* SPI_FLASH_CS_LOW(),是一个宏定义,就是拉低 CS(PA4) */
SPI_FLASH_CS_LOW();
/*W25X_DeviceID=0XAB,是 读 器 件 地 址 的 命 令 , 发 送 完 该 命 令 后 连
续发三个任意数字,在发第五个任意数后可以读出地址 */ SPI_FLASH_SendByte(0XAB);
/*指定 NSS 信号由软件管理*/
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
/SPI_BaudRatePrescaler 用来定义波特率预分频的值,这个值用以设置发送
和接收的 SCK 时钟/
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
/* 等待接收完一字节数据 */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
/* 返回接收到的数据 */
return SPI_I2S_ReceiveData(SPI1); } 现在我们再来看看读器件地址函数: / ************************************************************** ***************** * Function Name : SPI_FLASH_ReadDeviceID(void)
*****************/ u8 SPI_FLASH_SendByte(u8 byte) {
/* 等待 SPI 发送寄存器里的数据发送结束 */
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
/* 发送数据*/
SPI_I2S_SendData(SPI1, byte);
图 5-1
(3) 获取器件地址 2
获取完地址 1 后,我们再来获取地址 2.读地址 2 的命令是 0X9F,从图
5-1 中可以看到,发送完 0X9F 后连续读出 3 个数据。好的,我们来看看具
体的程序: / ********************************************************************* ********** * Function Name : SPI_FLASH_ReadID
* Description : 读器件地址 2
* Input : 无
* Output : 无
* 返回
: 器件地址 2
调用
: SPI_FLASH_SendByte
********************************************************************* **********/ u32 SPI_FLASH_ReadID(void) { u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
/*将 CLK 的高电平设为空闲*/
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
/*设 置 在 第 二 个 时 钟Байду номын сангаас沿 捕 获 数 据 */
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
好的,既然用到写命令那么我们写来写这两个最基础的程序。
写数据函数: / ************************************************************** ***************** * Function Name : SPI_FLASH_SendByte
void SPI_FLASH_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
/* Enable SPI1 and GPIO clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE); /*!< SPI_FLASH_SPI Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
/*将 PA6(DO)设置成浮空输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOA, &GPIO_InitStructure);
/将 PA7(DIO)设为浮空输入/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOA, &GPIO_InitStructure);
SPI_FLASH_CS_HIGH();
/* SPI 配置/
// W25X16: data input on the DIO pin is sampled on the rising edge of the CLK. // Data on the DO and DIO pins are clocked out on the falling edge of CLK.
1) 获取地址 1 2) 获取地址 2 3) 擦除扇区 4) 写入数据 好的,下面我们对每个步骤进行分析
(1) 在对芯片操作前先要对端口及 SPI 外设进行相应的设置:
/*
函数名:SPI_FLASH_Init(void)
功能 :对端口和 SPI 初始化 输入 :无 输出 :无 调用 :被主函数调用 */
(2) 获取器件地址 1
因为 SPI 总线上可以挂很多的器件,所以首先要获得器件的地址。
获得器件地址的步骤是:拉低 CS——>向器件发送获得地址的命令——>
连续发送三个任意数据——>在发送第四个任意数据时在 DO 口上读出
器件地址。注意,发送完读地址后,从机会将数据自动传给主机的 SPI
数据寄存器中,用户只要到该寄存器中取数就可以了。
/* 拉低 CS 来使能从机 */
SPI_FLASH_CS_LOW();
/*W25X_JedecDeviceID=0X9F,读 取 从 机 地 址 的 命 令 , 发 送 完 命 令 后 可 以 连 续
读三个字节的地址 */
SPI_FLASH_SendByte(0X9F); /* Read a byte from the FLASH */ Temp0 = SPI_FLASH_SendByte(Dummy_Byte); /* Read a byte from the FLASH */ Temp1 = SPI_FLASH_SendByte(Dummy_Byte); /* Read a byte from the FLASH */ Temp2 = SPI_FLASH_SendByte(Dummy_Byte);
/SPI_FirstBit 指定了数据传输从高位还是低位开始/
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
/SPI_CRCPolynomial 定义了用于 CRC 值计算的多项式/
SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(SPI1, ENABLE); }
* Description : 通过 SPI 总线发送一字节数据,再通过 SPI 总线返回
* Input
一字节数据 : byte ——要发送的数据
* Output : 从机返回的数据
* 调用
:被 SPI_FLASH_ReadDeviceID 调用
**************************************************************
SPI_FLASH_SendByte(0XFF); SPI_FLASH_SendByte(0XFF); SPI_FLASH_SendByte(0XFF); /* Read a byte from the FLASH */ Temp = SPI_FLASH_SendByte(0XFF); /* 失能芯片*/ SPI_FLASH_CS_HIGH(); /*返 回 器 件 地 址 */ return Temp; } 像温度传感器一样,WX25X16 也有很多的命令,具体的命令看下 图:
* Description : 读器件地址 1
* Input : 无
* Output : 无
* 返回
: 器件地址
调用
: SPI_FLASH_SendByte
************************************************************** *****************/ u32 SPI_FLASH_ReadDeviceID(void) { u32 Temp = 0;
/将 PA4(CS)设为推挽输出/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure);
/拉高 CS,失能芯片,该语句是宏定义,就是置高 PA4/