/*************************************
*文件名称:w25x16_spi.c
*
*功能描述:访问和写入数据到闪存w25x16
*
*建立日期:2016-03-16
*
* w25x16
*共8192页*256字节/页=2097152字节
*2097152字节/512个扇区=4096字节/扇区
*
*Block(块)-->Sector(扇区)-->Page(页)-->256(字节)
* 32 512 8192
*************************************/

.H文件的定义

#define W25X16_CS PORTA_OUT(2)   //片选信号

/* w25x16指令 */
#define W25X16_WRITE_ENABLE 0x06
#define W25X16_WRITE_DISABLE 0x04
#define W25X16_READ_DATA 0x03
#define W25X16_READ_QUICK 0x0b
#define W25X16_READ_DOUBLE 0x3b
#define W25X16_READ_STATUS_REG 0x05
#define W25X16_WRITE_STATUS_REG 0x01
#define W25X16_PAGE_PROGRAM 0x02
#define W25X16_SECTOR_ERASE 0x20
#define W25X16_BLOCK_ERASE 0xd8
#define W25X16_CHIP_ERASE 0xc7
#define W25X16_POWER_OFF 0xb9
#define W25X16_POWER_ON 0xab
#define W25X16_DEVICE_ID 0x90
#define W25X16_JEDEC_ID 0x9f
#define W25X16_MANUFACTDEVICE_ID 0x90

.C文件的函数

初始化SPI接口

/*************************************
*文件名称:w25x16_spi.c
*
*功能描述:访问和写入数据到闪存w25x16
*
*建立日期:2016-03-16
*
*FLASH设备名称:w25x16
*共8192页*256字节/页=2097152字节
*2097152字节/512个扇区=4096字节/扇区
*
*Block(块)-->Sector(扇区)-->Page(页)-->256(字节)
* 32 512 8192
*************************************/ mySPI.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_256; //分频
mySPI.SPI_CPHA =SPI_CPHA_2Edge; //第2个跳变沿数据被采样
mySPI.SPI_CPOL =SPI_CPOL_High; //空闲状态为高电平
mySPI.SPI_CRCPolynomial =; //CRC值计算
mySPI.SPI_DataSize =SPI_DataSize_8b; //以1个byte为单位
mySPI.SPI_Direction =SPI_Direction_2Lines_FullDuplex; //双线双向全双工
mySPI.SPI_FirstBit =SPI_FirstBit_MSB; //数据传输从MSB位开始
mySPI.SPI_Mode =SPI_Mode_Master; //设置为主SPI模式
mySPI.SPI_NSS =SPI_NSS_Soft; //NSS信号由软件控制 SPI_Init(SPI1,&mySPI);
SPI_Cmd(SPI1, ENABLE); //使能SPI外设

读取FLASH的ID

u16 w25x16_spi_read_id(void)
{
u16 temp=;
W25X16_CS=; w25x16_spi_read_write_byte(W25X16_DEVICE_ID); //发送指令
w25x16_spi_read_write_byte(0x00);
w25x16_spi_read_write_byte(0x00);
w25x16_spi_read_write_byte(0x00);
temp|=w25x16_spi_read_write_byte(0xff)<<; //送0xff,读取数据
temp|=w25x16_spi_read_write_byte(0xff);
W25X16_CS=; return temp;
}

SPI的读写操作

/*读取一个字节的数据
//_data:要写入的数据
//SPI特性:如果要得到一个数据,则取返回值;如果要写入一个数据,则忽略返回的数据.
*/
u8 w25x16_spi_read_write_byte(u8 _data)
{
u8 temp=; //如果发送区是空的,则最多尝试100次就返回错误
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE == RESET))
{
if(temp++>)
return ;
} SPI_I2S_SendData(SPI1,_data);
temp=; //如果接收区是空的,则最多尝试100次就返回错误
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET)
{
if(temp++>)
return ;
} return SPI_I2S_ReceiveData(SPI1);
}

读取FLASH指定位置的数据

