本文在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. ***如何优雅的选择字体(font-family)
  2. 使用startForeground让android服务前台运行
  3. java基础之Object类和异常
  4. mock模拟接口测试_Python接口测试之mock(中)
  5. Pat乙级 1049 数列的片段和
  6. 里怎么做页眉页脚_这年头县城里在家做的电商利润怎么样
  7. e3是合法浮点数吗_下面4个选项中,均是合法浮点数的选项是?
  8. Linq to xml 示例分析
  9. 玩抖音,你喜欢的,都是对自身没好处的
  10. vs2015 编译时项目出现NuGet程序包还原失败,找不到xxx.xxx.xxx版本的程序包,怎么解决这个问题?
  11. 获取地球某点最新的磁偏角
  12. 诗歌九 声律启蒙(云对雨,雪对风,晚照对晴空)
  13. html登录qq页面无法显示,如何解决QQ可以登录网页而无法打开的问题
  14. 微信怎样诞生:张小龙给马化腾的一封邮件
  15. easyui datagrid 可编辑单元格 显示 clear icon 和 放大镜图标
  16. android app 控制背光,android7.1+msm8937背光控制
  17. 基于cocos-2dx的游戏制作——I wanna save the princess
  18. 腾讯云IM回调接口-单聊发言后回调
  19. YOLOv5-detect
  20. STM32的AD转换

热门文章

  1. html button去除默认样式
  2. 进制转换(二进制,八进制,十进制)
  3. LearnOpenGL->光照->投光物/多光源
  4. 游戏html登录注册,HTML5 点击开锁小游戏(反应能力测试)
  5. 咱们老百姓,今儿个真高兴
  6. 创建银行账户,实现存款,取款,转账(正解)
  7. 星际争霸2免修改器修改绝对一劳永逸
  8. powerCenter介绍
  9. PHP 运行方式详解
  10. Doxygen 配置