树莓派读写spi_flash w25q64
·
Flash操作注意事项
3.2.1 写入操作
写入操作前,必须先进行写使能
每个数据位只能由1改写为0,不能由0改写为1(成本和技术原因)
写入数据前必须先擦除,擦除后,所有数据位变为1(Flash有专门的擦除命令,操作时仅需要发送擦除命令即可),在Flash中0FFH代表空白
擦除必须按最小擦除单元(在本芯片中,最小的擦除单元是一个扇区Sector)进行
连续写入多字节时,最多写入一页的数据,超过页尾位置的数据,会回到页首覆盖写入(页缓存器的限制),在写入时,要注意写入的地址范围不能跨越页尾
写入操作结束后,芯片进入忙状态,不响应新的读写操作
3.2.2 读取操作
直接调用读取时序,无需使能,无需额外操作,没有页的限制,读取操作结束后不会进入忙状态,但不能在忙状态时读取

根据读写指令使用ioctl实现flash读写操作
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define RX_TX_MAX 1024
static void pabort(const char *s)
{
perror(s);
abort();
}
typedef unsigned char __u8;
typedef unsigned short __u16;
typedef unsigned int __u32;
static const char *device = "/dev/spidev0.0";
static unsigned char mode = SPI_MODE_0;
static unsigned char bits = 8;
static uint32_t speed = 1000000;
static uint16_t delay;
static char* file_name;
static uint32_t number_byte=0;
static unsigned char read_write_flg=0; //0-read 1-write
int spi_fd;
unsigned char readbuf[1024];
static void dumpstat(const char *name, int fd)
{
__u8 lsb, bits;
__u32 mode, speed;
if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {
perror("SPI rd_mode");
return;
}
if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
perror("SPI rd_lsb_fist");
return;
}
if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
perror("SPI bits_per_word");
return;
}
if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
perror("SPI max_speed_hz");
return;
}
printf("%s: spi mode 0x%x, %d bits %sper word, %d Hz max\n",
name, mode, bits, lsb ? "(lsb first) " : "", speed);
}
static void write_en()
{
int ret;
uint8_t rx[1];
uint8_t tx[1] = {
0x06,
};
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = 1,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
}
static char read_reg1()
{
int ret;
uint8_t rx[2];
uint8_t tx[2]={0x05,0x00,};
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = 2,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);
if (ret < 1)
pabort("can't send spi message");
return rx[1];
}
static void BlockErase64k(int addr)
{
int ret;
uint8_t rx[4];
uint8_t tx[4]={0xd8,0x00,0x00,0x00,};
tx[1] = (addr&0xFF0000) >> 16;
write_en();
while(read_reg1()&0x01==0x01);
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = 4,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);
while(read_reg1()&0x01==0x01);
if (ret < 1)
pabort("can't send spi message");
return ;
}
static void write_data_page(int addr ,char *data,int size)
{
BlockErase64k(addr);
int ret;
int i;
uint8_t rx[256+4];
uint8_t tx[256+4]={0x02,0x00,0x00,0x00,};
tx[1] = (addr&0xFF0000) >> 16;
tx[2] = (addr&0x00FF00) >> 8;
tx[3] = (addr&0xFF);
write_en();
while(read_reg1()&0x01==0x01);
for(i = 0; i < size; i++)
{
tx[i+4] = data[i];
printf("write data[%d]:%x\n",i,tx[4+i]);
}
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = 4+size,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);
if (ret < 1)
pabort("can't send spi message");
while(read_reg1()&0x01==0x01);
}
static unsigned char* read_data(int addr ,int size)
{
int ret;
int i;
uint8_t rx[256+4];
uint8_t tx[4+256]={0x03,0x00,0x00,0x00,};
tx[1] = (addr&0xFF0000) >> 16;
tx[2] = (addr&0x00FF00) >> 8;
tx[3] = (addr&0xFF);
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = size+4,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);
if (ret < 1)
pabort("can't send spi message");
for(i = 0; i < size;i++){
readbuf[i] = rx[i+4];
printf("read data[%d]:%x\n",i,readbuf[i]);
}
printf("read data:%d Byte,first data:%x",size,rx[4]);
return readbuf;
}
static char read_id()
{
int ret;
uint8_t rx[4];
uint8_t tx[4]={0x9f,};
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = 4,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(spi_fd,SPI_IOC_MESSAGE(1),&tr);
if (ret < 1)
pabort("can't send spi message");
printf("id:%x %x\n",rx[2],rx[3]);
return rx[0];
}
int main (int argc,char*argv[])
{
int ret;
char data[4] = {0x01,0x02,0x03,};
spi_fd = open(device,O_RDWR);
if(spi_fd < 0)
pabort("can't open device");
ret = ioctl(spi_fd,SPI_IOC_WR_MODE,&mode);
if(ret < 0)
pabort("can't set device mode");
ret = ioctl(spi_fd,SPI_IOC_RD_BITS_PER_WORD,&bits);
if(ret < 0)
pabort("can't set device mode");
ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
read_id();
write_data_page(0x000000,data,4);
read_data(0x000000,4);
}
接线
![[图片]](https://i-blog.csdnimg.cn/direct/81e72fc08f194d48ad64a29be58a9f35.png)
运行结果

更多推荐



所有评论(0)