那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

CKS32F4xx系列產品SPI通信

中科芯MCU ? 來源:中科芯MCU ? 2023-04-21 09:36 ? 次閱讀

SPI協議是由摩托羅拉公司提出的通訊協議(Serial Peripheral Interface),即串行外圍設備接口,是一種高速全雙工的通信總線。它在芯片的管腳上只占用四根線,節約了芯片的管腳,同時為PCB在布局上節省了空間,提供方便,正是出于這種簡單易用的特性,現在越來越多的芯片集成了這種通信協議,它被廣泛地使用在ADC、LCD、FLASH等設備與MCU之間的通信。

CKS32F4xx系列產品SPI介紹

CKS32F4xx系列的SPI外設可用作通訊的主機及從機,支持最高的SCK時鐘頻率為fpclk/2(CKS32F407型號的芯片默認fpclk為142MHz,fpclk2為84MHz),完全支持SPI協議的4種模式。SPI協議根據CPOL及CPHA的不同狀態分成的四種工作模式如下表所示:

71895c76-dfb8-11ed-bfe3-dac502259ad0.jpg

CKS32F4xx系列的SPI架構如下圖所示:

71a38bc8-dfb8-11ed-bfe3-dac502259ad0.png

圖中的1處是SPI的引腳MOSI、MISO、SCK、NSS。CKS32F4xx芯片有多個 SPI外設,它們的SPI通訊信號引出到不同GPIO引腳上,使用時必須配置到這些指定的引腳。關于GPIO引腳的復用功能可以查閱芯片數據手冊。各個引腳的作用介紹如下:

(1)NSS:從設備選擇信號線,常稱為片選信號線。當有多個SPI從設備與 SPI主機相連時,設備的其它信號線SCK、MOSI及MISO同時并聯到相同的SPI 總線上,即無論有多少個從設備,都共同只使用這3條總線;而每個從設備都有獨立的一條NSS信號線,當主機要選擇從設備時,把該從設備的NSS信號線設置為低電平,該從設備即被選中,即片選有效,接著主機開始與被選中的從設備進行SPI通訊。所以SPI通訊以NSS線置低電平為開始信號,以NSS線被拉高作為結束信號。

(2)SCK:時鐘信號線,用于通訊數據同步。它由通訊主機產生,決定了通訊的速率,不同的設備支持的最高時鐘頻率不一樣,兩個設備之間通訊時,通訊速率受限于低速設備。

(3)MOSI:主設備輸出/從設備輸入引腳。主機的數據從這條信號線輸出,從機由這條信號線讀入主機發送的數據,即這條線上數據的方向為主機到從機。

(4)MISO:主設備輸入/從設備輸出引腳。主機從這條信號線讀入數據,從機的數據由這條信號線輸出到主機,即在這條線上數據的方向為從機到主機。

圖中的2處是SCK線的時鐘信號,由波特率發生器根據“控制寄存器CR1”中的BR[0:2]位控制,該位是對fpclk時鐘的分頻因子,對fpclk的分頻結果就是SCK引腳的輸出時鐘頻率。

圖中的3處是SPI的數據控制邏輯。SPI的MOSI及MISO都連接到數據移位寄存器上,數據移位寄存器的內容來源于接收緩沖區及發送緩沖區以及MISO、MOSI線。當向外發送數據的時候,數據移位寄存器以“發送緩沖區”為數據源,把數據一位一位地通過數據線發送出去;當從外部接收數據的時候,數據移位寄存器把數據線采樣到的數據一位一位地存儲到“接收緩沖區”中。通過寫SPI 的“數據寄存器DR”把數據填充到發送緩沖區中,通過“數據寄存器DR”,可以獲取接收緩沖區中的內容。其中數據幀的長度可以通過“控制寄存器CR1”的“DFF位”配置成8位及16位模式;配置“LSBFIRST位”可選擇MSB先行還是 LSB先行。

圖中的4處是SPI的整體控制邏輯。整體控制邏輯負責協調整個SPI外設,控制邏輯的工作模式根據我們配置的“控制寄存器(CR1/CR2)”的參數而改變,基本的控制參數包括SPI模式、波特率、LSB先行、主從模式、單雙向模式等等。在外設工作時,控制邏輯會根據外設的工作狀態修改“狀態寄存器(SR)”,我們只要讀取狀態寄存器相關的寄存器位,就可以了解SPI的工作狀態了。除此之外,控制邏輯還根據要求,負責控制產生SPI中斷信號、DMA請求及控制NSS信號線。實際應用中,我們一般不使用CKS32 SPI外設的標準NSS信號線,而是更簡單地使用普通的GPIO,軟件控制它的電平輸出,從而產生通訊起始和停止信號。

