STM32-SPI接口的簡單實(shí)現(xiàn)13頁_第1頁
STM32-SPI接口的簡單實(shí)現(xiàn)13頁_第2頁
STM32-SPI接口的簡單實(shí)現(xiàn)13頁_第3頁
STM32-SPI接口的簡單實(shí)現(xiàn)13頁_第4頁
STM32-SPI接口的簡單實(shí)現(xiàn)13頁_第5頁
已閱讀5頁,還剩8頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、STM32 SPI接口的簡單實(shí)現(xiàn)通常SPI通過4個(gè)引腳與外部器件相連: MISO:主設(shè)備輸入/從設(shè)備輸出引腳。該引腳在從模式下發(fā)送數(shù)據(jù),在主模式下接收數(shù)據(jù)。 MOSI:主設(shè)備輸出/從設(shè)備輸入引腳。該引腳在主模式下發(fā)送數(shù)據(jù),在從模式下接收數(shù)據(jù)。 SCK:串口時(shí)鐘,作為主設(shè)備的輸出,從設(shè)備的輸入NSS:從設(shè)備選擇。這是一個(gè)可選的引腳,用來選擇主/從設(shè)備。它的功能是用來作為“片選引腳”,讓主設(shè)備可以單獨(dú)地與特定從設(shè)備通訊,避免數(shù)據(jù)線上的沖突。從設(shè)備的NSS引腳可以由主設(shè)備的一個(gè)標(biāo)準(zhǔn)I/O引腳來驅(qū)動。一旦被使能(SSOE位),NSS引腳也可以作為輸出引腳,并在SPI處于主模式時(shí)拉低;此時(shí),所有的SPI

2、設(shè)備,如果它們的NSS引腳連接到主設(shè)備的NSS引腳,則會檢測到低電平,如果它們被設(shè)置為NSS硬件模式,就會自動進(jìn)入從設(shè)備狀態(tài)。當(dāng)配置為主設(shè)備、NSS配置為輸入引腳(MSTR=1,SSOE=0)時(shí),如果NSS被拉低,則這個(gè)SPI設(shè)備進(jìn)入主模式失敗狀態(tài):即MSTR位被自動清除,此設(shè)備進(jìn)入從模式。時(shí)鐘信號的相位和極性SPI_CR寄存器的CPOL和CPHA位,能夠組合成四種可能的時(shí)序關(guān)系。CPOL(時(shí)鐘極性)位控制在沒有數(shù)據(jù)傳輸時(shí)時(shí)鐘的空閑狀態(tài)電平,此位對主模式和從模式下的設(shè)備都有效。如果CPOL被清0,SCK引腳在空閑狀態(tài)保持低電平;如果CPOL被置1,SCK引腳在空閑狀態(tài)保持高電平。如果CPHA(

3、時(shí)鐘相位)位被置1,SCK時(shí)鐘的第二個(gè)邊沿(CPOL位為0時(shí)就是下降沿,CPOL位為1時(shí)就是上升沿)進(jìn)行數(shù)據(jù)位的采樣,數(shù)據(jù)在第二個(gè)時(shí)鐘邊沿被鎖存。如果CPHA位被清0,SCK時(shí)鐘的第一邊沿(CPOL位為0時(shí)就是下降沿,CPOL位為1時(shí)就是上升沿)進(jìn)行數(shù)據(jù)位采樣,數(shù)據(jù)在第一個(gè)時(shí)鐘邊沿被鎖存。CPOL時(shí)鐘極性和CPHA時(shí)鐘相位的組合選擇數(shù)據(jù)捕捉的時(shí)鐘邊沿。圖212顯示了SPI傳輸?shù)?種CPHA和CPOL位組合。此圖可以解釋為主設(shè)備和從設(shè)備的SCK腳、MISO腳、MOSI腳直接連接的主或從時(shí)序圖。CPOL時(shí)鐘極性和CPHA時(shí)鐘相位的組合選擇數(shù)據(jù)捕捉的時(shí)鐘邊沿。上圖顯示了SPI傳輸?shù)?種CPHA和CP