/*读取FLASH中指定位置的数据
//_data :数据存储数组
//_readaddr:要开始读取的flash地址,此地址分3次写入,每次写入8位
//_datasize:要读取的数据大小
*/
void w25x16_spi_read(u8* _data,u32 _readaddr,u16 _datasize)
{
u16 i;
W25X16_CS=;
w25x16_spi_read_write_byte(W25X16_READ_DATA); //发送读数据命令,忽略返回的数据
w25x16_spi_read_write_byte((u8)((_readaddr)>>)); //右移16位,但只取低8位,因为有U8的强制转换
w25x16_spi_read_write_byte((u8)((_readaddr)>>)); //右移8位,还是只取低8位,因为有U8的强制转换
w25x16_spi_read_write_byte((u8)((_readaddr))); //将地址的低8位写入s
for(i=;i<_datasize;i++)
{
_data[i]=w25x16_spi_read_write_byte(0xff); //写空数据,得到指定长度的数据
}
W25X16_CS=;
}

等待FLASH忙信号

/*  等待忙信号  */
void w25x16_spi_wait_busy(void)
{
//寄存器第一位如果还是1,则继续等待,直到0为止
while((w25x16_spi_read_sr()&0x01)==0x01); //w25x16_spi_read_sr()&0x01:取结果的第一位数值
}

写入指定位置的数据

/*  写入指定地址的数据  */
//_data :要写入的数据
//_writeaddr:要写入的地址
//_datasize :要写入的数据大小
void w25x16_spi_write_page(u8* _data,u32 _writeaddr,u16 _datasize)
{
u16 i;
W25X16_CS=;
w25x16_spi_write_enable();
w25x16_spi_read_write_byte(W25X16_PAGE_PROGRAM); //发送指令
w25x16_spi_read_write_byte((u8)((_writeaddr)>>));
w25x16_spi_read_write_byte((u8)((_writeaddr)>>));
w25x16_spi_read_write_byte((u8)_writeaddr);
for(i=;i<_datasize;i++)
w25x16_spi_read_write_byte(_data[i]); W25X16_CS=;
w25x16_spi_wait_busy(); //等待完成操作
}
/**************************************
//根据扇区编号写入数据
//_sectorid:删除编号
//一个扇区有16页,每页256字节.一个扇区共16*256=4096字节
//用页编程模式,每次编程256字节,如果要写4096字节,则要连续编程16次
**************************************/
void w25x16_spi_write_by_sectorid(u16 _sectorid,u8* _data,u32 _datasize)
{
u8 i,write_pages_num; //要写入的满页面的数量,一个页面256字节
u32 write_addr=_sectorid*; //要写入的flash首地址 write_pages_num=_datasize/; //要写入的满页面数量 //首先擦除该删除的数据,擦除后数据为0xff
w25x16_spi_erase_sector(_sectorid); //写入满页的数据
for(i=;i<write_pages_num;i++)
{
w25x16_spi_write_page(((u8*)(_data+i*)),write_addr+i*,); //每次写满256个字节,满页的写入数据
} //写入剩余的数据,如果数据小于256,则直接写入
w25x16_spi_write_page(((u8*)(_data + write_pages_num*)),write_addr + write_pages_num*,_datasize - write_pages_num*); }
/*擦除指定的扇区数据
//_sector_id:扇区编号 0~511
*/
void w25x16_spi_erase_sector(u32 _sector_id)
{
u32 sector_addr=_sector_id*;
w25x16_spi_write_enable();
w25x16_spi_wait_busy();
W25X16_CS=;
myspi_read_write_byte(W25X16_SECTOR_ERASE); //送扇区擦除指令
myspi_read_write_byte((u8)((sector_addr)>>)); //右移16位,用u8强制转换,取D23-D16
myspi_read_write_byte((u8)((sector_addr)>>)); //右移8位,用u8强制转换,取D15-D8
myspi_read_write_byte((u8)sector_addr); //用u8强制转换,取D7-D0
W25X16_CS=;
w25x16_spi_wait_busy();
}

