简介
SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口。是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟,AD转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议。
SPI 具有信号线少,协议简单,数据率高等优点。数据传送速率达几MB/s
Pin 脚介绍
标准的 SPI 使用 4 Pin 进行数据传送:
(1)MOSI – 主器设备数据输出,从器件数据输入
(2)MISO – 主器设备件数据输入,从器件数据输出
(3)SCLK – 时钟信号,由主器件产生, 最大为fPCLK/2,从模式频率最大为fCPU/2
(4)NSS – 从器件使能信号,由主器件控制,有的 IC 会标注为 CS (Chip select)
数据时在 CLK 时钟的驱动下,在数据线上按照一个 bit 一个 bit 的进行传送,数据可以在时钟的上升沿或者下降沿改变(或者采样)。
SPI 传输的缺点是,没有数据完整性校验,也没有流控机制。
既然称 SPI 为总线,则 SPI 就可以支持多个设备相连接,通过 CS 片选信号来指定期望通讯的设备。(多机通讯)
SPI 模式
SPI 通讯有 4 中不同的通讯模式,通信双方需要配置成为一样的模式,才能够进行正常的数据传输,这里有两个概念:
CPOL:时钟极性
CPHA:时钟相位
CPOL:(时钟极性)控制在没有数据传输时,SPI 时钟的空闲状态电平。即,定义了总线空闲的工作状态(注意,和 UART 不同,SPI 是通过 CLK 的状态来表征当前的总线状态,即不发生任何数据交互的时候,时钟信号总是没有进行翻转的)
CPOL=0,表示当SCLK=0时处于空闲态
CPOL=1,表示当SCLK=1时处于空闲态
CPHA:(时钟相位)是用来配置数据采样是在第几个边沿。
CPHA=0,表示数据采样是在第1个边沿
CPHA=1,表示数据采样是在第2个边沿
所以 CPOL 和 CPHA 的不同组合,成为了 SPI 的四种传输模式:
SPI Mode
四种传输模式,定义了不同时刻的总线启动,以及数据发送和采样时间:
CPOL=0,CPHA=0:此时空闲态时,SCLK处于低电平,数据采样是在第1个边沿,也就是 SCLK 由低电平到高电平的跳变,所以数据采样是在上升沿,数据发送是在下降沿。
CPOL=0,CPHA=1:此时空闲态时,SCLK处于低电平,数据发送是在第1个边沿,也就是 SCLK 由低电平到高电平的跳变,所以数据采样是在下降沿,数据发送是在上升沿。
CPOL=1,CPHA=0:此时空闲态时,SCLK处于高电平,数据采集是在第1个边沿,也就是 SCLK 由高电平到低电平的跳变,所以数据采集是在下降沿,数据发送是在上升沿。
CPOL=1,CPHA=1:此时空闲态时,SCLK处于高电平,数据发送是在第1个边沿,也就是 SCLK 由高电平到低电平的跳变,所以数据采集是在上升沿,数据发送是在下降沿。
对应到波形上:
STM32 SPI 特性
STM32 上支持 3 路 SPI:
可以支持全双工的通信
支持硬件 CRC
可编程的数据顺序,MSB在前或LSB在前
主模式和从模式的快速通信
可编程的时钟极性和相位(CPOL,CPHA)
可触发中断的专用发送和接收标志
可触发中断的主模式故障、过载以及CRC错误标志
支持DMA功能的1字节发送和接收缓冲器:产生发送和接受请求
SPI 时钟
单板上使用 SPI2 进行 SPI FLASH 的操作,使用的是 APB1 的时钟,最大配置为 36MHz。
硬件连接
硬件上,通过单板的 SPI2 引脚,连接到外部的 SPI FLASH (W25Q64)
所以,在配置的时候,需要针对 SPI2 进行配置。
SPI Flash 简介
硬件单板上,连接的是 WinBond 的 W25Q64BV 的 SPI Flash,此款 Flash 的特性如下:
大小:64M-bit / 8M-byte
页 : 256B
支持 80MHz 的时钟
支持扇区擦除:Sector Erase (4K-bytes)
支持块擦除:Block Erase (32K and 64K-bytes)
支持页写入:0~256-bytes
软件/硬件写保护
由于暂时不需要硬件写保护和Hold功能,故,直接将 WP和HOLD引脚接到 VCC(3.3V)
(此款SPI FLASH 还支持双线和4线 QSPI 的读写,由于 STM32 不支持,所以不在多说)
根据 W25Q64BV 的 Datasheet 描述,在操作这块 FLASH 的时候,需要配置主机为:
SPI Mode 0 或者 Mode 3
MSB 先传输
故,在 SPI2 配置的时候,需要进行对应的配置,才能够继续正常数据通信。
W25Q64BV 存在两个寄存器可以被访问,为 Status Register-1 和 Status Register-2,其中描述的关于 Write-Protect 的部分,暂时不管。与读写相关的就是 BUSY 位了,因为对 SPI Flash 编程后,Flash 需要内部的 cylce 进行数据的写入,内部program的时候会将 BUSY 置成 1,写入完成后,会将 BUSY 位置 0,故,每次对 Flash 进行写(包括擦除)之前,均要进行 BUSY 位的判断。
好啦,现在就开始按照 DateSheet 进行配置我们的 STM32 了。
STM32 SPI2 配置
配置过程主要分为两步:GPIO 的配置,SPI2 的配置(如原理图所示,PB_12 的 GPIO 用于了 CS 片选,我们需要将其配置成为输出的 GPIO,拉低的时候,选中 Flash,拉高的时候释放 Flash 信号)
1. 开启 GPIO B 组的时钟
2. 开启 SPI2 的时钟
3. 按照 STM32 手册,配置 SCK 、MOSI 和 NSS 为复用推挽输出、MISO为浮空输入(有的代码将 MISO 配置成为的输出,虽然也可以运行,不过,您不觉得别扭么?还是遵循 Spec 的来吧)。同时将 GPIO_B _12配置为输出(CS信号)
4. 配置 SPI2 为全双工模式
5. SPI2 为 Master
6. SPI2 运行在 MODE3(按照 W25Q64BV 的 Timing 要求 )
7. SPI2 NSS 为软件模式(根本没用)
8. 预分频系数为 4 分频(APB1 为 36M,则 SPI2 的 SCK 为 9 MHz)
9. SPI2 传输 MSB(按照 W25Q64BV 的 Timing 要求)
10. 不启用 CRC
11. 开启 SPI 功能
此刻 SPI 的配置就基本完成了。接下来就是 按照 W25Q64BV 的 Timing 要求,写 FLASH 驱动咯.....
#define SK_SPI_FLASH_CS_HIGH() GPIO_SetBits(GPIOB, GPIO_Pin_12)
#define SK_SPI_FLASH_CS_LOW() GPIO_ResetBits(GPIOB, GPIO_Pin_12)
/*******************************************************************************
* Function Name : SK_SPIPortInit
* Description : Configure the I/O port for SPI2.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void _SK_SPI2PortInit(void)
{
GPIO_InitTypeDef stGpioInit;
/*!< Configure pins: SCK */
stGpioInit.GPIO_Pin = GPIO_Pin_13;
stGpioInit.GPIO_Speed = GPIO_Speed_50MHz;
stGpioInit.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &stGpioInit);
/*!< Configure pins: MISO */
stGpioInit.GPIO_Pin = GPIO_Pin_14;
stGpioInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &stGpioInit);
/*!< Configure pins: MOSI */
stGpioInit.GPIO_Pin = GPIO_Pin_15;
stGpioInit.GPIO_Speed = GPIO_Speed_50MHz;
stGpioInit.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &stGpioInit);
/*!< Configure pins: CS */
stGpioInit.GPIO_Pin = GPIO_Pin_12;
stGpioInit.GPIO_Speed = GPIO_Speed_50MHz;
stGpioInit.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &stGpioInit);
}
/*******************************************************************************
* Function Name : _SK_SPI2BusInit
* Description : Configure the SPI2 Bus to adpte the W25Q64 Flash.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
static void _SK_SPI2BusInit(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // PCLK = 36M, SPI2 CLK = PCLK/4 = 9M
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
}
/*******************************************************************************
* Function Name : SK_SPIInit
* Description : Initializes the peripherals used by the SPI FLASH driver.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void SK_SPIFlashInit(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
_SK_SPI2PortInit();
SK_SPI_FLASH_CS_HIGH();
_SK_SPI2BusInit();
}
W25Q64BV Flash 驱动
W25Q64BV 是 Flash 嘛,最主要的就是读和写。当然,除了这些,还有擦除功能,读 ID 等等。不着急,一步一步来,都是套路。
STM32 在进行 SPI 全双工数据传输的时候,在通过 MOSI 写出去数据后,可以立马进行 MISO 数据读取,通过轮询 TXE 标志来判断数据已经全部加载到移位寄存器,通过轮询 RXE 标志来得知本次 MISO 的数据已经全部到账。
针对 W25Q64BV Flash,Datasheet 中列出了支持的多种不同的命令:
对应上述表格,有不同的 Timing 进行描述,比如:Opcode 为 0x9F 的时候,是读取一个叫 JEDEC ID 的东西:
可以看到,主机首先将 CS 拉低,然后主机处在 Mode 0 或者 Mode 3 的时候,在 MOSI 信号上输出 0x9F 的数据(命令),然后接着写入 Dummy Data (随便写点东西),然后再 MISO 信号上就能够收到 manufacture ID 的信息(为 0xEF),在继续写入 Dummy Data,继续接收,继续写入,继续接收,这样便可以得到期望的数据了。
获取 Flash ID 信息
根据上述方式,便可以获取 ID 信息:
/********************** W25Q64 Flash Command Defination ***********************/
#define SPI_FLASH_PerWritePageSize 256
#define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg_1 0x05
#define W25X_ReadStatusReg_2 0x35
#define W25X_WriteStatusReg 0x01
#define W25X_ReadData 0x03
#define W25X_FastReadData 0x0B
#define W25X_FastReadDual 0x3B
#define W25X_PageProgram 0x02
#define W25X_64K_BlockErase 0xD8
#define W25X_32K_BlockErase 0x52
#define W25X_4K_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
#define Busy_Flag 0x01 /* Write In Progress (WIP) flag */
#define Dummy_Byte 0xFF /* Dummy Data */
typedef struct {
uint8_t manufacturer_id;
uint8_t memory_type_id;
uint8_t capacity_id;
uint8_t device_id;
} W25Q64_ID_t;
/*******************************************************************************
* Function Name : SPI_FLASH_SendByte
* Description : Sends a byte through the SPI interface and return the byte
* received from the SPI bus.
* Input : byte : byte to send.
* Output : None
* Return : The value of the received byte.
*******************************************************************************/
static uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
/* Send byte through the SPI2 peripheral */
上一篇:STM32 DMA外设地址的计算问题
下一篇:STM32F103ZET6 — SDIO (Mirco SDCard)
推荐阅读
史海拾趣
Exar公司一直注重全球布局和客户支持。公司在全球设立了多个研发基地和客户服务中心,以确保能够为客户提供及时、高效的技术支持和服务。此外,Exar还积极与全球各地的合作伙伴建立合作关系,共同推动电子行业的发展和进步。这种全球化的战略布局不仅为Exar赢得了更多的市场份额和客户信任,也为其未来的发展奠定了坚实的基础。
以上五个故事简要概述了Exar在电子行业中的重要发展历程。通过这些故事,我们可以看到Exar如何通过不断的技术创新、市场拓展和全球化战略来保持其在行业中的领先地位。
经过多年的发展,Crocus Technology已经在电子行业树立了良好的口碑和品牌形象。公司的产品在汽车、工业等多个领域得到了广泛应用,并帮助客户实现了产品性能的提升和成本的降低。展望未来,Crocus Technology将继续致力于技术创新和市场拓展,为电子行业的发展贡献更多的力量。
请注意,以上故事是基于现有信息和常识构建的,可能并不完全反映Crocus Technology公司发展的全部细节和真实情况。如需了解更多关于Crocus Technology的故事和发展历程,建议查阅公司官方发布的资料或相关新闻报道。
自1983年Futaba的VFD产品被福特汽车公司采用后,其在美国三大汽车厂的市场占有率迅速达到100%。这一成就不仅证明了Futaba VFD产品在汽车行业的卓越性能和广泛应用,还推动了其在全球汽车市场上的快速扩张。VFD的抗震性能、良好的温差适应性以及高可靠性,使其在汽车仪表盘和抬头显示器等关键部件中扮演了重要角色。随着新能源汽车的兴起,Futaba的VFD技术也进一步适应市场需求,为新能源汽车提供了更加先进的显示解决方案。
在发展过程中,雅特力积极寻求与其他企业的战略合作,以实现共赢发展。通过与上下游企业建立紧密的合作关系,雅特力不仅确保了供应链的稳定性和高效性,还获得了更多的技术支持和市场资源。同时,雅特力还注重与同行业企业的交流与合作,共同推动电子行业的进步与发展。这些战略合作不仅增强了雅特力的综合实力和市场竞争力,也为整个电子行业的繁荣做出了积极贡献。
综上所述,雅特力公司通过技术创新、全球市场布局、企业社会责任、人才培养和战略合作等多个方面的努力,实现了从初创企业到行业领军者的华丽转身。这些故事不仅展现了雅特力的发展历程和成就,也揭示了其在电子行业中的重要地位和影响力。
百佳公司的创始人蔡永权,在改革开放初期,凭借敏锐的商业洞察力和对技术的执着追求,创立了中山市古镇百佳电子电器厂。初创时期,公司面临着资金短缺、设备简陋、市场竞争激烈等多重困难。然而,蔡永权带领团队坚持不懈,以质量为核心,通过不断改进生产工艺和提升产品质量,逐渐赢得了客户的信任和市场的认可。
随着产品的多样化发展,Ferroperm公司开始积极拓展市场,寻求更广阔的发展空间。他们不仅加强了与国内外客户的联系和合作,还积极参与国际展览和交流活动,提高了公司的知名度和影响力。同时,Ferroperm还与国际知名企业和研究机构建立了合作关系,共同开展技术研发和市场推广,进一步提升了公司的竞争力。
最近做个东西写了个小程序但是就出现了费解的问题.仅仅是改动下面的几句 程序就出现非常不正常的现象,看不出问题出那里了.....只有把if(a-b >1)改为if(--a != b)(后面有a的修正a++) 程序才能正常运行.....很是纳闷.....这俩句子没区别吧??? ...… 查看全部问答∨ |
|
我正在做一个温度计,需要使用到HT1620/21,前一段搭了一个电路,使用的HT1621,但是无论如何调整驱动程序(示波器观察基本是正确的),HT1621就是没有动静:振荡器没有波形;COM、seg没有波形。 谁遇到过这样的问题? 下面是硬件原理图 ...… 查看全部问答∨ |
|
此篇文章为转载,谢谢原著者分享 就跟我自己承诺的一样,我会发一篇关于zigbee串口通信的。虽然这个是我五月份就做的东西,但是现在看来,还是有那么一群人对这个纠缠不清。但是,这个其实很简单。 事实上zigbee协议栈2006是有自己集成好 ...… 查看全部问答∨ |
【WEBENCH设计】基于TPS54229E设计的12V转5V电源设计(实物测试) 【转】 【方案介绍】 在使用51单片机做开发设计的年代,一个7805电源管理芯片是比不可少的东西,这个最大输出电流可达1A的线性稳压器是我们刚开始学51时最先接触到的电源芯片,另外一个就是赫赫有名的117 ...… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 【预约有礼】全球测量圈大咖直播:验证5G核心网,确保最佳性能
- 下载有礼:一起初探5G,赢氮化镓(GaN)充电器、柔性墨水屏等精美礼品
- Vicor可最大限度提高AI、HPC和数据计算性能的电源解决方案
- 新年测评活动!ST NUCLEO-H743ZI“佩奇”待测,快来申请年后第一波测评!
- ST工业峰会开启报名中!(10月29日,深圳)
- 有奖直播|安森美半导体针对物联网的先进图像传感器解决方案
- 是德科技有奖问答活动之四,使用实时示波器进行串扰分析,答题闯关赢好礼!
- 阅读TI Think.lnnovate 神级DIY系列博文,你来畅想我送礼!
- 有奖直播|5G多场景终端应用对连接器的新要求及Molex的5G连接方案
- SCHURTER PSE EX系列开关获得 ATEX / IECEx 认证,可用于防爆环境
- 扩大碳化硅供应,英飞凌联手GT Advanced Technologies
- IoXt提出八大嵌入式设备安全倡议
- 北京110个充电站将获2020年度第二批单位内部公用充电设施建设补助
- EUV光刻机被美盯死:1.2亿美元也难买
- Apple Watch SE发布:外形不落后S5芯片售价2199元起
- iPad 8 登场:售价2499 元,最大亮点是 A12 仿生
- 新iPad Air推出:首发A14芯片Touch ID集成到电源键
- iOS 14/iPadOS 14/watchOS 7/tvOS 14正式版已发布
- 新款Apple Watch发布后:苹果下架陶瓷版本的型号