4、OL位組合。此圖可以解釋為主設(shè)備和從設(shè)備的SCK腳、MISO腳、MOSI腳直接連接的主或從時(shí)序圖。注意:1. 在改變CPOL/CPHA位之前,必須清除SPE位將SPI禁止。2. 主和從必須配置成相同的時(shí)序模式。3.SCK的空閑狀態(tài)必須和SPI_CR1寄存器指定的極性一致(CPOL為1時(shí),空閑時(shí)應(yīng)上拉SCK為高電平;CPOL為0時(shí),空閑時(shí)應(yīng)下拉SCK為低電平)。4. 數(shù)據(jù)幀格式(8位或16位)由SPI_CR1寄存器的DFF位選擇,并且決定發(fā)送/接收的數(shù)據(jù)長度。我只要知道主機(jī)和從機(jī)的CPOL和CPHA位要一致就夠了。有2種NSS模式:軟件NSS模式:可以通過設(shè)置SPI_CR1寄存器的SSM位來使能

5、這種模式。在這種模式下NSS引腳可以用作它用,而內(nèi)部NSS信號電平可以通過寫SPI_CR1的SSI位來驅(qū)動 硬件NSS模式,分兩種情況:NSS輸出被使能:當(dāng)STM32F10xxx工作為主SPI,并且NSS輸出已經(jīng)通過SPI_CR2寄存器的SSOE位使能,這時(shí)NSS引腳被拉低,所有NSS引腳與這個(gè)主SPI的NSS引腳相連并配置為硬件NSS的SPI設(shè)備,將自動變成從SPI設(shè)備。當(dāng)一個(gè)SPI設(shè)備需要發(fā)送廣播數(shù)據(jù),它必須拉低NSS信號,以通知所有其它的設(shè)備它是主設(shè)備;如果它不能拉低NSS,這意味著總線上有另外一個(gè)主設(shè)備在通信,這時(shí)將產(chǎn)生一個(gè)硬件失敗錯(cuò)誤(HardFault)。 NSS輸出被關(guān)閉:允許操

6、作于多主環(huán)境。/我們用軟件NSS主從的轉(zhuǎn)換都可借助庫來實(shí)現(xiàn)數(shù)據(jù)幀格式根據(jù)SPI_CR1寄存器中的LSBFIRST位,輸出數(shù)據(jù)位時(shí)可以MSB在先也可以LSB在先。根據(jù)SPI_CR1寄存器的DFF位,每個(gè)數(shù)據(jù)幀可以是8位或是16位。所選擇的數(shù)據(jù)幀格式對發(fā)送和/或接收都有效。配置一個(gè)SPI 這里選SPI2如下:SPI_InitTypeDef SPI_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);SPI_Cmd(SPI2, DISABLE); /必須先禁能,才能改變MODESPI_InitStructure.SPI_D

7、irection =SPI_Direction_2Lines_FullDuplex; /兩線全雙工SPI_InitStructure.SPI_Mode =SPI_Mode_Master; /主SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b; /8位SPI_InitStructure.SPI_CPOL =SPI_CPOL_High; /CPOL=1時(shí)鐘懸空高SPI_InitStructure.SPI_CPHA =SPI_CPHA_1Edge; /CPHA=1 數(shù)據(jù)捕獲第2個(gè)SPI_InitStructure.SPI_NSS =SPI_NSS_Sof

8、t; /軟件NSSSPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_2; /2分頻SPI_InitStructure.SPI_FirstBit =SPI_FirstBit_MSB; /高位在前SPI_InitStructure.SPI_CRCPolynomial =7; /CRC7SPI_Init(SPI2,&SPI_InitStructure);SPI_Cmd(SPI2, ENABLE);/spi的配置結(jié)束了可以使用了。也可用 函數(shù)SPI_StructInit 把SPI_InitStruct中的每一個(gè)參數(shù)按缺省值填入

9、_發(fā)送緩沖器空閑標(biāo)志(TXE)【3.0 SPI_I2S_FLAG_TXE】此標(biāo)志為1時(shí)表明發(fā)送緩沖器為空,可以寫下一個(gè)待發(fā)送的數(shù)據(jù)進(jìn)入緩沖器中。當(dāng)寫入SPI_DR時(shí),TXE標(biāo)志被清除。接收緩沖器非空(RXNE)【3.0 SPI_I2S_FLAG_RXNE】此標(biāo)志為1時(shí)表明在接收緩沖器中包含有效的接收數(shù)據(jù)。讀SPI數(shù)據(jù)寄存器可以清除此標(biāo)志。注意在2.0的庫中函數(shù)SPI_SendData SPI_ReceiveData SPI_GetFlagStatus 等在3.0的庫中 變?yōu)镾PI_I2S_SendData SPI_I2S_ReceiveData SPI_I2S_GetFlagStatus寫一個(gè)

