新聞中心

STM32的SPI問(wèn)題。

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
問(wèn)題描述:

之前一直使用的單片機(jī)是LPC2109,對(duì)其SPI很熟悉?;揪褪窃灸脕?lái)稍作修改就用。
由于某種原因需要使用STM32,然后設(shè)備的驅(qū)動(dòng)是之前寫(xiě)好的,只修改了一些硬件控制端口,由于硬件驅(qū)動(dòng)使用到了SPI接口,而我是把SPI接口提供了出來(lái),本來(lái)以為簡(jiǎn)單修改SPI配置到對(duì)應(yīng)單片機(jī)就行了。簡(jiǎn)單看了STM3的SPI配置,輕車熟路改代碼,瞬間體現(xiàn)了良好的接口有哈。
編譯,生成目標(biāo)文件,下載運(yùn)行。
并沒(méi)有出現(xiàn)預(yù)想的結(jié)果。由于之前的設(shè)備驅(qū)動(dòng)是能用的,所以排除設(shè)備驅(qū)動(dòng)問(wèn)題。
開(kāi)始以為是由于對(duì)STM32端口配置的不熟悉導(dǎo)致的、看手冊(cè),看別人代碼,沒(méi)發(fā)現(xiàn)問(wèn)題。
debug........
問(wèn)題定在SPI代碼上。查看配置,一樣啊。郁悶!?。?br />把自己配置考到別人能用的代碼中,可以使用。更加郁悶!?。?!
debug看寄存器。對(duì)比能運(yùn)行代碼寄存器狀態(tài)。發(fā)現(xiàn)運(yùn)行到一段代碼的時(shí)候寄存器不同
SPI_CR 0x0043
SPI_CR 0x2
看datasheet.OVR置位。問(wèn)題應(yīng)該就在這了??墒菫槭裁茨???????

本文引用地址:http://m.butianyuan.cn/article/201611/318264.htm

搜此問(wèn)題,此處出自這里

溢出錯(cuò)誤(OVR)
 溢出錯(cuò)誤表示連續(xù)傳輸多個(gè)數(shù)據(jù)時(shí),后一個(gè)數(shù)據(jù)覆蓋了前一個(gè)數(shù)據(jù)而產(chǎn)生的錯(cuò)誤。
 狀態(tài)標(biāo)志SPIF表示的是數(shù)據(jù)傳輸正在進(jìn)行中,它對(duì)數(shù)據(jù)的傳輸有較大的影響。主器件的SPIF有效由數(shù)據(jù)寄存器的空標(biāo)志SPTE=0產(chǎn)生,而從器件的SPIF有效則只能由收到的第一個(gè)SCK的跳變產(chǎn)生,且又由于從器件的SPIF和主器件發(fā)出的SCK是異步的,因此從器件的傳輸標(biāo)志SPIF從相對(duì)于主器件的傳輸標(biāo)志SPIF主有一定的滯后。如圖4所示,在主器件連續(xù)發(fā)送兩個(gè)數(shù)據(jù)的時(shí)候?qū)⒂锌赡軐?dǎo)致從器件的傳輸標(biāo)志和主器件下一個(gè)數(shù)據(jù)的傳輸標(biāo)志相重疊(圖4中虛線和陰影部分),第一個(gè)收到的數(shù)據(jù)必然被覆蓋,第二個(gè)數(shù)據(jù)的收/發(fā)也必然出錯(cuò),產(chǎn)生溢出錯(cuò)誤

圖4溢出錯(cuò)誤
  通過(guò)對(duì)從器件的波形分析發(fā)現(xiàn),counter=8后的第一個(gè)時(shí)鐘周期,數(shù)據(jù)最后一位的傳輸已經(jīng)完成。在數(shù)據(jù)已經(jīng)收/發(fā)完畢的情況下,counter=8狀態(tài)的長(zhǎng)短對(duì)數(shù)據(jù)的正確性沒(méi)有影響,因此可以縮短counter=8的狀態(tài),以避免前一個(gè)SPIF和后一個(gè)SPIF相重疊。這樣,從硬件上避免了這一階段的溢出錯(cuò)誤。
  但是,如果從器件工作速度不夠快或者軟件正在處理其他事情,在SPI接口接收到的數(shù)據(jù)尚未被讀取的情況下,又接收到一個(gè)新的數(shù)據(jù),溢出錯(cuò)誤還是會(huì)發(fā)生的。此時(shí),SPI接口保護(hù)前一個(gè)數(shù)據(jù)不被覆蓋,舍棄新收到的數(shù)據(jù),置溢出標(biāo)志OVR=1;另外發(fā)出中斷信號(hào)(如果該中斷允許),通知從器件及時(shí)讀取數(shù)據(jù)。