访问FLASH设备-W25X16的更多相关文章

  1. 【驱动】Flash设备驱动基础·NOR·NAND

    Flash存储器 ——>Flash存储器是近几年来发展最快的存储设备,通常也称作闪存.Flash属于EEPROM(电可擦除可编程只读存储器),是一类存取速度很高的存储器. ——>它既有RO ...

  2. Ionic2学习笔记(9):访问本地设备

    作者:Grey 原文地址: http://www.cnblogs.com/greyzeng/p/5559927.html               Ionic2提供了访问本地设备的方法,但是需要安装 ...

  3. win10添加打印机--无法访问指定设备,路径或文件。。

    win10添加打印机无法访问指定设备,路径或文件..后来发现很多按钮点击多说无法访问指定设备,路径或文件.. 解决添加打印机问题: 在搜索栏中搜索:print (从这里添加) 彻底解决: 添加环境变量 ...

  4. ubuntu 下root用户无法访问声音设备的解决方案

    原因:root用户没有对pulsaudio的访问权限,而且pulsaudio默认是不能在root下自动启动解决办法: 一.修改自动启动:编辑 gedit /etc/default/pulseaudio ...

  5. Java访问USB设备

    最近在用Java访问RDing设备,使用的是Java HID API.使用过程中发现一个问题,由于是嵌入式小白,不知道如何向USB设备发送report.于是想到可以看看自带的软件如何访问USB的.找到 ...

  6. vs2015使用Apache Cordova用JavaScript来访问本地设备的功能,比如摄像头、加速计

    看到下面这张图就代表着我VS2015 跨平台Moblie开发工具安装成功了. 上周安装成功后本想一睹跨平台开发的乐趣,可是一直找不到合适的入口.这周又来捯饬一下结果发现了一个入口.于是来写一个Hell ...

  7. ubuntu下virtualbox 共享文件夹 & 访问USB设备

    在Ubuntu 12.04 上为Virtualbox 启用USB 设备支持 Ubuntu安装虚拟机,实现文件和USB的共享 Ubuntu下virtualbox 虚拟xp 访问USB设备

  8. 管理员技术(二): 访问练习用虚拟机、 命令行基础技巧 、 挂载并访问光盘设备、ls列表及文档创建、复制删除移动

    一.访问练习用虚拟机 目标: 学会在教学环境中访问练习用虚拟机,主要完成以下事项: 1> 快速重置教学虚拟机环境       2> 通过“虚拟系统管理器”访问虚拟机       3> ...

  9. Linux应用可通过USB访问Android设备-Chrome OS 75版发布

    导读 谷歌已经为支持的Chromebook设备发布了Chrome OS 75操作系统,这是一个主要版本,增加了各种新功能,最新安全补丁和其他改进. 对于大多数Chromebook设备,Chrome O ...

随机推荐

  1. c++程序编码

    c++程序中涉及到中文字符的输入输出以及其他操作经常会出现乱码.乱码主要是由于程序的源文件编码.可执行文件编码以及程序运行环境的编码不匹配导致.比如,c++源程序文件编码为GB18030, 在源程序中 ...

  2. MFC Socket

    目录 第1章同步TCP通讯    1 1.1 同步通讯与异步通讯    1 1.2 同步通讯类    1 1.3 同步TCP通讯客户端    4 1.3.1 界面    4 1.3.2 界面类声明   ...

  3. Linux源码安装mysql步骤

    创建文件夹: mkdir  /usr/local/webserver 安装必要依赖包      yum -y install gcc gcc-c++ make ncurses-devel安装cmake ...

  4. 【BZOJ 3295】动态逆序对 - 分块+树状数组

    题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...

  5. eclipse 下面的folder,source folder,package的区别与作用

    首先明确一点,folder,source folder,package都是文件夹,既然是文件夹,那么任何的文件都可以往这三种文件夹下面的放.1.他们的区别folder就是普通的文件夹,它和我们wind ...

  6. JavaScript实现冒泡排序

    思想:从第一个元素开始,对数组中两两相邻的元素比较,将值较小的元素放在前面,值较大的元素放在后面,一轮比较完毕,一个最大的数沉底成为数组中的最后一个元素,一些较小的数如同气泡一样上浮一个位置.n个数, ...

  7. C++文件读写练习

    编写一个程序,统计data.txt文件的行数,并将所有行前加上行号后写到data1.txt文件中. 算法提示: 行与行之间以回车符分隔,而getline()函数以回车符作为终止符.因此,可以采用get ...

  8. easyui 中重复加载两次url

    之前一直在使用easyui中,忽视了官网上的小细节,类似于datagrid.combobox 等组件在使用的时候,它的数据加载方式分为两种: 官网中: ①在html中,比如: <table id ...

  9. Word文档增加快捷键

  10. git 将本地项目添加到远程

    git init git add README.md git commit -m "first commit" git remote add origin git@github.c ...