wordpress支持建多个站点吗,文字图片在线制作生成器,Wordpress只做后端,新网站建设的流程SPI软件模拟的时序
SPI协议中#xff0c;NSS、SCK、MOSI由主机产生#xff0c;MISO由从机产生#xff0c;在SCK每个时钟周期MOSI、MISO传输一位数据#xff0c;数据的输入输出是同时进行的#xff0c;所以读写数据也可以视作交换数据。所以读写时对数据位的控制都是用同一…SPI软件模拟的时序
SPI协议中NSS、SCK、MOSI由主机产生MISO由从机产生在SCK每个时钟周期MOSI、MISO传输一位数据数据的输入输出是同时进行的所以读写数据也可以视作交换数据。所以读写时对数据位的控制都是用同一个函数即可。
输出引脚为推挽输出输入引脚为浮空或上拉输入 如上图所示 初始状态下
CS需要拉高CLK模式0的时候拉低模式3的时候拉高
然后读/写数据状态时
CS拉低如果需要写数据或读数据先将数据写入DI线拉高CLK电平读DO线拉低CLK电平然后循环7次前面四步则交换了一个字节数据
例程
#include stm32f10x.h // Device header
#include hal_spi.hvoid hal_SPI_W_SS(uint8_t BitValue) //写设备线
{GPIO_WriteBit(SPI_SS_PORT, SPI_SS_PIN, (BitAction)BitValue);
}void hal_SPI_W_SCK(uint8_t BitValue) //写时钟线
{GPIO_WriteBit(SPI_SCK_PORT, SPI_SCK_PIN, (BitAction)BitValue);
}void hal_SPI_W_MOSI(uint8_t BitValue) //写主机发数据线
{GPIO_WriteBit(SPI_MOSI_PORT, SPI_MOSI_PIN, (BitAction)BitValue);
}uint8_t hal_SPI_R_MISO(void) //读从机发数据线
{return GPIO_ReadInputDataBit(SPI_MISO_PORT, SPI_MISO_PIN);
}/****************************************************************************
**名称 hal_SPI_Init
**功能 初始化spi的各个引脚
**形参 无
**返回值 无
****************************************************************************/
void hal_SPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin GPIO_Pin_4 | 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);hal_SPI_W_SS(1);hal_SPI_W_SCK(0);
}/****************************************************************************
**名称 hal_SPI_Start
**功能 spi开始传输数据设备线拉高
**形参 无
**返回值 无
****************************************************************************/
void hal_SPI_Start(void)
{hal_SPI_W_SS(0);
}/****************************************************************************
**名称 hal_SPI_Stop
**功能 spi停止传输数据设备线拉低
**形参 无
**返回值 无
****************************************************************************/
void hal_SPI_Stop(void)
{hal_SPI_W_SS(1);
}/****************************************************************************
**名称 hal_SPI_SwapByte
**功能 spi交换数据交换一个八位数据
**形参 无
**返回值 无
****************************************************************************/
uint8_t hal_SPI_SwapByte(uint8_t ByteSend) //交换一个八位数据
{uint8_t i, ByteReceive 0x00;for (i 0; i 8; i ){hal_SPI_W_MOSI(ByteSend (0x80 i));hal_SPI_W_SCK(1);if (hal_SPI_R_MISO() 1){ByteReceive | (0x80 i);}hal_SPI_W_SCK(0);}return ByteReceive;
}
SPI在读取数据时为什么我们必须发送虚拟字节Dummy_Bytes才能接收结果 SPI必须生成时钟脉冲才能将数据移出。对于大多数(如果不是全部)SPI主机产生时钟脉冲的唯一方式是发送字节。如果你仔细想想这是有道理的。 总结Dummy_Bytes无实际意义只是为了产生时钟脉冲这样才能读取数据。
W25Q64的通讯格式
FLASH操作注意事项 写入操作前必须先进行写使能每个数据位只能由1改写为0不能由0改写为1写入数据前必须先擦除擦除后所有数据位变为1擦除必须按最小擦除单元进行扇区擦除4096个字节4KB连续写入多字节时最多写入一页数据超过页尾位置的数据会到页首覆盖一页256个字节写入操作后芯片进入忙碌状态不响应新的读写操作看Busy寄存器是否为1 W25Q64的读写数据帧结构 如上起始信号命令地址交换数据结束
整体代码实现
综合上述两点要求得以下代码思路
写操作
在每次写操作开始前都进行写使能结束前进行等待写操作完成 则整个流程为写使能起始信号发送写指令写入地址写入数据结束信号等待写操作完成
/****************************************************************************
**名称 hal_W25Q64_WriteEnable
**功能 spi写使能打开
**形参 无
**返回值 无
****************************************************************************/
void hal_W25Q64_WriteEnable(void) //spi写使能打开
{hal_SPI_Start(); hal_SPI_SwapByte(W25Q64_WRITE_ENABLE); //0x06指令码写使能打开hal_SPI_Stop();
}/****************************************************************************
**名称 hal_W25Q64_WaitBusy
**功能 忙碌位寄存器如果写寄存器在工作就等待没有就很快退出
**形参 无
**返回值 无
****************************************************************************/
void hal_W25Q64_WaitBusy(void) //忙碌位寄存器如果写寄存器在工作就等待没有就很快退出
{uint32_t Timeout;hal_SPI_Start();hal_SPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1); //W25Q64_READ_STATUS_REGISTER_1忙碌标志位地址Timeout 100000;while ((hal_SPI_SwapByte(W25Q64_DUMMY_BYTE) 0x01) 0x01) //忙为1不忙为0{Timeout --;if (Timeout 0){break;}}hal_SPI_Stop();
}/****************************************************************************
**名称 hal_W25Q64_PageProgram
**功能 页写入
**形参 Address写入的地址 DataArray写入数据存放地址 Count写入字节数
**返回值 无
****************************************************************************/
void hal_W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count) //页写入
{uint16_t i;hal_W25Q64_WriteEnable();hal_SPI_Start();hal_SPI_SwapByte(W25Q64_PAGE_PROGRAM); //连续写指令hal_SPI_SwapByte(Address 16); //二十四位地址高八位hal_SPI_SwapByte(Address 8); //地址中间八位hal_SPI_SwapByte(Address); //地址低八位for (i 0; i Count; i ){hal_SPI_SwapByte(DataArray[i]); //连续写入数据}hal_SPI_Stop();hal_W25Q64_WaitBusy(); //等待写入成功
}不过调用写函数时记得先擦除原先的数据
擦除操作
操作步骤写使能起始信号擦除命令擦除地址结束信号等待写完成
/****************************************************************************
**名称 hal_W25Q64_SectorErase
**功能 扇区擦除操作
**形参 Address擦除扇区的地址
**返回值 无
****************************************************************************/
void hal_W25Q64_SectorErase(uint32_t Address) //扇区擦除操作
{hal_W25Q64_WriteEnable(); //写使能hal_SPI_Start(); hal_SPI_SwapByte(W25Q64_SECTOR_ERASE_4KB); //扇区擦除指令码hal_SPI_SwapByte(Address 16); //擦除的地址高8位hal_SPI_SwapByte(Address 8); //擦除的地址中间8位hal_SPI_SwapByte(Address);hal_SPI_Stop();hal_W25Q64_WaitBusy();
}读操作
读操作要注意开头说的她必须交换数据既读取同时要发送一个无用数据 操作步骤起始信号读指令读地址读数据并写入0xff结束信号 /****************************************************************************
**名称 hal_W25Q64_ReadData
**功能 连续读数据
**形参 Address读的首地址 DataArray读出数据存放地址 Count读的字节数
**返回值 无
****************************************************************************/
void hal_W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count) //连续读数据
{uint32_t i;hal_SPI_Start(); hal_SPI_SwapByte(W25Q64_READ_DATA); //读指令hal_SPI_SwapByte(Address 16); //读开始地址hal_SPI_SwapByte(Address 8); hal_SPI_SwapByte(Address);for (i 0; i Count; i ){DataArray[i] hal_SPI_SwapByte(W25Q64_DUMMY_BYTE); //连续读}hal_SPI_Stop();
}