SPI实现SST25VF016B驱动(Flash)
本文在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)相关推荐
- ESPIDF开发ESP32学习笔记【SPI与片外FLASH基础】
文章目录 SPI SPI Master SPI传输时序 Notes on Sending Mixed Transactions to the Same Device SPI传输模式 中断传输 轮询传输 ...
- 第24章 SPI—读写串行FLASH—零死角玩转STM32-F429系列
第24章 SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...
- SPI—读写串行FLASH(时序中的无关项)
SPI-读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 本章 ...
- 乐鑫Esp32学习之旅28 分享在 esp32 SDK实现驱动 Flash W25Q32 的封装,扩大容量存储更多的资源。(开源源码工程)。
本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 系列一:ESP32系列模组基础学习系列笔记 1. 爬坑学习新旅程,虚 ...
- SPI—读写串行FLASH
1 SPI协议简介 SPI协议是由摩托罗拉公司提出的通讯协议(SerialPeripheralInterface),即串行外围设备接口,是一种高速全双工的通信总线.它被广泛地使用在ADC.LCD等设备 ...
- pinctrl虚拟spi的linux驱动,LinuxSPI驱动.md
--- ![](https://b3logfile.com/bing/20190517.jpg?imageView2/1/w/960/h/540/interlace/1/q/100) SPI 驱动框架 ...
- Linux SPI总线设备驱动模型详解
随着技术不断进步,系统的拓扑结构越来越复杂,对热插拔.跨平台移植性的要求越来越高,早期的内核难以满足这些要求,从linux2.6内核开始,引入了总线设备驱动模型.其实在linux2.4总线的概念就已经 ...
- linux spi屏驱动程序,65 linux spi设备驱动之spi LCD屏驱动
SPI的控制器驱动由平台设备与平台驱动来实现. 驱动后用spi_master对象来描述.在设备驱动中就可以通过函数spi_write, spi_read, spi_w8r16, spi_w8r8等函数 ...
- STM32学习之SPI协议(读写FLASH)
关于STM32学习分享 第八章 SPI协议(读写FLASH) 文章目录 关于STM32学习分享 前言 二.代码 1.spi_flash.c 2.spi_flash.h 3.main.c 总结 前言 开 ...
最新文章
- ***如何优雅的选择字体(font-family)
- 使用startForeground让android服务前台运行
- java基础之Object类和异常
- mock模拟接口测试_Python接口测试之mock(中)
- Pat乙级 1049 数列的片段和
- 里怎么做页眉页脚_这年头县城里在家做的电商利润怎么样
- e3是合法浮点数吗_下面4个选项中,均是合法浮点数的选项是?
- Linq to xml 示例分析
- 玩抖音,你喜欢的,都是对自身没好处的
- vs2015 编译时项目出现NuGet程序包还原失败,找不到xxx.xxx.xxx版本的程序包,怎么解决这个问题?
- 获取地球某点最新的磁偏角
- 诗歌九 声律启蒙(云对雨,雪对风,晚照对晴空)
- html登录qq页面无法显示,如何解决QQ可以登录网页而无法打开的问题
- 微信怎样诞生:张小龙给马化腾的一封邮件
- easyui datagrid 可编辑单元格 显示 clear icon 和 放大镜图标
- android app 控制背光,android7.1+msm8937背光控制
- 基于cocos-2dx的游戏制作——I wanna save the princess
- 腾讯云IM回调接口-单聊发言后回调
- YOLOv5-detect
- STM32的AD转换