10、發(fā)送/接受函數(shù)static u8 SPIByte(u8 byte)while(SPI2-SR &SPI_I2S_FLAG_TXE)=RESET);/while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)=RESET);SPI2-DR = byte;/SPI_I2S_SendData(SPI2,byte);while(SPI2-SR &SPI_I2S_FLAG_RXNE)=RESET);/while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)=RESET);return(SPI2-DR);/return

11、SPI_I2S_ReceiveData(SPI2);讀寄存器用硬件清除標(biāo)志位。/SPI_I2S_ClearFlag(SPI2,SPI_I2S_FLAG_RXNE) ;直接軟件清除標(biāo)志位。這里有兩種寫法直接操作寄存器與用庫函數(shù),相對來說直接操作寄存器應(yīng)該更直觀一些。調(diào)試總會遇到這樣那樣的小問題 和朋友一起進(jìn)步總會更快 希望對別人能有點(diǎn)幫助節(jié)省些時(shí)間萬利的板子 板載的M25P80 PDF寫的這一型號有 25MHZ 和50MHZ兩種 注意初始化SPI的設(shè)置 BAUD至少就要PCLK/2 = 36Mhz即使配置為主模式發(fā)送 時(shí)鐘也不是連產(chǎn)生的 接收的時(shí)候同樣需要發(fā)送無用字節(jié)以維持?jǐn)?shù)據(jù)時(shí)鐘STM32 的

12、 NSS腳需要配置為軟件模式(可以通過寄存器控制NSS高低) 硬件模式下 NSS引腳必須+ 正的邏輯電平 才能將SPE MSTR位時(shí)能配置SPI為主模式先寫了一遍 然后借鑒一個(gè)sst25vf08的應(yīng)用筆記又寫了一遍 看這個(gè)筆記省了不少時(shí)間 很感謝同一地址單元 重新寫入需先擦除 否者二次寫入后讀出無效其他按照時(shí)序走就可以了程序如下:#define WREN 0x06#define WRDI 0x04#define RDSR 0x05#define WRSR 0x01#define READ 0x03#define FAST_READ 0x06#define PAGE_PROG 0x02#defi

13、ne SECTOR_ERASER 0xd8#define BULK_ERASER 0xc7#define DEEP_SLEEP 0xb9#define RES 0xab#define M25P80_SELECT() GPIOB-BRR |= GPIO_Pin_2#define M25P80_DESELECT() GPIOB-BSRR |= GPIO_Pin_2u8 SPI_SeRe_Byte(u8 data);void M25p80_Cmd1b(u8 cmd);u8 M25p80_Cmd1b_R1b(u8 cmd);void M25p80_Cmd1b_S1b(u8 cmd , u8 data)

14、;void M25p80_WP_En(void);void M25p80_Write_En(void);u8 M25p80_Busy(void);u8 M25p80_Read_1Byte(u32 addr );void M25p80_Read_Bytes(u32 addr , u8* re_buf_p , u16 no);void M25p80_Write_1Byte(u32 addr , u8 data);void M25p80_Write_Bytes(u32 addr , u8* wr_buf_p , u16 no);void M25p80_Section_Erase(u32 addr);

15、void M25p80_Bulk_Erase(void);/* op-code for M25P80 SPI EEROM* 8Mbit = 1,048,576 bytes = 16 sectors (512 Kbits, 65536 bytes each) = 4096 pages (256 bytes each)* 1sector = 256 page* address range 00000 fffffh*/u8 SPI_SeRe_Byte(u8 data)u8 re_data;while(! (SPI1-SR & 0x0002) );/*TXE?*/SPI1-DR = data;whil

