做网站月薪资多少,自己做网站挣钱吗,微信网站开发公司电话,温州做网站哪里好STM32–SPI通信与W25Q64#xff08;1#xff09; 文章目录 SPI外设特征 SPI框图传输模式主模式全双工连续传输 非连续传输硬件SPI读写W25Q64 SPI外设
STM32内部集成了硬件SPI收发电路#xff0c;可以由硬件自动执行时钟生成、数据收发等功能#xff0c;减轻CPU的负担。
特…STM32–SPI通信与W25Q641 文章目录 SPI外设特征 SPI框图传输模式主模式全双工连续传输 非连续传输硬件SPI读写W25Q64 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非空读取数据ANTXE也为空时BSY位置0关闭SPI模块 这里的连续传输就是在一开始一个数据写入之后还会继续写入一个数据由于是同时进行传输所以等到读取数据后又写入一个数据 在最后会连续读取两个数据表示结束。 非连续传输 一开始写入一个数据1接着会等待TXE为空时此时读取一个数据A1接着会等待RXNE非空时再写入数据2以此类推。 对于写入的数据等待TXE为空后本来可以再写入一个数据但是在这种模式是读取一个数据等到RXNE非空时再写入数据 你会发现在标志位后本来是做出对应的事件但是这种方式却是选择等待也就是传输的数据是不连续的。 硬件SPI读写W25Q64
这里的接线方式和试验方法和软件读写是一致的只是将MySPI.进行改装。
#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_ModeGPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_PinGPIO_Pin_4;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);GPIO_InitStructure.GPIO_ModeGPIO_Mode_AF_PP; //复用推挽输出GPIO_InitStructure.GPIO_PinGPIO_Pin_5|GPIO_Pin_7;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);GPIO_InitStructure.GPIO_ModeGPIO_Mode_IPU; //上拉输入GPIO_InitStructure.GPIO_PinGPIO_Pin_6;GPIO_InitStructure.GPIO_SpeedGPIO_Speed_50MHz;GPIO_Init(GPIOA,GPIO_InitStructure);SPI_InitTypeDef SPI_InitStructure;SPI_InitStructure.SPI_BaudRatePrescalerSPI_BaudRatePrescaler_128; //设置SCK时钟波特率分频值SPI_InitStructure.SPI_CPHASPI_CPHA_1Edge;//指定哪个边沿开始捕获SPI_InitStructure.SPI_CPOLSPI_CPOL_Low; //低边沿为常态SPI_InitStructure.SPI_CRCPolynomial7; //CRC设置值默认值为7SPI_InitStructure.SPI_DataSizeSPI_DataSize_8b;//传输数据大小bitSPI_InitStructure.SPI_DirectionSPI_Direction_2Lines_FullDuplex;//设置双工和收发SPI_InitStructure.SPI_FirstBitSPI_FirstBit_MSB;//指定传输从低位还是高位开始SPI_InitStructure.SPI_ModeSPI_Mode_Master;//主从模式SPI_InitStructure.SPI_NSSSPI_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就是尾页的大小进行测试通过改变地址来进行验证。