CKS32F4xx系列的SPI作為通訊主機端時收發數據的過程如下:

(1) 控制NSS信號線,產生起始信號;

(2) 把要發送的數據寫入到“數據寄存器DR”中,該數據會被存儲到發送緩沖區;

(3) 通訊開始,SCK時鐘開始運行。MOSI把發送緩沖區中的數據一位一位地傳輸出去;MISO則把數據一位一位地存儲進接收緩沖區中;

(4) 當發送完一幀數據的時候,“狀態寄存器SR”中的“TXE標志位”會被置1,表示傳輸完一幀,發送緩沖區已空;類似地,當接收完一幀數據的時候,“RXNE標志位”會被置1,表示傳輸完一幀,接收緩沖區非空;

(5) 等待到“TXE標志位”為1時,若還要繼續發送數據,則再次往“數據寄存器DR”寫入數據即可;等待到“RXNE標志位”為1時,通過讀取“數據寄存器DR”可以獲取接收緩沖區中的內容。

假如我們使能了TXE或RXNE中斷,TXE或RXNE置1時會產生SPI中斷信號,進入同一個中斷服務函數,到SPI中斷服務程序后,可通過檢查寄存器位來了解是哪一個事件,再分別進行處理。也可以使用DMA方式來收發“數據寄存器 DR”中的數據。

CKS32F4xx系列產品SPI的配置

接下來我們講解如何利用CKS32F4xx系列固件庫來完成對SPI的配置使用。跟其它外設一樣,CKS32標準庫提供了SPI初始化結構體及初始化函數來配置 SPI外設。了解初始化結構體后我們就能對SPI外設運用自如了,代碼如下:

typedef struct
{
  uint16_t SPI_Direction;          
  uint16_t SPI_Mode;              
  uint16_t SPI_DataSize;          
  uint16_t SPI_CPOL;             
  uint16_t SPI_CPHA;               
  uint16_t SPI_NSS;               
  uint16_t SPI_BaudRatePrescaler;  
  uint16_t SPI_FirstBit;           
  uint16_t SPI_CRCPolynomial;       
}SPI_InitTypeDef;

結構體中各個成員變量的介紹及初始化時可被賦的值如下:

1) SPI_Direction:本成員設置SPI的通訊方向,可設置為雙線全雙工 (SPI_Direction_2Lines_FullDuplex),雙線只接收 (SPI_Direction_2Lines_RxOnly),單線只接收(SPI_Direction_1Line_Rx)、單線只發送模式(SPI_Direction_1Line_Tx)。

2) SPI_Mode:本成員設置SPI工作在主機模式(SPI_Mode_Master)或從機模式(SPI_Mode_Slave ),這兩個模式的最大區別為SPI的SCK信號線的時序,SCK的時序是由通訊中的主機產生的。若被配置為從機模式,CKS32的SPI外設將接受外來的SCK信號:

3) SPI_DataSize: 本成員可以選擇SPI通訊的數據幀大小是為8位 (SPI_DataSize_8b)還是16位(SPI_DataSize_16b)。

4) SPI_CPOL和SPI_CPHA: 這兩個成員配置SPI的時鐘極性CPOL和時鐘相位CPHA,前面講過這兩個配置影響到SPI的通訊模式。時鐘極性CPOL成員可設置為高電平(SPI_CPOL_High)或低電平(SPI_CPOL_Low )。時鐘相位CPHA則 可以設置為SPI_CPHA_1Edge(在SCK的奇數邊沿采集數據)或 SPI_CPHA_2Edge(在SCK的偶數邊沿采集數據)。

5) SPI_NSS: 本成員配置NSS引腳的使用模式,可以選擇為硬件模式 (SPI_NSS_Hard )與軟件模式(SPI_NSS_Soft ),在硬件模式中的SPI片選信號由 SPI硬件自動產生,而軟件模式則需要我們自己把相應的GPIO端口拉高或置低產生非片選和片選信號。實際中軟件模式應用比較多。

