STM32--SPI通信与W25Q64(2)

STM32--SPI通信与W25Q64(1)

文章目录

SPI外设

STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担

特征

3线全双工同步传输
8或16位传输帧格式选择
主或从操作
支持多主模式
8个主模式波特率预分频系数(最大为fPCLK/2)
主模式和从模式下均可以由软件或硬件进行NSS管理:主/从操作模式的动态改变
可编程的数据顺序, MSB在前或LSB在前
可编程的时钟极性和相位
SPI总线忙状态标志
兼容I2S协议

STM32F103C8T6 硬件SPI资源:SPI1、SPI2

SPI框图

通过主控制电路来控制数据的传输;

先看左上角部分,对于接收的数据,会从MISO引脚进入;数据一位一位的进入移位寄存器,当有一个字节(或者两个字节大小)的数据在移位寄存器时,传送移位寄存器里的数据到接收缓冲器,并且RXNE标志被置位

这里的RXNE是是接收缓冲区的标志位,

读SPI_DR接收寄存器可以清除RNXE标志位

在连续传输数据中,一个要接收的数据只有被读出,下一个数据才有机会进入接收缓冲器。而利用RNXE标志位即可知道当前数据是否被读出。否则,下一个数据会对当前数据进行覆盖,那么读取数据就会造成错误。

对于要发送的数据,会将写入数据先放在发送缓冲器中,在发送第一个数据位时,数据字被并行地(通过内部总线)传入移位寄存器,而后串行地移出到MOSI脚上;(可自行设定低位先行还是高位先行); 数据从发送缓冲器传输到移位寄存器时TXE标志将被置位

发送到移位寄存器的标志位

只要写入SPI_DR寄存器那么TXE标志位就会被清除。这里将移位寄存器和接收缓冲区和发送缓冲区合在一起,就是数据寄存器;

这里要注意,数据寄存器内部会分为两部分,接收和发送,移位寄存器是共用的,但传输单位最小是8bit或者是16bit,都是以字节为单位的,不会造成同时进行发送和接收的冲突;

右边则是将寄存器的位都标出来了,CR是控制寄存器,只要是产生使能的寄存器;SR是状态寄存器,比较重要的就是刚才介绍的两个RXNE和TXE;

波特率发生器用来控制SCK分频;

传输模式

主模式全双工连续传输

同时进行传输的

一开始,会先写入一个数据1,接着会使标志位TXE置非空,等到TXE位空时,再写入一个数据2,此时会等待RXNE非空时,读取数据A1,接着就是等到TXE为空,再写入一个数据3,然后又是等待RXNE非空时,读取数据A2...以此传输下去,到最后,RXNE非空,读取数据AN,TXE也为空时,BSY位置0,关闭SPI模块;

这里的连续传输就是在一开始一个数据写入之后,还会继续写入一个数据,由于是同时进行传输,所以等到读取数据后又写入一个数据;

在最后会连续读取两个数据表示结束。

非连续传输

一开始写入一个数据1,接着会等待TXE为空时,此时读取一个数据A1,接着会等待RXNE非空时,再写入数据2,以此类推。

对于写入的数据,等待TXE为空后,本来可以再写入一个数据,但是在这种模式是读取一个数据,等到RXNE非空时,再写入数据;

你会发现,在标志位后本来是做出对应的事件,但是这种方式却是选择等待,也就是传输的数据是不连续的。

硬件SPI读写W25Q64

这里的接线方式和试验方法和软件读写是一致的,只是将MySPI.进行改装。

c 复制代码
#include "stm32f10x.h"                  // Device header

//片选电平
void MySPI_W_SS(uint8_t Byte)
{
    GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)Byte);
}


//初始化
void MySPI_Init()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //上拉输入
    GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);
    
    SPI_InitTypeDef SPI_InitStructure;
    SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_128; //设置SCK时钟波特率分频值
    SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;//指定哪个边沿开始捕获
    SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low; //低边沿为常态
    SPI_InitStructure.SPI_CRCPolynomial=7; //CRC设置值,默认值为7
    SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;//传输数据大小(bit)
    SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//设置双工和收发
    SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;//指定传输从低位还是高位开始
    SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//主从模式
    SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//软件设置
    SPI_Init(SPI1,&SPI_InitStructure);
    
    SPI_Cmd(SPI1,ENABLE);
    MySPI_W_SS(1);
    
}
//开始
void MySPI_Start()
{
    MySPI_W_SS(0);
}
//结束
void MySPI_Stop()
{
    MySPI_W_SS(1);
}
//交换字节
uint8_t MySPI_SwapByte(uint8_t SendByte)
{
    while(!SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE));
    SPI_I2S_SendData(SPI1,SendByte);
    while(!SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE));
    return SPI_I2S_ReceiveData(SPI1);
}

对于片选信号,我们用GPIO引脚表示高低电平会更加容易;

对于A5和A7引脚,由于SPI外设是GPIO口的片上外设,所以要采用复用功能;

这里SPI外设的传输是有多种模式,我们选择全双工收发模式;

高位开始低位开始传输也是可以选择的;

最后要记得要启用SPI,否则将无效;
这里的交换字节采用非连续传输的方式,我们的顺序与上面的逻辑图是相反的,是因为对于标志位,在读取和写入时会自动清除标志位,先写标志位,再写发送数据和读出数据会更加方便;

在这里说一下试验的注意事项,

对于扇区擦除,只要输入的数据在指定扇区,那么就会对那一片扇区进行擦除;

这是一片扇区,那么输入000000h到000FFFh的地址位,都是对该扇区的擦除;

对于测试连续写入多字节时,最多写入一页的数据,超过页尾位置的数据,会回到页首覆盖写入。

我们可以以000000h为头,那么0000FFh就是尾,(页的大小)进行测试;通过改变地址来进行验证。

相关推荐
时空自由民.24 分钟前
无人机系统耗电,低功耗管理问题解决方法(chatgpt)
单片机·嵌入式硬件·无人机
时空自由民.29 分钟前
无人机系统耗电,低功耗管理问题解决方法(腾讯元宝)
单片机·嵌入式硬件·无人机
清风6666662 小时前
基于单片机的双档输出数字直流电压源设计
单片机·mongodb·毕业设计·nosql·课程设计
牛马大师兄2 小时前
STM32独立看门狗IWDG与窗口看门狗WWDG知识梳理笔记
笔记·stm32·单片机·嵌入式硬件·嵌入式·看门狗
夜月yeyue2 小时前
STM32 Flash 访问加速器详解(ART Accelerator)
linux·单片机·嵌入式硬件·uboot·bootloard
A9better2 小时前
嵌入式开发学习日志37——stm32之USART
stm32·嵌入式硬件·学习
国科安芯6 小时前
ASP4644芯片低功耗设计思路解析
网络·单片机·嵌入式硬件·安全
充哥单片机设计6 小时前
【STM32项目开源】基于STM32的智能厨房火灾燃气监控
stm32·单片机·嵌入式硬件
CiLerLinux13 小时前
第四十九章 ESP32S3 WiFi 路由实验
网络·人工智能·单片机·嵌入式硬件
时光の尘13 小时前
【PCB电路设计】常见元器件简介(电阻、电容、电感、二极管、三极管以及场效应管)
单片机·嵌入式硬件·pcb·二极管·电感·三极管·场效应管