新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STM32 SPI W25X16驅動

        STM32 SPI W25X16驅動

        作者: 時間:2016-11-25 來源:網絡 收藏
        前面說了STM32的I2C,作為STM32的另外一個串行接口就不得不提到了——SPI。與I2C差不多,同樣有硬件接口,有庫函數支持,我們要做的就是結合SPI接口芯片調用庫函數,就能實現SPI驅動了。一切看代碼,你會懂的,注釋非常詳細的,很適合初學者。代碼能夠直接用到實際項目工程里面去的。SPI芯片選用W25X系列。。。

        演示效果使用超級終端或者SecureCRT 5.5(這貨真的不錯)

        本文引用地址:http://www.104case.com/article/201611/321302.htm

        工程結構圖:

        1、工程里面的beep.c led.c usart1.c 與《STM32 基于庫函數控制按鍵&nb… 》《STM32 串口例程之查詢收》里面完全一樣,這里就不在上代碼。

        2、main.c

        //程序功能:主要用于測試SPI W25X16驅動是否正常


        #include"stm32f10x.h"
        #include"user_usart1.h"
        #include"user_led.h"
        #include"user_beep.h"
        #include"user_spi_w25x16.h"
        #include


        #define FLASH_ID1 0xef3015
        #define FLASH_ID2 0xef4015
        #define FLASH_WriteAddress 0x000000
        #define FLASH_ReadAddress FLASH_WriteAddress
        #define FLASH_SectorErase FLASH_WriteAddress

        #define CountOf(a) (sizeof(a)/sizeof(*(a)))
        #define DataSize(CountOf(TxDataTable)-1)

        u8 TxDataTable[]="Hello,I am wgchnln,我 愛 ARM,I will persist in learning ARM,堅決不放棄";
        u8 RxDataTable[DataSize];


        //=============================================
        #ifdef __GNUC__

        #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
        #else
        #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
        #endif
        //=============================================



        TestStatus User_SPI_DataCompare(u8 *TxData,u8 *RxData,u8 Num)
        {
        while(Num--)
        {
        if(*TxData!=*RxData)
        {
        return Failed;
        }
        RxData++;
        TxData++;
        }

        return Successed;
        }


        void User_SPI_Test(void)
        {
        vu32 ID,DeviceID;
        u8 Buffer;
        volatile TestStatus Test1=Failed;
        volatile TestStatus Test2=Successed; //存放兩次測試的結果


        printf("正在努力讀取ID號.....");
        User_LedSpark(Led1,2);
        ID=User_SPI_W25X16_ReadID();
        printf("flashID:%x",ID);

        printf("正在努力讀取DeviceID號......");
        User_LedSpark(Led1,2);
        DeviceID=User_SPI_W25X16_ReadDeviceID();
        printf("flashDeviceID:%x",DeviceID);



        if((ID==FLASH_ID1)||(ID==FLASH_ID2))
        {

        printf("ARM在芯片擦除......");
        User_LedSpark(Led1,2);
        User_SPI_W25X16_SectorErase(FLASH_SectorErase);
        printf("完成");


        printf("你要寫入的數據:%s",TxDataTable);
        printf("努力為你芯片寫入中......");
        User_LedSpark(Led1,2);
        User_SPI_W25X16_ChipWrite(TxDataTable,FLASH_WriteAddress,DataSize);
        printf("完成");


        printf("芯片數據讀取......");
        User_LedSpark(Led1,2);
        User_SPI_W25X16_ChipRead(RxDataTable,FLASH_ReadAddress,DataSize);
        printf("完成");
        User_LedSpark(Led1,2);
        printf("為您讀取的數據:%s",RxDataTable);


        printf("為您做數據比較中......");
        User_LedSpark(Led1,2);
        Test1=User_SPI_DataCompare(RxDataTable,TxDataTable,DataSize);
        if(Test1==Successed)
        {
        printf("數據相同");
        }
        else
        {
        printf("數據不相同");
        User_LedSpark(Led2,2);
        printf("為您分析可能原因:數據未寫入、讀取錯誤、或者兩者同時存在");
        }


        printf("再一次芯片擦除......");
        User_LedSpark(Led1,2);
        User_SPI_W25X16_SectorErase(FLASH_SectorErase);
        printf("完成");


        printf("又一次芯片讀取......");
        User_LedSpark(Led1,2);
        User_SPI_W25X16_ChipRead(RxDataTable,FLASH_ReadAddress,DataSize);
        printf("完成");


        printf("判斷是否擦除掉......");
        User_LedSpark(Led1,1);
        for(Buffer=0;Buffer
        {
        if(RxDataTable[Buffer]!=0xff)
        {
        Test2=Failed;
        }
        }
        if(Test2==Failed)
        {
        printf("失敗");
        printf("為您分析的可能原因:讀取錯誤、擦除失敗、或者兩者同時存在");
        }
        else
        {
        printf("擦除OK");
        }


        printf("------------為您展示此次測試結果------------");
        if((Test1==Successed)&&((Test2==Successed)))
        {
        User_LedSpark(Led1,2);
        printf("恭喜你,SPI W25X16驅動測試通過啦");
        }
        else
        {
        User_LedSpark(Led2,2);
        printf("糟糕,SPI功能演示失敗了......原因可能是讀寫數據不一致、軟件擦除失敗");
        }
        }


        else
        {
        User_LedSpark(Led2,2);
        printf("悲劇了,SPI功能演示失敗啦.....原因是芯片ID號碼讀取出錯哦");
        }
        }


        int main(void)
        {
        User_USART1Config();
        printf("串口1配置......");
        printf("完成");

        printf("蜂鳴器初始化...");
        User_BeepConfig();
        printf("蜂鳴器測試......");
        User_BeepStatus(BeepStatus_TurnOn);
        printf("完成");

        printf("LED初始化...");
        User_LedConfig();
        printf("LED測試......");
        User_LedSpark(Led0,2);
        printf("完成");

        printf("SPI初始化...");
        User_SPI_Config();
        User_LedSpark(Led0,2);
        printf("完成");

        User_SPI_Test();

        while(1);
        }

        //==================================================
        PUTCHAR_PROTOTYPE
        {


        USART_SendData(USART1, (uint8_t) ch);


        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
        {}

        return ch;
        }
        //==================================================

        3、user_spi_w25x16.c

        //program function:SPI1 Init && FLASF Chip W25X16 driver


        #include"stm32f10x.h"
        #include"user_spi_w25x16.h"
        #include



        #define WriteEnable0x06
        #define WriteDisable0x04
        #define ReadStatusRegister0x05
        #define WriteStatusRegister0x01
        #define ReadData0x03
        #define FastRead0x0b
        #define FsatReadDualOutput0x3b
        #define PageProgram0x02
        #define BlukErase0xd8
        #define SectorErase0x20
        #define ChipErase0xc7
        #define PowerDown0xb9
        #define WakeUp0xab
        #define DeviceID0xab
        #define ManufatureID0x90
        #define JedecID0x9f

        #define JudgeCode0x01 //用于判斷通訊是否結束用
        #define NoneCode0xa5 //無意義的指令,用于:接收數據時,發送這個質量來產生接收時候的時鐘



        void User_SPI_Config(void)
        {


        SPI_InitTypeDef SPI_InitStructure;

        GPIO_InitTypeDef GPIO_InitStructure;



        RCC_APB2PeriphClockCmd(SPI_24G_CS_Clock,ENABLE);
        GPIO_InitStructure.GPIO_Pin =SPI_24G_CS_Pin;
        GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
        GPIO_Init(SPI_24G_CS_Port,&GPIO_InitStructure);
        GPIO_SetBits(SPI_24G_CS_Port,SPI_24G_CS_Pin);


        RCC_APB2PeriphClockCmd(SPI_VS1003B_CS_Clock,ENABLE);
        GPIO_InitStructure.GPIO_Pin =SPI_VS1003B_CS_Pin;
        GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
        GPIO_Init(SPI_VS1003B_CS_Port,&GPIO_InitStructure);
        GPIO_SetBits(SPI_VS1003B_CS_Port,SPI_VS1003B_CS_Pin);



        RCC_APB2PeriphClockCmd(SPI_W25X16_Clock,ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);



        RCC_APB2PeriphClockCmd(SPI_W25X16_CS_Clock,ENABLE);
        GPIO_InitStructure.GPIO_Pin =SPI_W25X16_CS_Pin;
        GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
        GPIO_Init(SPI_W25X16_CS_Port,&GPIO_InitStructure);
        SPI_W25X16_CS_DisSelect;


        RCC_APB2PeriphClockCmd(SPI_W25X16_SCK_Clock,ENABLE);
        GPIO_InitStructure.GPIO_Pin =SPI_W25X16_SCK_Pin;
        GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
        GPIO_Init(SPI_W25X16_SCK_Port,&GPIO_InitStructure);


        RCC_APB2PeriphClockCmd(SPI_W25X16_MISO_Clock,ENABLE);
        GPIO_InitStructure.GPIO_Pin =SPI_W25X16_MISO_Pin;
        GPIO_Init(SPI_W25X16_MISO_Port,&GPIO_InitStructure);


        RCC_APB2PeriphClockCmd(SPI_W25X16_MOSI_Clock,ENABLE);
        GPIO_InitStructure.GPIO_Pin =SPI_W25X16_MOSI_Pin;
        GPIO_Init(SPI_W25X16_MOSI_Port,&GPIO_InitStructure);



        SPI_InitStructure.SPI_Direction =SPI_Direction_2Lines_FullDuplex; //通訊模式:雙向全雙工模式
        SPI_InitStructure.SPI_Mode =SPI_Mode_Master;//主從:主模式
        SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b;//數據幀長度:8bits
        SPI_InitStructure.SPI_CPOL =SPI_CPOL_High;//空閑時置高
        SPI_InitStructure.SPI_CPHA =SPI_CPHA_2Edge;//第二個時鐘采樣
        SPI_InitStructure.SPI_NSS =SPI_NSS_Soft;//NSS控制選擇:軟件控制
        SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_2;//波特率分配系數:2分頻
        SPI_InitStructure.SPI_FirstBit =SPI_FirstBit_MSB;//數據幀格式:MSB在前
        SPI_InitStructure.SPI_CRCPolynomial =7;//CRC效驗多項式

        SPI_Init(SPI1,&SPI_InitStructure);

        SPI_Cmd(SPI1,ENABLE);
        }


        u8 User_SPI_W25X16_SendByte(u8 SendByteData)
        {
        u8 ReceiveData;


        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);

        SPI_I2S_SendData(SPI1,SendByteData);


        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);

        ReceiveData=SPI_I2S_ReceiveData(SPI1);

        return ReceiveData;
        }


        u8 User_SPI_W25X16_ReadByte(void)
        {
        u8 ReceiveData;

        ReceiveData=User_SPI_W25X16_SendByte(NoneCode);

        return ReceiveData;
        }


        vu16 User_SPI_W25X16_SendHalfWord(u16 HalfWord)
        {
        vu16 ReceiveData;


        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET);

        SPI_I2S_SendData(SPI1,HalfWord);


        while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);

        ReceiveData=SPI_I2S_ReceiveData(SPI1);

        return ReceiveData;
        }


        void User_SPI_W25X16_WriteEnable(void)
        {

        SPI_W25X16_CS_Select;


        User_SPI_W25X16_SendByte(WriteEnable);


        SPI_W25X16_CS_DisSelect;
        }


        上一頁 1 2 下一頁

        關鍵詞: STM32SPIW25X16驅

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 寿阳县| 城市| 枣强县| 集贤县| 浦县| 鄂托克旗| 中江县| 清原| 阳信县| 武义县| 荥经县| 鹤壁市| 西乡县| 巴楚县| 延吉市| 漯河市| 镇远县| 岐山县| 织金县| 庆城县| 恩平市| 兴和县| 景泰县| 龙江县| 彭水| 崇文区| 沽源县| 株洲市| 东明县| 新民市| 拉萨市| 含山县| 华阴市| 肃宁县| 新乡市| 吉木乃县| 临朐县| 凭祥市| 北宁市| 建湖县| 噶尔县|