加强网站政务服务建设,房地产开发公司招聘,老徐蜂了网站策划书,教育类网站源码目录 需求一、SPI概要二、SPI配置1.开时钟2.配置IO3.配置使能SPI 三、FLash操作函数1.SPI发送数据2.FLASH写使能3.FLASH等待操作完成4.FLASH页写操作5.FLASH读操作6.FLASH扇区擦除 四、需求实现 需求
通过SPI控制FLash进行数据的保存和删除。 一、SPI概要
在我们使用UA… 目录 需求一、SPI概要二、SPI配置1.开时钟2.配置IO3.配置使能SPI 三、FLash操作函数1.SPI发送数据2.FLASH写使能3.FLASH等待操作完成4.FLASH页写操作5.FLASH读操作6.FLASH扇区擦除 四、需求实现 需求
通过SPI控制FLash进行数据的保存和删除。 一、SPI概要
在我们使用UART通用串行异步通讯协议时因为UART没有时钟信号速度不同无法控制何时收发数据。 非要解决这个问题的话需要为UART传输的数据添加起始位和停止位双方波特率还需同步很麻烦比较垃圾。 于是由摩托摩拉公司牵头推出了一种新的通讯总线 SPI:串行外设接口。 SPI是一个高速、全双工、同步的串行通信总线。应用场景OLED屏幕、FLASH存储器、AD转换器 通信方式串行同步全双工人话就是数据在线上按照时间顺序一位一位的传输发送和接收时要在通信时钟的同步下进行数据传输且可以同时发送和接收 该总线就是利用单独的数据线MISO和MOSI和单独的时钟信号线SCK完美解决了收发端的数据完美同步。 接线 MOSI 主设备输出、从设备输入 TX MISO 主设备输入、从设备输出 RX SCK 时钟线 CS 片选信号线 一主多从拉低选择和哪个从机通信 GND 地线 单从机时 多从机时 总结除了SS片选线需要单独备一根线和从机进行一对一的链接其他都可以一对多多个从机接同一个主机接口。 SPI通信模式环形传输发多少收多少。 操作逻辑 1、用时先拉低CS。 2、开始操作发数据收数据。 3、用完后拉高CS。
STM32中SPI接口
二、SPI配置
1.开时钟
打开原理图找到引脚 根据引脚的开SPI2和GPIOB的时钟 //1,开时钟GPIO SPI2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);2.配置IO
MOSISCK复用推挽输出 均需要输出高低电平还是复用功能所以配复用推挽输出 MISO浮空输入 需要接收数据没什么好说的 CS通用推挽输出 由于是主机所以CS当做GPIO配就行软件模式 从机的话配硬件模式 //2,配置IO模式GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Pin GPIO_Pin_12;//CSGPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin GPIO_Pin_13|GPIO_Pin_15;//SCK和MOSIGPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin GPIO_Pin_14;//MISOGPIO_Init(GPIOB,GPIO_InitStruct); GPIO_SetBits(GPIOB,GPIO_Pin_12);//拉高CS避免通信出错最后拉高CS是因为当CS拉低时表示开始传输信号。
3.配置使能SPI 参考手册中的步骤如下 CPHA时钟相位 CPHA0时在时钟的第一个边沿进行采样第二个边沿进行输出 CPHA1时在时钟的第二个边沿进行采样第三个边沿进行输出 CPOL时钟极性 CPOL0时空闲时时钟为低电平 CPOL1时空闲时时钟为高电平
SPI的模式0CPHA0,CPOL0 上升沿采样、下降沿接受SPI的模式1CPHA0,CPOL1 下降沿采样、上升沿接受SPI的模式2CPHA1,CPOL0 下降沿采样、上升沿接受SPI的模式3CPHA1,CPOL1 上升沿采样、下降沿接受 一般能够支持SPI模式0的设备也支持SPI模式3支持模式1的设备也支持模式2。SPI通信没有具体的协议格式格式根据通信对象的要求来定。一般的传输数据时候采用的就是8位进行高位先传还是低位先传传输的速度。这些参数都需要根据通信对象来进行配置。 //2,配置SPISPI_InitStruct.SPI_BaudRatePrescalerSPI_BaudRatePrescaler_2;//时钟分频2SPI_InitStruct.SPI_CPHASPI_CPHA_1Edge;//时钟相位第一个边沿采样SPI_InitStruct.SPI_CPOLSPI_CPOL_Low;//时钟极性 低电平SPI_InitStruct.SPI_CRCPolynomial0x12;//不使用CRC校验参数无意义SPI_InitStruct.SPI_DataSizeSPI_DataSize_8b;//数据宽度8未SPI_InitStruct.SPI_DirectionSPI_Direction_2Lines_FullDuplex;//双线全双工模式SPI_InitStruct.SPI_FirstBitSPI_FirstBit_MSB;//先发高位SPI_InitStruct.SPI_ModeSPI_Mode_Master;//主机模式SPI_InitStruct.SPI_NSSSPI_NSS_Soft;//软件NSS模式SPI_Init(SPI2,SPI_InitStruct);//3,使能SPISPI_Cmd(SPI2,ENABLE);本此SPI配置的对象是FLash需求如下
三、FLash操作函数 本次用到的FLash为W25Q64是华邦存储推出的一款串行FLASH存储芯片。 空间规格 64Mbit 兆位 8Mbyte兆字节 256字节为一页、16页为一扇区、16扇区为一块
地址表示
1.SPI发送数据
由于SPI是环形传输所以发多少我们也要接收多少。 发送判断发送缓冲器空闲标志(TXE)是否为0为0表示正在发此时持续等待数据发完。标志为1表示之前的发送完了空闲下来了。此时就可以开始往DR发数据。 接收判断接收缓冲器非空(RXNE)是否为0为0表示接受缓冲区为空没数据此时持续等待数据到来。标志为1表示数据来了此时就可以开始读DR的数据了。
/******************************************************************函 数 名 称SPI2_SendData*函 数 功 能SPI2发送数据*函 数 形 参SPI2_SendData 发送内容*函 数 返 回SPI2_RecvData 返回收到的数据*作 者ZHT*修 改 日 期xx\xx\xx*******************************************************************/
uint8_t SPI2_SendData(uint8_t SPI2_SendData)
{uint8_t SPI2_RecvData 0;while((SPI2-SR (0x11)) 0);SPI2-DR SPI2_SendData;while((SPI2-SR (0x10)) 0);SPI2_RecvData SPI2-DR;return SPI2_RecvData;
}
2.FLASH写使能
看手册上的时序 得知逻辑 1.先拉低CS。 2.SPI发出06指令。 3.最后拉高CS。
/******************************************************************函 数 名 称Write_Enable*函 数 功 能FLASH写使能操作*函 数 形 参无*函 数 返 回无*作 者ZHT*修 改 日 期xx/xx/xx
*******************************************************************/
void Write_Enable(void)
{//拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12);//发送0x06指令SPI2_SendData(0x06);//拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12);
}
3.FLASH等待操作完成
看手册上的时序 得知逻辑 1.先拉低CS。 2.发送05或35指令。 3.循环往FLash发送数据无所谓什么数据只是为了置换出FLash状态寄存器的值判断寄存器的第0位BUSY是否为0为0时就代表Flash为空闲状态可以执行其他操作。 4.判断结束就拉高CS。
/******************************************************************函 数 名 称Flash_WaitForWriteEnd*函 数 功 能FLASH等待操作完成*函 数 形 参无*函 数 返 回无*作 者ZHT*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_WaitForWriteEnd(void)
{uint8_t recv 0;//拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12);SPI2_SendData(0x05);//发送读取指令do{recv SPI2_SendData(0x55);//循环读取寄存器数据,0x55随便改}while((recv 0x01) SET);//判断寄存器的第0位是否是1//拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12);
}
4.FLASH页写操作
顾名思义就是往FLash中写入一页256Byte的操作。 手册上的时序 得出逻辑 1.由于要进行写操作所以要先进行写使能。 2.拉低CS发送02指令。 3.发送三个字节即24位的地址每次发8位分3次发送。为了告知写入的位置。 4.发送数据,8位8位发最多256。 5.调用FLash等待函数等待写入完成。 6.写入完成后拉高CS。
/******************************************************************函 数 名 称Flash_WritePage*函 数 功 能FLASH页写操作*函 数 形 参Write_Local写入地址 Write_data写入数据 Write_len写入数据长度*函 数 返 回无*作 者ZHT*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_WritePage(uint8_t *Write_data,uint32_t Write_Local,uint16_t Write_len)
{//1,先写使能Write_Enable();//2,拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12);//3,发送命令SPI2_SendData(0x02);//4,发送三个字节地址 add 0x123456SPI2_SendData((Write_Local0xFF0000) 16);SPI2_SendData((Write_Local0x00FF00) 8);SPI2_SendData((Write_Local0x0000FF));while(Write_len--){SPI2_SendData( *Write_data);Write_data;}//5,拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12);//6,等待操作完成Flash_WaitForWriteEnd();
}5.FLASH读操作
手册上的时序 得出逻辑 1.拉低CS发送03指令。 2.发送3字节读取的地址。 3.随便发送1个字节的数据返回值就是要获取的数据。 4.拉高CS。千万不要等待操作完成因为手册里没写
/******************************************************************函 数 名 称Flash_ReadData*函 数 功 能FLASH读操作*函 数 形 参add读取地址 data保存读取数据 len读取数据长度*函 数 返 回无*作 者ZHT*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_ReadData(uint32_t add, uint8_t *data,uint16_t len)
{//1,拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12); //2,发送命令SPI2_SendData(0x03); //3,发送三个字节地址 add 0x123456SPI2_SendData((add0xFF0000) 16);SPI2_SendData((add0x00FF00) 8);SPI2_SendData((add0x0000FF));while(len--){*data SPI2_SendData(0x55);data;}//4,拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12);
}6.FLASH扇区擦除
看时序图 逻辑 1.擦除操作实际上也是写入操作是往Flash中写入0xFF。所以此时也要先开写使能。 2.拉低CS发送指令20。 3.发送三个字节。 4.拉高电平等待操作完成。
/******************************************************************函 数 名 称Flash_SectorErase*函 数 功 能FLASH扇区擦除*函 数 形 参add读取地址*函 数 返 回无*作 者CYM*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_SectorErase(uint32_t add)
{//先写使能Write_Enable();//1,拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12); //2,发送命令SPI2_SendData(0x20); //3,发送三个字节地址 add 0x123456SPI2_SendData(add 16);SPI2_SendData((add0x00FF00) 8);SPI2_SendData((add0x0000FF)); //4,拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12); //5,等待忙标志变0Flash_WaitForWriteEnd();
}四、需求实现
main.c
#include stm32f10x.h
#include usart.h
#include stdio.h
#include delay.h
#include string.h
#include pwm.h
#include adc.h
#include su03t.h
#include dht11.h
#include kqm.h
#include key.h
#include RTC.h
#include bsp_lcd.h
#include wifi.h
#include aliot.h
#include time.h
#include spi.h
#define TestAddr 0x000700
char buff1[20];
int main()
{NVIC_SetPriorityGrouping(5);//两位抢占两位次级Usart1_Config(); SysTick_Config(72000);SPI2_Config();Flash_ReadID();Flash_SectorErase(TestAddr);FLASH_WriteBuffer((u8*)好饿好饿好饿~,TestAddr,300);printf(写数据后\r\n);Flash_ReadData(TestAddr,buff1,300);printf(FLASH:%s\r\n,buff1);Flash_SectorErase(TestAddr);printf(清数据后\r\n);Flash_ReadData(TestAddr,buff1,300);printf(FLASH:%s\r\n,buff1);FLASH_WriteBuffer((u8*)好饿好饿好饿~,TestAddr,300);printf(重写数据后\r\n);Flash_ReadData(TestAddr,buff1,300);printf(FLASH:%s\r\n,buff1);while(1){ if(ledcnt[0]ledcnt[1])//2S一次{ledcnt[0]0;printf(FLASH:%s\r\n,buff1);}}return 0;
}
spi.c
#include spi.h
#define sFLASH_SPI_PAGESIZE 0x100
/******************************************************************函 数 名 称SPI2_Config*函 数 功 能初始化SPI2*函 数 形 参无*函 数 返 回无*作 者ZHT*修 改 日 期xx\xx\xx*******************************************************************/
void SPI2_Config()
{
#if 0//1,开时钟GPIO SPI2 代码简短但不直观RCC-APB2ENR | 13;RCC-APB1ENR | 114;//2,配置IO模式GPIOB-CRH ~(0xFFFF16);GPIOB-CRH | 0xB4B316;//配置4个IO口的模式 1011GPIOB-ODR | 0x112;//拉高PB12避免对通信产生影响//3,配置SPISPI2-CR1 | 0x0244;//配置SPI工作模式#elseGPIO_InitTypeDef GPIO_InitStruct{0};SPI_InitTypeDef SPI_InitStruct{0};//1,开时钟GPIO SPI2 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);//2,配置IO模式GPIO_InitStruct.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Pin GPIO_Pin_12;//CSGPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin GPIO_Pin_13|GPIO_Pin_15;//SCK和MOSIGPIO_InitStruct.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOB,GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin GPIO_Pin_14;//MISOGPIO_Init(GPIOB,GPIO_InitStruct); GPIO_SetBits(GPIOB,GPIO_Pin_12);//拉高CS避免通信出错//2,配置SPISPI_InitStruct.SPI_BaudRatePrescalerSPI_BaudRatePrescaler_2;//时钟分频2SPI_InitStruct.SPI_CPHASPI_CPHA_1Edge;//时钟相位第一个边沿采样SPI_InitStruct.SPI_CPOLSPI_CPOL_Low;//时钟极性 低电平SPI_InitStruct.SPI_CRCPolynomial0x12;//不使用CRC校验参数无意义SPI_InitStruct.SPI_DataSizeSPI_DataSize_8b;//数据宽度8未SPI_InitStruct.SPI_DirectionSPI_Direction_2Lines_FullDuplex;//双线全双工模式SPI_InitStruct.SPI_FirstBitSPI_FirstBit_MSB;//先发高位SPI_InitStruct.SPI_ModeSPI_Mode_Master;//主机模式SPI_InitStruct.SPI_NSSSPI_NSS_Soft;//软件NSS模式SPI_Init(SPI2,SPI_InitStruct);//3,使能SPISPI_Cmd(SPI2,ENABLE);#endif
}/******************************************************************函 数 名 称SPI2_SendData*函 数 功 能SPI2发送数据*函 数 形 参SPI2_SendData 发送内容*函 数 返 回SPI2_RecvData 返回收到的数据*作 者ZHT*修 改 日 期xx\xx\xx*******************************************************************/
uint8_t SPI2_SendData(uint8_t SPI2_SendData)
{uint8_t SPI2_RecvData 0;while((SPI2-SR (0x11)) 0);SPI2-DR SPI2_SendData;while((SPI2-SR (0x10)) 0);SPI2_RecvData SPI2-DR;return SPI2_RecvData;
}/************************SPI-FLASH********************************/
/******************************************************************函 数 名 称Write_Enable*函 数 功 能FLASH写使能操作*函 数 形 参无*函 数 返 回无*作 者ZHT*修 改 日 期xx/xx/xx
*******************************************************************/
void Write_Enable(void)
{//拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12);//发送0x06指令SPI2_SendData(0x06);//拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12);
}/******************************************************************函 数 名 称Flash_WaitForWriteEnd*函 数 功 能FLASH等待操作完成*函 数 形 参无*函 数 返 回无*作 者CYM*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_WaitForWriteEnd(void)
{uint8_t recv 0;//拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12);SPI2_SendData(0x05);//发送读取指令do{recv SPI2_SendData(0x55);//循环读取寄存器数据,0x55随便改}while((recv 0x01) SET);//判断寄存器的第0位是否是1//拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12);
}/******************************************************************函 数 名 称Flash_WritePage*函 数 功 能FLASH页写操作*函 数 形 参Write_Local写入地址 Write_data写入数据 Write_len写入数据长度*函 数 返 回无*作 者CYM*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_WritePage(uint8_t *Write_data,uint32_t Write_Local,uint16_t Write_len)
{//1,先写使能Write_Enable();//2,拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12);//3,发送命令SPI2_SendData(0x02);//4,发送三个字节地址 add 0x123456SPI2_SendData((Write_Local0xFF0000) 16);SPI2_SendData((Write_Local0x00FF00) 8);SPI2_SendData((Write_Local0x0000FF));while(Write_len--){SPI2_SendData( *Write_data);Write_data;}//5,拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12);//6,等待操作完成Flash_WaitForWriteEnd();
}/******************************************************************函 数 名 称Flash_ReadData*函 数 功 能FLASH读操作*函 数 形 参add读取地址 data保存读取数据 len读取数据长度*函 数 返 回无*作 者CYM*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_ReadData(uint32_t add, uint8_t *data,uint16_t len)
{//1,拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12); //2,发送命令SPI2_SendData(0x03); //3,发送三个字节地址 add 0x123456SPI2_SendData((add0xFF0000) 16);SPI2_SendData((add0x00FF00) 8);SPI2_SendData((add0x0000FF));while(len--){*data SPI2_SendData(0x55);data;}//4,拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12);
}
/******************************************************************函 数 名 称Flash_SectorErase*函 数 功 能FLASH扇区擦除*函 数 形 参add读取地址*函 数 返 回无*作 者CYM*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_SectorErase(uint32_t add)
{//先写使能Write_Enable();//1,拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12); //2,发送命令SPI2_SendData(0x20); //3,发送三个字节地址 add 0x123456SPI2_SendData(add 16);SPI2_SendData((add0x00FF00) 8);SPI2_SendData((add0x0000FF)); //4,拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12); //5,等待忙标志变0Flash_WaitForWriteEnd();
}
/******************************************************************函 数 名 称Flash_ReadID*函 数 功 能FLASH读取ID*函 数 形 参无*函 数 返 回无*作 者ZHT*修 改 日 期xx/xx/xx
*******************************************************************/
void Flash_ReadID(void)
{uint32_t Temp 0, Temp0 0, Temp1 0, Temp2 0;//1,拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12); SPI2_SendData(0x9F);Temp0 SPI2_SendData(0x55);Temp1 SPI2_SendData(0x55);Temp2 SPI2_SendData(0x55);GPIO_SetBits(GPIOB,GPIO_Pin_12); Temp (Temp0 16) | (Temp1 8) | Temp2;printf(FLASH_ID:%x\r\n,Temp);
}/******************************************************************函 数 名 称Flash_ChipClean*函 数 功 能全片擦除*函 数 形 参无*函 数 返 回无*作 者ZHT*修 改 日 期xx\xx\xx*******************************************************************/
void Flash_ChipClean()
{//先写使能Write_Enable();//1,拉低CSGPIO_ResetBits(GPIOB,GPIO_Pin_12); //2,发送命令SPI2_SendData(0x60); //4,拉高CSGPIO_SetBits(GPIOB,GPIO_Pin_12); Flash_WaitForWriteEnd();
}/******************************************************************函 数 名 称FLASH_WriteBuffer*函 数 功 能随意写入*函 数 形 参uint8_t* pBuffer指向要写入数据的缓冲区的指针。uint32_t WriteAddr写入数据的起始地址。uint16_t NumByteToWrite要写入的字节数。*函 数 返 回无*作 者ZHT*修 改 日 期xx\xx\xx*******************************************************************/void FLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{uint8_t NumOfPage 0,NumOfSingle 0,Addr 0,count 0,temp 0;
// 整页的数量 不足一页的剩余字节数 起始地址偏移 当前页剩余可写入的字节数 临时变量用于存储超出当前页的字节数Addr WriteAddr % 256;count 0x100 - Addr;NumOfPage NumByteToWrite / 256;NumOfSingle NumByteToWrite % 256;if (Addr 0) /*! WriteAddr is sFLASH_PAGESIZE aligned */{if (NumOfPage 0) /*! NumByteToWrite sFLASH_PAGESIZE */{Flash_WritePage(pBuffer, WriteAddr, NumByteToWrite);}else /*! NumByteToWrite sFLASH_PAGESIZE */{while (NumOfPage--){Flash_WritePage(pBuffer, WriteAddr, 256);WriteAddr 256;pBuffer 256;}Flash_WritePage(pBuffer, WriteAddr, NumOfSingle);}}else /*! WriteAddr is not sFLASH_PAGESIZE aligned */{if (NumOfPage 0) /*! NumByteToWrite sFLASH_PAGESIZE */{if (NumOfSingle count) /*! (NumByteToWrite WriteAddr) sFLASH_PAGESIZE */{temp NumOfSingle - count;Flash_WritePage(pBuffer, WriteAddr, count);WriteAddr count;pBuffer count;Flash_WritePage(pBuffer, WriteAddr, temp);}else{Flash_WritePage(pBuffer, WriteAddr, NumByteToWrite);}}else /*! NumByteToWrite sFLASH_PAGESIZE */{NumByteToWrite - count;NumOfPage NumByteToWrite / 256;NumOfSingle NumByteToWrite % 256;Flash_WritePage(pBuffer, WriteAddr, count);WriteAddr count;pBuffer count;while (NumOfPage--){Flash_WritePage(pBuffer, WriteAddr, 256);WriteAddr 256;pBuffer 256;}if (NumOfSingle ! 0){Flash_WritePage(pBuffer, WriteAddr, NumOfSingle);}}}
}void sFLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{uint8_t NumOfPage 0, NumOfSingle 0, Addr 0, count 0, temp 0;Addr WriteAddr % sFLASH_SPI_PAGESIZE;count sFLASH_SPI_PAGESIZE - Addr;NumOfPage NumByteToWrite / sFLASH_SPI_PAGESIZE;NumOfSingle NumByteToWrite % sFLASH_SPI_PAGESIZE;if (Addr 0) /*! WriteAddr is sFLASH_PAGESIZE aligned */{if (NumOfPage 0) /*! NumByteToWrite sFLASH_PAGESIZE */{Flash_WritePage(pBuffer, WriteAddr, NumByteToWrite);}else /*! NumByteToWrite sFLASH_PAGESIZE */{while (NumOfPage--){Flash_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);WriteAddr sFLASH_SPI_PAGESIZE;pBuffer sFLASH_SPI_PAGESIZE;}Flash_WritePage(pBuffer, WriteAddr, NumOfSingle);}}else /*! WriteAddr is not sFLASH_PAGESIZE aligned */{if (NumOfPage 0) /*! NumByteToWrite sFLASH_PAGESIZE */{if (NumOfSingle count) /*! (NumByteToWrite WriteAddr) sFLASH_PAGESIZE */{temp NumOfSingle - count;Flash_WritePage(pBuffer, WriteAddr, count);WriteAddr count;pBuffer count;Flash_WritePage(pBuffer, WriteAddr, temp);}else{Flash_WritePage(pBuffer, WriteAddr, NumByteToWrite);}}else /*! NumByteToWrite sFLASH_PAGESIZE */{NumByteToWrite - count;NumOfPage NumByteToWrite / sFLASH_SPI_PAGESIZE;NumOfSingle NumByteToWrite % sFLASH_SPI_PAGESIZE;Flash_WritePage(pBuffer, WriteAddr, count);WriteAddr count;pBuffer count;while (NumOfPage--){Flash_WritePage(pBuffer, WriteAddr, sFLASH_SPI_PAGESIZE);WriteAddr sFLASH_SPI_PAGESIZE;pBuffer sFLASH_SPI_PAGESIZE;}if (NumOfSingle ! 0){Flash_WritePage(pBuffer, WriteAddr, NumOfSingle);}}}
}
spi.h
#ifndef __SPI_H
#define __SPI_H#include stm32f10x.h
#include stdio.hvoid SPI2_Config();
void Flash_WritePage(uint8_t *Write_data,uint32_t Write_Local,uint16_t Write_len);
void Flash_ReadData(uint32_t add, uint8_t *data,uint16_t len);
void Flash_SectorErase(uint32_t add);
void Flash_ReadID(void);
void Flash_WaitForWriteEnd(void);
void Flash_ChipClean();
void FLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
void sFLASH_WriteBuffer(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
#endif