6) SPI_BaudRatePrescaler: 本成員設置波特率分頻因子,分頻后的時鐘即為SPI的SCK信號線的時鐘頻率。這個成員參數可設置為fpclk的2、4、6、8、16、32、64、128、256分頻??蛇x的值如下所示:

SPI_BaudRatePrescaler_2    //2分頻
SPI_BaudRatePrescaler_4    //4分頻
SPI_BaudRatePrescaler_6    //6分頻
SPI_BaudRatePrescaler_8    //8分頻
SPI_BaudRatePrescaler_16   //16分頻
SPI_BaudRatePrescaler_32   //32分頻
SPI_BaudRatePrescaler_64   //64分頻
SPI_BaudRatePrescaler_128  //128分頻
SPI_BaudRatePrescaler_256  //256分頻
?

7) SPI_FirstBit:所有串行的通訊協議都會有MSB先行(高位數據在前)還是 LSB先行(低位數據在前)的問題,而CKS32F4xx系列的SPI模塊可以通過這個結構體成員,對這個特性編程控制。

SPI_FirstBit_MSB    //高位數據在前
SPI_FirstBit_LSB     //低位數據在前

8) SPI_CRCPolynomial:這是SPI的CRC校驗中的多項式,若我們使用CRC 校驗時,就使用這個成員的參數(多項式),來計算CRC的值。

配置完這些結構體成員的值,調用庫函數SPI_Init即可把結構體的配置寫入到寄存器中。

CKS32F4xx讀寫SPI FLASH實驗

串口的DMA接發通信實驗是存儲器到外設和外設到存儲器的數據傳輸。在第24

本小節以一種使用SPI通訊的串行FLASH存儲芯片的讀寫實驗為大家講解 CKS32F4xx系列的SPI使用方法。實驗中的FLASH芯片(型號:W25Q32)是一種使用SPI通訊協議的NORFLASH存儲器,它的CS/CLK/DIO/DO引腳分別連接到了CKS32F4xx對應的SPI引腳NSS/SCK/MOSI/MISO上,其中CKS32F4xx的NSS引腳是一個普通的GPIO,不是SPI的專用NSS引腳,所以程序中我們要使用軟件控制的方式。

1.編程要點

(1) 初始化通訊使用的目標引腳及端口時鐘;

(2) 使能SPI外設的時鐘;

(3) 配置SPI外設的模式、地址、速率等參數并使能SPI外設;

(4) 編寫基本SPI按字節收發的函數;

(5) 編寫對FLASH擦除及讀寫操作的的函數;

(6) 編寫測試程序,對讀寫數據進行校驗。

2.代碼分析

代碼清單1:W25Q32初始化配置

void W25QXX_Init(void)
{ 
  GPIO_InitTypeDef  GPIO_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); 
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 
  GPIO_Init(GPIOD, &GPIO_InitStructure); 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_SetBits(GPIOG,GPIO_Pin_3); 
  W25QXX_CS=1;                        //SPI FLASH不選中
  SPI1_Init();                               //初始化SPI
  SPI1_SetSpeed(SPI_BaudRatePrescaler_4);    //設置為21M時鐘
  W25QXX_TYPE=W25QXX_ReadID();         //讀取FLASH ID.
}  

上面的代碼主要是完成對W25Q32片選引腳的初始化,SPI初始化。SPI通信速率設置和讀取W25Q32的ID。

代碼清單2:SPI初始化函數

void SPI1_Init(void)
{   
  GPIO_InitTypeDef  GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 
  GPIO_Init(GPIOB, &GPIO_InitStructure); 
GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_SPI1);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_SPI1); 
GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_SPI1); 
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;    
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;  
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;    
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; 
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;    
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;  
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  
  SPI_InitStructure.SPI_CRCPolynomial = 7;  
  SPI_Init(SPI1, &SPI_InitStructure);  
  SPI_Cmd(SPI1, ENABLE); 
  SPI1_ReadWriteByte(0xff);   
}   

上面這段代碼主要是完成對SPI1的初始化,首先是配置了SPI1使用的引腳SPI1_SCK、SPI1_MOSI和SPI1_MISO。然后是根據第2小節的內容完成對SPI1外設模式的配置。根據FLASH芯片W25Q32的說明,它支持SPI模式0及模式3,支持雙線全雙工,使用MSB先行模式,支持最高通訊時鐘為104MHz,數據幀長度為8位。我們要把CKS32F4的SPI外設中的這些參數配置一致。