23.4.7 錯(cuò)誤標(biāo)志位
I2S 單元有2個(gè)錯(cuò)誤標(biāo)志位。
下溢標(biāo)志位(UDR)
在從發(fā)送模式下,如果數(shù)據(jù)傳輸?shù)牡谝粋€(gè)時(shí)鐘邊沿到達(dá)時(shí),新的數(shù)據(jù)仍然沒(méi)有寫(xiě)入SPI_DR寄存
器,該標(biāo)志位會(huì)被置’1’ 。在寄存器SPI_I2SCFGR的I2SMOD 位置’1’ 后,該標(biāo)志位才有效。如果
寄存器SPI_CR2的ERRIE位為’1’ ,就會(huì)產(chǎn)生中斷。
通過(guò)對(duì)寄存器SPI_SR進(jìn)行讀操作來(lái)清除該標(biāo)志位。
上溢標(biāo)志位(OVR)
如果還沒(méi)有讀出前一個(gè)接收到的數(shù)據(jù)時(shí),又接收到新的數(shù)據(jù),即產(chǎn)生上溢,該標(biāo)志位置’1’ ,如
果寄存器SPI_CR2的ERRIE位為’1’ ,則產(chǎn)生中斷指示發(fā)生了錯(cuò)誤。
這時(shí),接收緩存的內(nèi)容,不會(huì)刷新為從發(fā)送設(shè)備送來(lái)的新數(shù)據(jù)。對(duì)寄存器SPI_DR的讀操作返回
最后一個(gè)正確接收到的數(shù)據(jù)。其他所有在上溢發(fā)生后由發(fā)送設(shè)備發(fā)出的16位數(shù)據(jù)都會(huì)丟失。
通過(guò)先讀寄存器SPI_SR再讀寄存器SPI_DR,來(lái)清除該標(biāo)志位。

void SPI_write_byte(u8 data){S0SPDR = data;while ((S0SPSR & 0x80) == 0);}u8 SPI_read_byte(void){S0SPDR = 0xff;while((S0SPSR & 0x80) == 0);return (S0SPDR);}

整個(gè)工程修改的代碼如下(注釋代碼為不能正常工作的):

/**/// void SPI_write_byte(u8 data)// {// while (!(SPI1->SR & (1 << 1)));// SPI1->DR = data;// }// u8 SPI_read_byte(void)// {// while (!(SPI1->SR & 1));// return SPI1->DR;// }u8 spi_rw(u8 data){while (!(SPI1->SR & (1 << 1)));SPI1->DR = data;while (!(SPI1->SR & 1));return SPI1->DR;}/**/// SPI_write_byte(op  (address & ADDR_MASK));// SPI_write_byte(data);spi_rw(op  (address & ADDR_MASK));spi_rw(data);/**/// SPI_write_byte(RBM);spi_rw(RBM);// *data = SPI_read_byte();*data = spi_rw(0xff);/**/// SPI_write_byte(WBM);spi_rw(WBM);// SPI_write_byte(*data);spi_rw(*data);/**/

看完基本就明白問(wèn)題所在了...

分析問(wèn)題:

我是按照LPC的SPI配置的,而現(xiàn)在的是STM32,問(wèn)題關(guān)鍵就在于STM32的接受緩沖空和發(fā)送緩沖非空的標(biāo)志是不同的。而LPC單片機(jī)是相同的。仔細(xì)分析我寫(xiě)的代碼,實(shí)際上每次執(zhí)行都缺少了對(duì)狀態(tài)的判斷,從而導(dǎo)致了數(shù)據(jù)的溢出。

解決問(wèn)題:

修改代碼如下,問(wèn)題解決。

u8 SPI_write_byte(u8 data){while (!(SPI1->SR & (1 << 1)));SPI1->DR = data;while (!(SPI1->SR & 1));return SPI1->DR;}u8 SPI_read_byte(void){while (!(SPI1->SR & (1 << 1)));SPI1->DR = 0xff;while (!(SPI1->SR & 1));return SPI1->DR;}


總結(jié):

問(wèn)題出在思維的定勢(shì),先入為主的思想導(dǎo)致了錯(cuò)誤的思維,也體現(xiàn)了對(duì)問(wèn)題的分析能力,以及編碼的隨意性。哎血的教訓(xùn)啊。。。



關(guān)鍵詞: STM32SPI問(wèn)

評(píng)論


技術(shù)專區(qū)

關(guān)閉