本文在STM32F103上实现SSH25的驱动,实现数据的写入和读取:

1:此驱动未加擦除时候是否擦除成功的判断,一般写入FLASH不成功的最大原因就是擦除不成功,所以一般特选FLASH里面的一个地址存储一个特征字,比如0x12,当执行完操作擦除命令后,去判断这个特征字是否被擦除为0xff,如果擦除成功,执行写指令,当然,也可以进行CRC校验,判断写入和读取的是否一致;

2:FLASH的写入时,避免被中断打断;

main.c

#include "stdio.h"
#include "sys.h"
#include "USART_Init.h"
#include "SST25_SPI_Init.h"u8 SSH_Buff[20];
u32 baud_menu[] = {1200,2400,3840,4800,5760,9600,19200,115200};
u16 ARR = 0;int main()
{NVIC_Configuration();                    //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 delay_init();                            //延时函数初始化Usart_Init(9600);                         //串口初始化 Spi_Init();                              //SPI1/SSH25初始化Write_State_Register(0X00);              //写状态寄存器为0x00,取消写保护,上电默认全片保护Block_Clear(Clear_4_K,10);               //擦除4K扇区Write_Mul_Byte(0,"sunshine",8);          //将"sunshine"字符串写入扇区0       Read_Data(0,8,SSH_Buff);                 //将扇区0开始8个字节读进SSH_BuffUsart_Send_Data(SSH_Buff,8);             //发送串口打印delay_ms(1000);
}

SSH_SPI_Init.h

#ifndef SSH25
#define SSH25#include <stm32f10x.h>
#include "delay.h"extern u8 ID[3];typedef enum
{Clear_4_K = 0,Clear_32_K = 1,Clear_64_K = 2,Clear_ALL_FLASH = 3,
}Block_Cnt;#define CS_LOW()  GPIO_ResetBits(GPIOC, GPIO_Pin_4)
#define CS_HIGH() GPIO_SetBits(GPIOC,GPIO_Pin_4)/*未使用*/
#define HOLD_LOW()
#define HOLD_HIGH() /*未使用*/
#define WP_LOW()
#define WP_HIGH()//函数申明
void Spi_Init(void);
u8 Read_State_Register(void);
void Wait_Busy_Clear(void);
void Write_State_Register(u8 dat);
void Write_Enable(void);
void Write_Disable(void);
void Read_Data(long add,u16 cnt,u8 *buff);
void Read_High_Speed_Data(u32 add,u16 cnt,u8 *buff);
void Write_Byte(u32 add,u8 dat);
void Write_Mul_Byte(u32 add,u8 *buff,u32 cnt);
void Block_Clear(Block_Cnt flag,u32 add);
void Read_ID(void);
void Write_Protect_Func(void);
void Hold_Func(u8 flag);#endif

SSH25_SPI_Init.c

