樹莓派4B-SPI讀寫flash-FM25CL16B(同時支援FM25CL64等其它系列Flash)

諾謙發表於2021-07-09

1.樹莓派SPI介紹

 4B的引腳如下圖所示:

其中Pin19、21、23是SPI0,介面定義如下所示:

  • 時鐘(SPI CLK, SCLK)
  • 主機輸出、從機輸入(MOSI)
  • 主機輸入、從機輸出(MISO)

在使用 SPI 介面前,你需要使用 gpio 命令來載入 SPI 驅勱到核心中:

gpio load spi

如果您需要的緩衝區大於 4KB,需要在命令列迕行指定緩衝區的大小,單位是 KB:

gpio load spi 100

上述命令將會分配 100KB 的緩衝區.(您可能很少需要改變返項謳置,預設值對於絕大多數應用程式來說已經足夠了). 為了使用 SPI 庫,你也需要在你的程式中新增如下語句:

#include <wiringPiSPI.h>

程式在編譯連線時,仍然需要新增-lwiringPi 選項

需要用到的函式如下所示:

int wiringPiSPISetup(int channel, int speed);
//使用該函式可以初始化一個 SPI 通道,樹莓派有兩個 SPI 通道(0 和 1)。
//speed 引數是一個整數值,其範圍為 500000~32000000,代表 SPI 時鐘速度,單位是 Hz。
//返回值為-1,則失敗。則需要檢查一下電路連線和是否開啟了樹莓派的SPI。

int wiringPiSPIDataRW(int channel, unsigned char* data, int len);
//該函式執行一個同時讀寫操作,通過選定的 SPI 匯流排。緩衝區中的資料,將會被 SPI匯流排的返回資料所覆蓋。

void delay (unsigned int howLong)
//延時ms,最大傳入32位無符號型整數,大約49天。

void delayMicroseconds (unsigned int howLong)
//延時微秒,最大傳入32位無符號型整數,大約71分鐘

 

2.FM25L16B晶片介紹

    FM25L16是採用先進的鐵電工藝製造的1024*16位的非易失性儲存器(2048個位元組)。鐵電隨機儲存器(FRAM)具有非易失性,並且可以象RAM一樣快速讀寫。FM25L16中的資料在掉電後可以儲存45年。相對EEPROM或其他非易失性儲存器,FM25L16具有結構更簡單,系統可靠性更高等諸多優點。
   與EEPROM系列不同的是,FM25L16以匯流排速度進行寫操作,無須延時。資料發到FM25L16後直接寫到具體的單元地址,下一個匯流排操作可以立即開始,無需資料輪詢。此外,FM25L16的讀/寫次數幾乎為無限次,比EEPROM高得多。同時,FM25L16的功耗也遠比EEPROM低。

引腳定義如下所示:

 

  • /CS: 片選,低電平為啟用裝置
  • SCK: SPI輸入時鐘,頻率最高支援20MHZ
  • /HOLD: 輸入保持,比如當我們在進行讀寫的時候,假如產生了一箇中斷,由於時序已經在進行了,這時可以給個低電平讓晶片保持時序,等待中斷處理完成後,再來置高,繼續讀寫資料.
  • /WP: 防寫,為低電平則不能寫操作
  • SI、SO: SPI輸入輸出資料引腳

指令如下所示:

 

 

2.1 狀態暫存器(0x01)介紹

狀態暫存器的每個bit位意義如下所示:

 

其中BP1和BP0是設定防寫區域的.如下圖所示:

 

我們必須將BP1和BP0設定為0,才可以有寫所有地址的許可權.

 

2.2 寫暫存器(0x06)介紹

所有對記憶體陣列的寫入都以WREN(0X06)操作碼開頭,下一個操作碼是WRITE指令,這個操作碼後面跟著一個雙位元組地址。地址的前5位將被忽略(最多儲存2048位元組),然後就可以一直寫入資料.最後將CS置高則完成寫操作.

 

3.最終程式碼

#include<stdio.h>
#include <cstring>
#include<wiringPi.h>
#include <wiringPiSPI.h>

typedef unsigned char u8;
typedef unsigned short u16;

#define FM25CL16_WREN       0x06       // 寫使能
#define FM25CL16_WRITE      0x02       // 寫暫存器
#define FM25CL16_READ       0x03       // 讀暫存器
#define FM25CL64_WRSR       0x01       // 狀態暫存器
#define FM25L16_CSPIN       21         // 片選引腳

void initSPI()
{
    //初始化所用到的IO引腳
    pinMode(FM25L16_CSPIN, OUTPUT);
    digitalWrite(FM25L16_CSPIN, HIGH);

    //初始化SPI通道0,並設定為速度
    if(wiringPiSPISetup(0,5000000)==-1) {
        printf("init spi failed!\n");
    }
}


// 片選
void fm25l16Cs(u8 select)
{
    if (select == 0) {
       digitalWrite(FM25L16_CSPIN, LOW);
    } else {
       digitalWrite(FM25L16_CSPIN, HIGH);
    }
}

// 向FLASH寫入一個位元組資料
static u8 fm25l16WriteByte(u8 Temp)
{
    return wiringPiSPIDataRW(0,&Temp,1);
}

// FLASH寫使能
static void fm25l16WriteEnable()
{
    fm25l16Cs(0);
    fm25l16WriteByte(FM25CL16_WREN);
    fm25l16Cs(1);

}

// 寫入一串資料
void fm25l16WriteBuff(u16 addr,u8* buff,u16 len)
{
    u8 buffHead[3]; // 資料頭

    fm25l16WriteEnable();
    fm25l16Cs(0);
    buffHead[0] = FM25CL16_WRITE;
    buffHead[1] = (addr&0xFF00)>>8;
    buffHead[2] = (addr&0x00FF);
    wiringPiSPIDataRW(0,buffHead,3);
    wiringPiSPIDataRW(0,buff,len);
    fm25l16Cs(1);
}


// 讀出一串資料到buff中
void fm25l16ReadBuff(u16 addr,u8* buff,u16 len)
{
    u8 buffHead[3]; // 資料頭

    fm25l16Cs(0);
    buffHead[0] = FM25CL16_READ;
    buffHead[1] = (addr&0xFF00)>>8;
    buffHead[2] = (addr&0x00FF);
    wiringPiSPIDataRW(0,buffHead,3);
    wiringPiSPIDataRW(0,buff,len);
    fm25l16Cs(1);
}

// 寫狀態
void fm25l16Status()
{
    u8 buff[2] = {FM25CL64_WRSR, 0X00};
    fm25l16WriteEnable();
    fm25l16Cs(0);
    wiringPiSPIDataRW(0,buff,2); // 取消防寫
    fm25l16Cs(1);
}

int main()
{
    u8 data[10];
    u8 i=0;
    u8 beginData = 0;
    //初始化wiringPI的庫函式
    if(wiringPiSetup()<0) {
        printf("init wiringPi error\n");
    }
    initSPI();          //spi的初始化
    fm25l16Status();    // 寫狀態暫存器
    while(1) {
        for(i=0;i<10;i++) {
            data[i] = beginData++;
        }
        fm25l16WriteBuff(0,data,10);
        printf("write ok\n");
        fm25l16ReadBuff(0,data,10);
        printf("read: ");
        for(i=0;i<10;i++) {
             printf("%d ",data[i]);
        }
        printf("\n");
        delay(20);
    }
    return 0;
} 

執行效果如下所示:

 

 

 

 

相關文章