16、e(! (SPI1-SR & 0x0001) );/*RXNE?*/re_data = SPI1-DR;return re_data;/*函數(shù)名稱:M25p80_cmd1b_r1b/M25p80_Cmd1b_S1b CMD命令發(fā)送 返回1BYTE/命令發(fā)送跟送1BYTE*/void M25p80_Cmd1b(u8 cmd)M25P80_SELECT();SPI_SeRe_Byte(cmd);M25P80_DESELECT();u8 M25p80_Cmd1b_R1b(u8 cmd)u8 data;M25P80_SELECT();SPI_SeRe_Byte(cmd);data = SPI_SeRe

17、_Byte(0xff);M25P80_DESELECT();return data;void M25p80_Cmd1b_S1b(u8 cmd , u8 data)M25P80_SELECT();SPI_SeRe_Byte(cmd);SPI_SeRe_Byte(data);M25P80_DESELECT();/*/*函數(shù)名稱:M25p80_WP_En/M25p80_Write_En M25p80寫保護(hù)使能/寫使能 status寄存器修改*/void M25p80_WP_En(void)u8 sta;sta = M25p80_Cmd1b_R1b(RDSR) | 0x1c;M25p80_Cmd1b_

18、S1b(WRSR, sta);M25p80_Cmd1b(WRDI);void M25p80_Write_En(void)u8 sta;sta = M25p80_Cmd1b_R1b(RDSR) & (0x1c);M25p80_Cmd1b_S1b(WRSR, sta);M25p80_Cmd1b(WREN);/*/u8 M25p80_Busy(void)u8 sta;sta = M25p80_Cmd1b_R1b(RDSR);return (sta & 0x01);u8 M25p80_Read_1Byte(u32 addr )u8 ad3 , data;ad0 = (addr & 0x00ff0000

19、) 16;ad1 = (addr & 0x0000ff00) 8;ad2 = (addr & 0x000000ff);M25P80_SELECT();SPI_SeRe_Byte(READ);SPI_SeRe_Byte(ad0);SPI_SeRe_Byte(ad1);SPI_SeRe_Byte(ad2);data = SPI_SeRe_Byte(0xff);M25P80_DESELECT();return data;void M25p80_Read_Bytes(u32 addr , u8* re_buf_p , u16 no)u8 ad3 ;ad0 = (addr & 0x00ff0000) 1

20、6;ad1 = (addr & 0x0000ff00) 8;ad2 = (addr & 0x000000ff);M25P80_SELECT();SPI_SeRe_Byte(READ);SPI_SeRe_Byte(ad0);SPI_SeRe_Byte(ad1);SPI_SeRe_Byte(ad2);for(; no 0; no-)*re_buf_p+ = SPI_SeRe_Byte(0xff);M25P80_DESELECT();/*/void M25p80_Write_1Byte(u32 addr , u8 data)u8 ad3 ;ad0 = (addr & 0x00ff0000) 16;a

