准备:
开启树莓派spi功能:
执行:sudo raspi-config
上图的网络标号括号内对应树莓派排针的引脚序号。
接下来直接贴代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define RX_TX_MAX 1024
static void pabort(const char *s)
{
perror(s);
abort();
}
static const char *device = "/dev/spidev0.0";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 1000000;
static uint16_t delay;
static char* file_name;
static uint32_t number_byte=0;
static uint8_t read_write_flg=0; //0-read 1-write
int spi_fd;
static void read_date(int addr,char *buff,int size)
{
int ret,i;
uint8_t rx[RX_TX_MAX];
uint8_t tx[RX_TX_MAX] = {
0x03, 0x00, 0x00, 0x00,0x00,
};
tx[1]=(addr&0xFF0000)>>16;
tx[2]=(addr&0xFF00)>>8;
tx[3]=addr&0xFF;
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = size+4,
.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");
for(i=0;i>16;
write_en(spi_fd);
while(read_reg1(spi_fd)&0x01==0x01);
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = 4,
.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");
while(read_reg1(spi_fd)&0x01==0x01);
}
static void write_data_page(int addr,char *tx_buff,int size)
{
int ret,i;
uint8_t rx[256+4];
char tx[256+4];
tx[0] =0x02;
tx[1]=(addr&0xFF0000)>>16;
tx[2]=(addr&0xFF00)>>8;
tx[3]=addr&0xFF;
write_en(spi_fd);
for(i=0;i<256;i++)
{
tx[4+i]=tx_buff[i];
}
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = size+4,
.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");
while(read_reg1(spi_fd)&0x01==0x01);
}
static void print_usage(const char *prog)
{
printf("Usage: %s [-DsbdlHOLC3]\n", prog);
puts(" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
" -d --delay delay (usec)\n"
" -b --bpw bits per word \n"
" -r --read read img \n"
" -w --writ write img \n"
" -n --number Number of bytes read or written \n"
" -l --loop loopback\n"
" -H --cpha clock phase\n"
" -O --cpol clock polarity\n"
" -L --lsb least significant bit first\n"
" -C --cs-high chip select active high\n"
" -3 --3wire SI/SO signals shared\n");
exit(1);
}
static void parse_opts(int argc, char *argv[])
{
while (1) {
static const struct option lopts[] = {
{ "device", 1, 0, 'D' },
{ "speed", 1, 0, 's' },
{ "delay", 1, 0, 'd' },
{ "bpw", 1, 0, 'b' },
{ "read", 1, 0, 'r' },
{ "write", 1, 0, 'w' },
{ "number", 1, 0, 'n' },
{ "loop", 0, 0, 'l' },
{ "cpha", 0, 0, 'H' },
{ "cpol", 0, 0, 'O' },
{ "lsb", 0, 0, 'L' },
{ "cs-high", 0, 0, 'C' },
{ "3wire", 0, 0, '3' },
{ "no-cs", 0, 0, 'N' },
{ "ready", 0, 0, 'R' },
{ NULL, 0, 0, 0 },
};
int c;
c = getopt_long(argc, argv, "D:s:d:b:r:w:n:lHOLC3NR", lopts, NULL);
if (c == -1)
break;
switch (c) {
case 'D':
device = optarg;
break;
case 's':
speed = atoi(optarg);
break;
case 'd':
delay = atoi(optarg);
break;
case 'b':
bits = atoi(optarg);
break;
case 'r':
read_write_flg =1;
file_name =optarg;
printf("file %s\n",file_name);
break;
case 'w':
read_write_flg =2;
file_name = optarg;
break;
case 'n':
number_byte = atoi(optarg);
break;
case 'l':
mode |= SPI_LOOP;
break;
case 'H':
mode |= SPI_CPHA;
break;
case 'O':
mode |= SPI_CPOL;
break;
case 'L':
mode |= SPI_LSB_FIRST;
break;
case 'C':
mode |= SPI_CS_HIGH;
break;
case '3':
mode |= SPI_3WIRE;
break;
case 'N':
mode |= SPI_NO_CS;
break;
case 'R':
mode |= SPI_READY;
break;
default:
print_usage(argv[0]);
break;
}
}
}
void write_img()
{
FILE *file = fopen(file_name,"rb");
if(file==0)
{
printf("open error for \"%s\"", file_name);
return;
}
//擦除块
int i;
printf("Eraseing...\n");
for (i = 0; i < (number_byte/64/1024); i++) {
BlockErase64k(i*64*1024);
printf("Block Erase for %d block %dkB-%dkB\n\33[1A", i,i*64,(i+1)*64);
}
printf("\nErase finish!\n");
printf("writing...\n");
//给芯片编程
char buff_data[256];
for (i = 0; i < (number_byte/256); i++) {
fread(&buff_data,1,256,file);
write_data_page(i*256,buff_data,256);
if(i%256==0)
printf("%dkB\n\33[1A", i*256/1024);
}
fclose(file);
write_dis();
printf("\nwrite finish!\n");
}
void read_img()
{
FILE *file = fopen(file_name,"wb");
if(file==0)
{
printf("open error for \"%s\"", file_name);
return;
}
printf("reading...\n");
char buff_data[256];
int i;
for (i = 0; i < (number_byte)/256; i++) {
read_date(i*256,buff_data,256);
fwrite(&buff_data,1,256,file);
if(i%256==0)
printf("%dkB\n\33[1A", i*256/1024);
}
fclose(file);
write_dis();
printf("\nread finish!\n");
}
int main(int argc, char *argv[])
{
int ret = 0;
int i;
char aa[256];
parse_opts(argc, argv);
spi_fd = open(device, O_RDWR);
if (spi_fd < 0)
pabort("can't open device");
/*
* spi mode
*/
ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(spi_fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort("can't get spi mode");
/*
* bits per word
*/
ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(spi_fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/*
* max speed hz
*/
ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(spi_fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get 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
if(read_write_flg==1)
{
read_img();
}
else if(read_write_flg==2)
{
write_img();
}
return ret;
}
编译执行:gcc spi-w25q64.c -o spi-w25q64
编译生成:spi-w25q64
应用使用方法:
1. 读取数据:sudo ./spi-w25q64 -r w25q64.img -n 8388608
-r 跟的参数是将读取的数据保存成w25q64.img文件
-n 跟的参数是要读多少字节
上图“40 17” 是读到的芯片id。
2.芯片编程:sudo ./spi-w25q64 -w w25q64.img -n 8388608
-r 跟的参数是将w25q64.img文件 中的数据写入芯片中。
-n 跟的参数是要读多少字节。
可下载源码:https://download.csdn.net/download/xiaopanpanpanpan/10337072