代碼清單3:SPI1單字節收發函數

u8 SPI1_ReadWriteByte(u8 TxData)
{            
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){} 
  SPI_I2S_SendData(SPI1, TxData); 
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){} 
  return SPI_I2S_ReceiveData(SPI1); 
}

本函數中不包含SPI起始和停止信號,只是收發的主要過程,所以在調用本函數前后要做好起始和停止信號的操作。通過檢測TXE標志,獲取發送緩沖區的狀態,若發送緩沖區為空,則表示可能存在的上一個數據已經發送完畢;等待至發送緩沖區為空后,調用庫函數SPI_I2S_SendData把要發送的數據“TxData”寫入到SPI的數據寄存器DR,寫入SPI數據寄存器的數據會存儲到發送緩沖區,由SPI外設發送出去;寫入完畢后等待RXNE事件,即接收緩沖區非空事件。由于SPI雙線全雙工模式下MOSI與MISO數據傳輸是同步的,當接收緩沖區非空時,表示上面的數據發送完畢,且接收緩沖區也收到新的數據;等待至接收緩沖區非空時,通過調用庫函數SPI_I2S_ReceiveData讀取SPI的數據寄存器DR,就可以獲取接收緩沖區中的新數據了。代碼中使用關鍵字“return”把接收到的這個數據作為SPI1_ReadWriteByte函數的返回值。

搞定了SPI的基本收發單元后,還需要了解如何對FLASH芯片進行讀寫。FLASH 芯片自定義了很多指令,我們通過控制CKS32F4利用SPI總線向FLASH 芯片發送指令,FLASH芯片收到后就會執行相應的操作。具體的指令代碼可以查看W25Q32芯片的數據手冊。

代碼清單4:讀取FLASH芯片ID函數

u16 W25QXX_ReadID(void)
{
  u16 Temp = 0;    
  W25QXX_CS=0;            
  SPI1_ReadWriteByte(0x90);      
  SPI1_ReadWriteByte(0x00);       
  SPI1_ReadWriteByte(0x00);       
  SPI1_ReadWriteByte(0x00);             
  Temp|=SPI1_ReadWriteByte(0xFF)<<8;  
  Temp|=SPI1_ReadWriteByte(0xFF);   
  W25QXX_CS=1;            
  return Temp;
}     

這段代碼利用控制CS引腳電平的宏“W25QXX_CS”以及前面編寫的單字節收發函數SPI1_ReadWriteByte,很清晰地實現了讀ID指令的時序,最后把讀 取到的這3個數據合并到一個變量Temp中,然后作為函數返回值,把該返回值與我們定義的芯片ID對比,即可知道FLASH芯片是否正常。

代碼清單5:W25Q32寫使能和寫禁止函數

void W25QXX_Write_Enable(void)   
{
  W25QXX_CS=0;                              
  SPI1_ReadWriteByte(W25X_WriteEnable);     
  W25QXX_CS=1;                                    
}
void W25QXX_Write_Disable(void)   
{  
  W25QXX_CS=0;                            
  SPI1_ReadWriteByte(W25X_WriteDisable);        
  W25QXX_CS=1;                                      
}   

由于FLASH存儲器的特性決定了它只能把原來為“1”的數據位改寫成“0”,而原來為“0”的數據位不能直接改寫為“1”。所以在寫入前,必須要對目標存儲矩陣進行擦除操作,把矩陣中的數據位擦除為“1”,在數據寫入的時候,如果要存儲數據“1”, 那就不修改存儲矩陣,在要存儲數據“0”時,需要更改該位。W25Q32支持“扇區擦除”、“塊擦除”以及“整片擦除”。扇區擦除指令的第一個字節為指令編碼,緊接著發送的3個字節用于表示要擦除的存儲矩陣地址。要注意的是在扇區擦除指令前,還需要先發送“寫使能”指令,發送扇區擦除指令后,通過讀取寄存器狀態等待扇區擦除操作完畢。

代碼清單6:W25Q32扇區擦除函數