21、d1 = (addr & 0x0000ff00) 8;ad2 = (addr & 0x000000ff);M25p80_Write_En();M25P80_SELECT();SPI_SeRe_Byte(PAGE_PROG);SPI_SeRe_Byte(ad0);SPI_SeRe_Byte(ad1);SPI_SeRe_Byte(ad2);SPI_SeRe_Byte(data);M25P80_DESELECT();M25p80_WP_En();while(M25p80_Busy();void M25p80_Write_Bytes(u32 addr , u8* wr_buf_p , u16 no)/

22、*u8 ad3 ;ad0 = (addr & 0x00ff0000) 16;ad1 = (addr & 0x0000ff00) 8;ad2 = (addr & 0x000000ff);if( no 0; no-)*wr_buf_p+ = SPI_SeRe_Byte(0xff);M25P80_DESELECT();M25p80_Cmd1b(WRDI);return 1;*/for(; no 0; no-)M25p80_Write_1Byte(addr , *wr_buf_p);addr+;wr_buf_p+;M25p80_WP_En();/*/void M25p80_Section_Erase(

23、u32 addr)u8 ad3 ;ad0 = (addr & 0x00ff0000) 16;ad1 = (addr & 0x0000ff00) 8;ad2 = (addr & 0x000000ff);M25p80_Write_En();M25P80_SELECT();SPI_SeRe_Byte(SECTOR_ERASER);SPI_SeRe_Byte(ad0);SPI_SeRe_Byte(ad1);SPI_SeRe_Byte(ad2);M25P80_DESELECT();while(M25p80_Busy();M25p80_WP_En();void M25p80_Bulk_Erase(void

24、)M25p80_Write_En();M25p80_Cmd1b(BULK_ERASER);while(M25p80_Busy();M25p80_WP_En();這里的多字節(jié)寫函數(shù)void M25p80_Write_Bytes(u32 addr , u8* wr_buf_p , u16 no) 調(diào)用了單字節(jié)寫函數(shù) 實(shí)際上還是一個(gè)一個(gè)寫 主要因?yàn)橛庙搶懖僮鞯脑?當(dāng)數(shù)據(jù)到達(dá)頁底會返回本頁從頭開始寫 會破壞數(shù)據(jù) 而且沒有字節(jié)寫操作碼感覺比sst25vf08麻煩很多。關(guān)于STM32 SPI NSS問題的探討。對于STM32的SPI ,Reference Manual中是給出的schematic如下:按照

25、標(biāo)準(zhǔn)的SPI協(xié)議,當(dāng)SPI被配置為主機(jī)模式后,通過SPI對從設(shè)備進(jìn)行操作時(shí),其NSS應(yīng)該自動置低,從而選中(使能)從設(shè)備;一旦不對從設(shè)備進(jìn)行操作,NSS立刻置為高。但是,我在實(shí)際調(diào)試過程中卻發(fā)現(xiàn):STM32 SPI NSS無法自動實(shí)現(xiàn)跳變。 一旦SPI初始化完成并使能SPI,NSS立刻置低,然后保持不變。這個(gè)問題一直無法解決,直到我在ST官方論壇上看到國外有些技術(shù)人員也在討論這個(gè)問題,他們得出的結(jié)論是:STM32 SPI NSS無法自動跳變。RichardE Posted 24-07-2009 at 16:07Registered on :11-05-2005From UK (United K

26、ingdom)Messages : 19OFF-LineIve just hit this NSS problem.What is good:That the discussion is here on the forum to stop me spending hours trying to work out what I have done wrong. Thanks guys!What is not good:hat NSS doesnt behave as expected.What I expected to happen:Im expecting to see on my scop

27、e what I see in Figure 208 of RM008 Reference Manual, i.e. NSS goes high after the transfer.Why a working NSS would be very helpful:Im using the SPI (with DMA) to clock data into shift registers. If NSS went high after the transfer (as indicated by Figure 208), I could use that edge as the strobe to

28、 latch the data across into the shift register outputs. Everything would be done by the peripheral. Fire and forget. As it is with the broken NSS, I have to generate an interrupt and use that to strobe the gpio output (I hate controlling gpio from within interrupt routines).Any update as to when thi

29、s will be fixed?ST官方技術(shù)人員也證實(shí):STM32 SPI NSS是不會自動置位和復(fù)位的。按照官方說法,ST已經(jīng)將其列入了改進(jìn)計(jì)劃。對于這個(gè)問題,可以采用下面的方法解決:在SPI初始化時(shí),采用NSS soft模式,然后使能NSS輸出功能。從而將NSS當(dāng)做GPIO使用,通過軟件set和reset來實(shí)現(xiàn)NSS的置位和復(fù)位。具體代碼如下:/* SPI1 configuration -*/SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;SPI_InitStructure.SPI_Mode = SPI_Mode_Maste

30、r;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; /SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;/SPI

31、_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 7;SPI_Init(SPI1, &SPI_InitStructure);/*Enable SPI1.NSS as a GPIO*/SPI_SSOutputCmd(SPI1, ENABLE);/*Configure PA.4(NSS)-*/GPIO_InitStructure.GPIO_Pin =GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);通過將N

32、SS配置為GPIO,在通過SPI操作從設(shè)備時(shí),就可以通過軟件來選中和釋放從設(shè)備了。雖然比起硬件自動置位要麻煩,但問題畢竟解決了。進(jìn)一步閱讀長達(dá)900頁的Manual,我發(fā)現(xiàn),文中對于SPI hard模式的描述并非大多數(shù)人所認(rèn)為的硬件SPI,原文如下:Slave select (NSS) pin managementThere are two NSS modes: Software NSS mode: this mode is enabled by setting the SSM bit in the SPI_CR1register (see Figure 209). In this mode, the external NSS pin is free for otherapplication uses and the internal N

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論