#include "SST25_SPI_Init.h"//SPI初始化
void Spi_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;                       //定义gpio结构体  SPI_InitTypeDef SPI_InitStruct;                         //SPI结构体初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);    //使能GPIOB口时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,  ENABLE ); //SPI2时钟使能     //GPIO结构体初始化GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;            //GPIO复用推挽 GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  //SPI2_NSS复用 启用软件从设备管理 NSS引脚上的电平由SI位确定GPIO_Init(GPIOA,&GPIO_InitStruct);     //CS片选GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;GPIO_InitStruct.GPIO_Speed =GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(GPIOC, &GPIO_InitStruct);GPIO_SetBits(GPIOC,GPIO_Pin_4);//SPI结构体初始化SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;SPI_InitStruct.SPI_CRCPolynomial = 7;SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;                             //启动软件从设备管理SPI_Init(SPI1,&SPI_InitStruct); SPI_Cmd(SPI1,ENABLE);                                               //spi2使能
}/*SST25发送一个字节的数据*/
u8 SST25_Send_Byte(u8 dat)
{while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);SPI_I2S_SendData(SPI1,dat);while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);return SPI_I2S_ReceiveData(SPI1);
}/*SST25读取一个字节的数据*/
u8 SST25_Receive_Byte()
{return SST25_Send_Byte(0xff);
}/*读状态寄存器*/
u8 Read_State_Register()
{u8 flag = 0;CS_LOW();                //使能片选信号SST25_Send_Byte(0x05);   //发送读状态寄存器操作码0x05*/flag = SST25_Receive_Byte();CS_HIGH();               //禁止片选信号 return flag;
}/*等待内部擦除或者编程操作结束*/
void Wait_Busy_Clear()
{while((Read_State_Register()&0x01) != 0x00);
}/*写状态寄存器*/
void Write_State_Register(u8 dat)
{CS_LOW();                //使能片选信号SST25_Send_Byte(0x50);   //发送写状态寄存器使能操作码0x50 CS_HIGH();               //禁止片选信号 CS_LOW();                //使能片选信号SST25_Send_Byte(0x01);   //发送写状态寄存器操作码0x01 SST25_Send_Byte(dat);   //写状态寄存器为0x00CS_HIGH();               //禁止片选信号 Wait_Busy_Clear();
}/*写使能操作*/
void Write_Enable()
{CS_LOW();                //使能片选信号SST25_Send_Byte(0x06);   //发送写使能操作码0x06CS_HIGH();               //禁止片选信号
}/*写禁止操作*/
void Write_Disable()
{CS_LOW();                //使能片选信号SST25_Send_Byte(0x04);   //发送写使能操作码0x04CS_HIGH();               //禁止片选信号
}/*读操作*/
void Read_Data(long add,u16 cnt,u8 *buff)
{CS_LOW();                //使能片选信号SST25_Send_Byte(0x03);   //发送写使能操作码0x03 SST25_Send_Byte(add>>16);//发送存储地址,24位SST25_Send_Byte(add>>8); //发送存储地址,24位SST25_Send_Byte(add);    //发送存储地址,24位for(;cnt>0;cnt--)*(buff++) = SST25_Receive_Byte();CS_HIGH();               //禁止片选信号
}/*高速读*/
void Read_High_Speed_Data(u32 add,u16 cnt,u8 *buff)
{CS_LOW();                //使能片选信号SST25_Send_Byte(0x0b);   //发送写使能操作码0x0bSST25_Send_Byte(add>>16);//发送存储地址,24位SST25_Send_Byte(add>>8); //发送存储地址,24位SST25_Send_Byte(add);    //发送存储地址,24位 SST25_Send_Byte(0x00);   //发送一个空周期 for(;cnt>0;cnt--)*(buff++) = SST25_Receive_Byte();CS_HIGH();               //禁止片选信号
}/*写单个字节操作,字节编程*/
void Write_Byte(u32 add,u8 dat)
{Write_Enable();          //写使能CS_LOW();                //使能片选信号SST25_Send_Byte(0x02);   //发送字节编程操作码0x02*/ SST25_Send_Byte(add>>16);//发送存储地址,24位SST25_Send_Byte(add>>8); //发送存储地址,24位SST25_Send_Byte(add);    //发送存储地址,24位 SST25_Send_Byte(dat);    //发送写入的数据 CS_HIGH();               //禁止片选信号 Wait_Busy_Clear();
}/*写多个字节操作,AAI编程*/
void Write_Mul_Byte(u32 add,u8 *buff,u32 cnt)
{u32 i = 0;Write_Enable();          //写使能CS_LOW();                //使能片选信号SST25_Send_Byte(0xad);   //发送AAI编程操作码0xad*/ SST25_Send_Byte(add>>16);//发送存储地址,24位SST25_Send_Byte(add>>8); //发送存储地址,24位SST25_Send_Byte(add);    //发送存储地址,24位 SST25_Send_Byte(buff[0]);//发送写入的数据 SST25_Send_Byte(buff[1]);//发送写入的数据 CS_HIGH();               //禁止片选信号 i = 2;while(i<cnt){delay_us(10);CS_LOW();                //使能片选信号SST25_Send_Byte(0xad);   //发送AAI编程操作码0xad*/ SST25_Send_Byte(buff[i++]);//发送写入的数据 SST25_Send_Byte(buff[i++]);//发送写入的数据 CS_HIGH();               //禁止片选信号 }delay_us(10);Write_Disable();           //退出AAI模式 delay_us(10);Wait_Busy_Clear();         //等待写结束
}/*4k扇区擦除或者32k块擦除或者64k块擦除*/
void Block_Clear(Block_Cnt flag,u32 add)
{if(flag == 0){Write_Enable();          //写使能CS_LOW();                //使能片选信号 SST25_Send_Byte(0x20);   //发送扇区擦除操作码0x20 SST25_Send_Byte(add>>16);//发送存储地址,24位SST25_Send_Byte(add>>8); //发送存储地址,24位SST25_Send_Byte(add);    //发送存储地址,24位 CS_HIGH();               //禁止片选信号 Wait_Busy_Clear();       //等待写结束 }elseif(flag == 1)              //32K块擦除{Write_Enable();          //写使能CS_LOW();                //使能片选信号 SST25_Send_Byte(0x52);   //发送32K块擦除操作码0x52SST25_Send_Byte(add>>16);//发送存储地址,24位SST25_Send_Byte(add>>8); //发送存储地址,24位SST25_Send_Byte(add);    //发送存储地址,24位 CS_HIGH();               //禁止片选信号 Wait_Busy_Clear();       //等待写结束 }elseif(flag == 2)              //64K块擦除 {Write_Enable();          //写使能CS_LOW();                //使能片选信号 SST25_Send_Byte(0xd8);   //发送64K块擦除操作码0xd8SST25_Send_Byte(add>>16);//发送存储地址,24位SST25_Send_Byte(add>>8); //发送存储地址,24位SST25_Send_Byte(add);    //发送存储地址,24位 CS_HIGH();               //禁止片选信号 Wait_Busy_Clear();       //等待写结束 }elseif(flag == 3)              //全部擦除 {Write_Enable();          //写使能CS_LOW();                //使能片选信号 SST25_Send_Byte(0x60);   //发送64K块擦除操作码0x60/0xc7SST25_Send_Byte(add>>16);//发送存储地址,24位SST25_Send_Byte(add>>8); //发送存储地址,24位SST25_Send_Byte(add);    //发送存储地址,24位 CS_HIGH();               //禁止片选信号 Wait_Busy_Clear();       //等待写结束 }
}u8 ID[3];
/*读设备ID*/
void Read_ID()
{CS_LOW();                     //使能片选信号 SST25_Send_Byte(0x9f);        //读ID指令ID[0] = SST25_Receive_Byte(); //获取IDID[1] = SST25_Receive_Byte(); ID[2] = SST25_Receive_Byte();    CS_HIGH();                    //禁止片选信号
}/*写保护函数*/
void Write_Protect_Func()
{Write_State_Register(0x80);   //BPL位为1WP_LOW();                     //写保护使能位拉低,BP0-BP4默认为高,只能读内存,不能写
}
/*保持操作*/
void Hold_Func(u8 flag)
{if(flag == ENABLE)HOLD_LOW();             //拉低HOLD引脚,开始保持elseif(flag == DISABLE)HOLD_HIGH();            //拉高HOLD引脚,保持结束
}

SPI实现SST25VF016B驱动(Flash)相关推荐

  1. ESPIDF开发ESP32学习笔记【SPI与片外FLASH基础】

    文章目录 SPI SPI Master SPI传输时序 Notes on Sending Mixed Transactions to the Same Device SPI传输模式 中断传输 轮询传输 ...

  2. 第24章 SPI—读写串行FLASH—零死角玩转STM32-F429系列

    第24章     SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...

  3. SPI—读写串行FLASH(时序中的无关项)

    SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 本章 ...

  4. 乐鑫Esp32学习之旅28 分享在 esp32 SDK实现驱动 Flash W25Q32 的封装,扩大容量存储更多的资源。(开源源码工程)。

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 系列一:ESP32系列模组基础学习系列笔记 1. 爬坑学习新旅程,虚 ...

  5. SPI—读写串行FLASH

    1 SPI协议简介 SPI协议是由摩托罗拉公司提出的通讯协议(SerialPeripheralInterface),即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在ADC.LCD等设备 ...

  6. pinctrl虚拟spi的linux驱动,LinuxSPI驱动.md

    --- ![](https://b3logfile.com/bing/20190517.jpg?imageView2/1/w/960/h/540/interlace/1/q/100) SPI 驱动框架 ...

  7. Linux SPI总线设备驱动模型详解

    随着技术不断进步,系统的拓扑结构越来越复杂,对热插拔.跨平台移植性的要求越来越高,早期的内核难以满足这些要求,从linux2.6内核开始,引入了总线设备驱动模型.其实在linux2.4总线的概念就已经 ...

  8. linux spi屏驱动程序,65 linux spi设备驱动之spi LCD屏驱动

    SPI的控制器驱动由平台设备与平台驱动来实现. 驱动后用spi_master对象来描述.在设备驱动中就可以通过函数spi_write, spi_read, spi_w8r16, spi_w8r8等函数 ...

  9. STM32学习之SPI协议(读写FLASH)

    关于STM32学习分享 第八章 SPI协议(读写FLASH) 文章目录 关于STM32学习分享 前言 二.代码 1.spi_flash.c 2.spi_flash.h 3.main.c 总结 前言 开 ...

最新文章

  1. java随机输出10计算题
  2. Python中json模块,字典和字符串相互转换
  3. UCloud想吃科创板的“第一个螃蟹”
  4. python练习12
  5. MHT格式文件更换默认图标及打开后显示乱码的问题
  6. 牛客IOI周赛26-提高组(逆序对,对序列,未曾设想的道路) 题解
  7. java反显是什么_卡西欧反显是什么意思
  8. 简单分布式系统构建知识
  9. webpack 生产环境下插件用途
  10. 孔浩老师SpringMVC视频总结
  11. 近义词替换-近义词替换器-免费近义词替换器
  12. Lattice Diamond 学习总结---“疑难杂症”杂篇
  13. JavaScript中的文档碎片
  14. Linux实验13_进程管理及任务计划.docx
  15. A*算法————传教士和野人
  16. Kali 渗透测试:基于结构化异常处理的渗透-使用Python编写渗透模块
  17. Oracle 19c VLDB and Partitioning Guide 第2章:Partitioning Concepts 读书笔记
  18. win7资源管理器经常崩溃shellext.dll_unloaded
  19. 强连接运营社张强:一篇文章带你读懂私域流量的本质和玩法
  20. Tensorflow之pb文件分析

热门文章

  1. Codeforces Round#466 E. Cashback
  2. HTML中对字体颜色稀色,平面设计之版式设计中常用到的对比手法
  3. mysql MYSQL远程访问 授权IP
  4. ABAP---BDC批导入
  5. redis命中率不高问题排查
  6. html按钮相对位置,html相对定位绝对定位
  7. 企业网络安全问题的痛点分析
  8. Perceptron(感知机与径向基)
  9. crontab 每5秒钟执行一次
  10. 反复折叠纸张 java_将一张无限宽的纸折叠100次会怎样!