void W25QXX_Erase_Sector(u32 Dst_Addr)   
{      
   Dst_Addr*=4096;
    W25QXX_Write_Enable();                    
    W25QXX_Wait_Busy();   
    W25QXX_CS=0;                              
    SPI1_ReadWriteByte(W25X_SectorErase);      
    SPI1_ReadWriteByte((u8)((Dst_Addr)>>16));     
    SPI1_ReadWriteByte((u8)((Dst_Addr)>>8));   
    SPI1_ReadWriteByte((u8)Dst_Addr);  
  W25QXX_CS=1;                                   
    W25QXX_Wait_Busy();             
}  

目標扇區被擦除完畢后,就可以向它寫入數據了。與EEPROM類似,FLASH芯片也有頁寫入命令,使用頁寫入命令最多可以一次向FLASH傳輸256個字節的數據,我們把這個單位稱為頁大小。在進行頁寫入時第1個字節為“頁寫入指令”編碼,2-4字節為要寫入的“地址A”,接著的是要寫入的內容,最多可以發送 256字節數據,這些數據將會從“地址A”開始,按順序寫入到FLASH的存儲矩陣。若發送的數據超出256個,則會覆蓋前面發送的數據。

代碼清單7:W25Q32頁寫入函數

void W25QXX_Write_Page(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)
{
   u16 i;  
    W25QXX_Write_Enable();                 
  W25QXX_CS=0;                               
    SPI1_ReadWriteByte(W25X_PageProgram);         
    SPI1_ReadWriteByte((u8)((WriteAddr)>>16));   
    SPI1_ReadWriteByte((u8)((WriteAddr)>>8));   
    SPI1_ReadWriteByte((u8)WriteAddr);   
    for(i=0;i

應用的時候我們常常要寫入不定量的數據,直接調用“頁寫入”函數并不是特別方便,所以我們頁寫入函數的基礎上編寫了“不定量數據寫入”的函數。在實際調用這個“不定量數據寫入”函數時,還要注意確保目標扇區處于擦除狀態

代碼清單8:W25Q32不定量數據寫入函數

void W25QXX_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   
{ 
  u32 secpos;
  u16 secoff;
  u16 secremain;     
   u16 i;    
  u8 * W25QXX_BUF;    
     W25QXX_BUF=W25QXX_BUFFER;       
   secpos=WriteAddr/4096; 
  secoff=WriteAddr%4096; 
  secremain=4096-secoff;  
   if(NumByteToWrite<=secremain)secremain=NumByteToWrite;
  while(1) 
  {  
    W25QXX_Read(W25QXX_BUF,secpos*4096,4096); 
    for(i=0;i4096)secremain=4096;  
      else secremain=NumByteToWrite;      
    }   
  };   
}

函數的入口參數pBuffer是數據存儲區、WriteAd是開始寫入的地址(24bit)、NumByteToWrite是要寫入的字節數(最大65535)gaojp。

相對于寫入,FLASH芯片W25Q32的數據讀取要簡單的多,發送了指令編碼及要讀的起始地址和要讀取的字節數之后,FLASH 芯片W25Q32就會按地址遞增的方式返回存儲矩陣中一定字節數量的數據。

代碼清單9:W25Q32讀取數據函數

void W25QXX_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)   
{ 
   u16 i;                           
  W25QXX_CS=0;                              
    SPI1_ReadWriteByte(W25X_ReadData);          
    SPI1_ReadWriteByte((u8)((ReadAddr)>>16));     
    SPI1_ReadWriteByte((u8)((ReadAddr)>>8));   
    SPI1_ReadWriteByte((u8)ReadAddr);   
    for(i=0;i

函數的入口參數pBuffer是數據存儲區、ReadAddr是開始讀取的地址(24bit)、NumByteToRead是要讀取的字節數(最大65535)。

完成基本的讀寫函數后,接下來我們編寫一個讀寫測試函數來檢驗驅動程。

代碼清單10:W25Q32讀寫測試函數

uint8_t w25q32_Test(void)
{
  u16 i;
   printf("寫入的數據:
");
  for ( i=0; i<=10; i++ ) 
  {   
    spi_Buf_Write[i] = i;
    printf("0x%02X ", spi_Buf_Write[i]);
   }
   W25QXX_Write((u8*)spi_Buf_Write,FLASH_SIZE-100,11);     
     printf("寫成功,");
     printf("讀出的數據:
");
    W25QXX_Read(datatemp,FLASH_SIZE-100,11);          
  for (i=0; i<11; i++)
  {  
    if(datatemp[i] != spi_Buf_Write[i])
    {
      printf("0x%02X ", datatemp[i]);
      printf("錯誤:I2C EEPROM寫入與讀出的數據不一致");
      return 0;
    }
    printf("0x%02X ", datatemp[i]);
  }
  printf("
");
    printf("spi(w25q32)讀寫測試成功");
  return 1;
}

代碼中先填充一個數組,數組的內容為0,1至10,接著把這個數組的內容寫入到SPI FLASH中,并將寫入的數據打印輸出到串口調試助手。寫入完畢后再從SPI FLASH的地址中讀取數據,把讀取到的數據與寫入的數據進行校驗,若一致說明讀寫正常,否則讀寫過程有問題或者SPI FLASH芯片不正常,然后再將讀取到的數據打印輸出到串口調試助手。

代碼清單11:主函數

int main(void)
{ 
    u16 id = 0;  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  delay_init(168);    
   USART_Configuration();
  W25QXX_Init();      
  while(1)
  {
    id = W25QXX_ReadID();
    if (id == W25Q32 || id == NM25Q32)
      break;
      printf("W25Q32 init failed
");
    delay_ms(500);
    delay_ms(500);
  }
   printf("W25Q32 init success
");
   w25q32_Test();
  while(1)
  {
      
  }       
}

主函數代碼比較簡單,主要是完成串口初始化和W25Q32的初始化,初始化完成之后會執行W25QXX_ReadID函數,讀取W25Q32的ID,同時對ID進行判斷,并將結果通過串口調試助手打印輸出。然后會執行一次W25Q32測試函數,并將一些測試結果通過串口調試助手打印輸出。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • mcu
    mcu
    +關注

    關注

    146

    文章

    17324

    瀏覽量

    352655
  • 接口
    +關注

    關注

    33

    文章

    8694

    瀏覽量

    151925
  • 通信
    +關注

    關注

    18

    文章

    6072

    瀏覽量

    136430
  • SPI
    SPI
    +關注

    關注

    17

    文章

    1722

    瀏覽量

    92130
  • 通訊協議
    +關注

    關注

    10

    文章

    279

    瀏覽量

    20437

原文標題:MCU微課堂 | CKS32F4xx系列產品SPI通信

文章出處:【微信號:中科芯MCU,微信公眾號:中科芯MCU】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    MCU微課堂|CKS32F4xx系列產品時鐘配置

    作為MCU運行的基礎,時鐘是單片機各個模塊工作時序的最小時間單位,推動單片機的各指令執行,是MCU選型的一個重要指標。CKS32F4xx系列產品具有眾多的外設,但并非所有的外設均需要系統時鐘的高頻率
    發表于 12-12 10:17 ?881次閱讀

    CKS32F4xx系列ETH通信詳解

    CKS32F4xx系列芯片自帶以太網模塊,該模塊包括帶專用DMA控制器的MAC 802.3(介質訪問控制)控制器
    的頭像 發表于 11-10 11:13 ?1084次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>ETH<b class='flag-5'>通信</b>詳解

    CKS32F4xx系列產品NVIC中斷優先級管理單元講解

    本課將為大家講解CKS32F4xx系列產品的中斷優先級管理單元NVIC。CM4內核共支持256個中斷,其中包含了16個內核中斷和240個外部中斷,具有256級可編程中斷設置。但CKS32F4x
    的頭像 發表于 02-06 14:52 ?1250次閱讀

    CKS32F4xx系列產品串口DMA傳輸

    在上一講,我們講過CKS32F4xx系列的6個串口都支持DMA傳輸。因此本節我們對CKS32F4xx系列的DMA進行介紹,同時利用DMA對串口數據進行傳輸。
    的頭像 發表于 04-10 11:18 ?1104次閱讀

    CKS32F4xx系列產品的定時器使用-基本特征和定時操作

    這一課我們將介紹CKS32F4XX系列產品的定時器使用,CKS32F4XX的定時器功能十分強大,包含2個高級控制定時器,8個普通定時器,2個基礎定時器,以及兩個看門狗定時器和一個系統定時器,總共15個定時器之多。關于定時器部分內
    的頭像 發表于 05-19 09:18 ?977次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產品</b>的定時器使用-基本特征和定時操作

    CKS32F4xx系列RNG功能設置

    ? MCU 微課堂 CKS32F4xx 系 列RNG功能 隨機數發生器簡介 ? ? CKS32F4xx系列自帶了硬件隨機數發生器(RNG),RNG處理器是一個以連續模擬噪聲為基礎的隨機數發生器,在
    的頭像 發表于 09-08 10:01 ?666次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>RNG功能設置

    CKS32F4xx系列DAC功能

    CKS32F4xx系列DAC功能
    的頭像 發表于 11-06 16:56 ?907次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>DAC功能

    CKS32F4xx系列ADC多通道DMA電壓采集

    CKS32F4xx系列ADC多通道DMA電壓采集
    的頭像 發表于 11-06 16:53 ?1159次閱讀

    CKS32F4xx系列低功耗模式STOP模式

    CKS32F4xx系列低功耗模式STOP模式
    的頭像 發表于 11-06 17:08 ?671次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>低功耗模式STOP模式

    CKS32F4xx系列產品Timer的基本使用方法-定時器脈沖計數

    CKS32F4xx系列產品Timer的基本使用方法-定時器脈沖計數
    的頭像 發表于 11-09 17:38 ?1141次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產品</b>Timer的基本使用方法-定時器脈沖計數

    CKS32F4xx系列產品Timer的基本使用方法-比較輸出

    CKS32F4xx系列產品Timer的基本使用方法-比較輸出
    的頭像 發表于 11-09 17:39 ?914次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產品</b>Timer的基本使用方法-比較輸出

    CKS32F4xx系列產品Timer的基本使用方法-定時操作

    CKS32F4xx系列產品Timer的基本使用方法-定時操作
    的頭像 發表于 11-09 17:41 ?680次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產品</b>Timer的基本使用方法-定時操作

    MCU微課堂 | CKS32F4xx系列產品SPI通信

    MCU微課堂 | CKS32F4xx系列產品SPI通信
    的頭像 發表于 10-24 17:12 ?766次閱讀
    MCU微課堂 | <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產品</b><b class='flag-5'>SPI</b><b class='flag-5'>通信</b>

    MCU微課堂 | CKS32F4xx系列產品GPIO口配置

    MCU微課堂 | CKS32F4xx系列產品GPIO口配置
    的頭像 發表于 10-24 15:14 ?851次閱讀
    MCU微課堂 | <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列產品</b>GPIO口配置

    CKS32F4xx系列FSMC功能簡介

    本課講為大家講解CKS32F4xx系列產品的FSMC應用實例,FSMC全稱是Flexible Static Memory Controller,讀作靈活的靜態存儲控制器,顧名思義,MCU可以通過FSMC擴展靜態內存
    的頭像 發表于 04-14 15:06 ?1046次閱讀
    <b class='flag-5'>CKS32F4xx</b><b class='flag-5'>系列</b>FSMC功能簡介
    大发888娱乐城大发888大发网| 菠菜百家乐官网娱乐城| 百家乐线路图分析| 解析百家乐投注法| 8运24山风水图解| 百家乐官网大天堂| 百家乐官网专业豪华版| 太阳城百家乐官网出千技术 | 会宁县| 青鹏棋牌官网| 棋牌小游戏| 体球网足球比分| 尊龙备用网址| 和静县| 百家乐官网棋牌公式| 沂水县| 百家乐官网国际娱乐城| 百家乐官网免费试玩游戏| 百家乐官网电子作弊器| 高手百家乐官网赢钱法| 澳门百家乐官网怎样下注| 澳门百家乐官网小游戏| 百家乐官网大小牌路的含义| 江山百家乐官网的玩法技巧和规则 | 大三巴百家乐官网的玩法技巧和规则 | 真钱百家乐官网送钱| 百家乐官网有看牌器吗| 百家乐官网视频游戏冲值| 百家乐官网只打一种牌型| 百家乐官网购怎么样| 百家乐官网网盛世三国| 顶尖百家乐官网的玩法技巧和规则| 百家乐取胜秘笈| 单双和百家乐游戏机厂家| 澳门百家乐走势图怎么看| 赌片百家乐的玩法技巧和规则 | 德州扑克官方下载| tt娱乐城开户| 百家乐官网赢得秘诀| 百家乐官网哪家赌安全| KK百家乐官网娱乐城|