最近要用到STM32的SPI從機(jī)模式,從其他板子讀SPI數(shù)據(jù)過(guò)來(lái),踩了2天坑,記錄一下過(guò)程。
(因?yàn)閔al庫(kù)提供了三種函數(shù),我調(diào)試的過(guò)程是阻塞、中斷、DMA依次來(lái)調(diào)試學(xué)習(xí)的,這份代碼為使用DMA方式的代碼。)
軟件:keil5、STM32CubeMX
硬件:兩塊STM32F103C8T6最小系統(tǒng)
實(shí)現(xiàn)功能:兩塊板子進(jìn)行SPI通信,一主一從,都是使用的SPI1。
代碼下載github:https://github.com/wyfroom/SPI_Master_Slave_STM32(第一次編程過(guò)程中使用git管理代碼)
代碼下載藍(lán)奏云:https://wwzr.lanzout.com/b04885ouf 密碼:372j
強(qiáng)調(diào)!?。。。。。。。。?!強(qiáng)調(diào)!?。。。。。。。。。?!強(qiáng)調(diào)?。。。。。。。。。。。?!
如果你SPI通了,但是莫名其妙數(shù)據(jù)亂碼、能發(fā)不能收等問(wèn)題,啥都別干了,先把杜邦線(xiàn)換新,一共5根線(xiàn),一根共地線(xiàn),四根SPI線(xiàn)。
一、SPI主機(jī)配置
基礎(chǔ)的工程配置,這邊就不貼圖了,可以看這個(gè)有詳細(xì)的步驟:http://t.csdn.cn/Wpcpk
直接看spi的配置,主要注意以下幾點(diǎn):
- SPI模式選擇
- 片選選擇
- 大端小端選擇
- 通信速率
- 采樣模式配置(CPOL、CPHA)
- CRC選擇
如果要用SPI中斷,要勾選中斷。
如果要用DMA,要對(duì)DMA進(jìn)行配置。
補(bǔ)充:片選還是要選,不然高速傳輸會(huì)出問(wèn)題。
二、SPI從機(jī)配置
從機(jī)配置僅模式選擇和主機(jī)不同,其他都一樣且必須一樣。
如果使用中斷,要勾選:
DMA配置:(和主機(jī)一樣)
補(bǔ)充:片選還是要選,不然高速傳輸時(shí)會(huì)出問(wèn)題。
三、雙機(jī)通信
HAL庫(kù)提供了三種SPI調(diào)用方式。都試了一遍,最后還是選用了DMA,高效,簡(jiǎn)潔。
//阻塞方式使用SPI
HAL_SPI_Transmit()
HAL_SPI_Receive()
HAL_SPI_TransmitReceive()
//中斷方式使用SPI
HAL_SPI_Transmit_IT()
HAL_SPI_Receive_IT()
HAL_SPI_TransmitReceive_IT()
//DMA方式使用SPI
HAL_SPI_Transmit_DMA()
HAL_SPI_Receive_DMA()
HAL_SPI_TransmitReceive_DMA()
1 輪詢(xún)+中斷(低速)
主機(jī)輪詢(xún),從機(jī)中斷。
這個(gè)我就不演示了,就正常流程,注意就行,在main里啟動(dòng)中斷,在中斷函數(shù)里再次啟動(dòng)中斷。
//main里啟動(dòng)中斷
HAL_SPI_TransmitReceive_IT(&hspi1, sendData, receiveData, 8);
//中斷回調(diào)函數(shù)
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
// 數(shù)據(jù)發(fā)送完成回調(diào)函數(shù)
if (hspi == &hspi1)
{
HAL_SPI_TransmitReceive_IT(&hspi1, sendData, receiveData, 8);
}
}
2 輪詢(xún)+DMA(低速)
主機(jī)使用阻塞函數(shù),從機(jī)使用DMA函數(shù)。(原因是我試了主從全部使用DMA的話(huà),速度太快了,會(huì)卡死和數(shù)據(jù)傳輸亂碼。解決啦,可以看問(wèn)題一,這一部分還是演示輪詢(xún)+DMA)
主機(jī):
從機(jī):
debug測(cè)試:
3 DMA+DMA(高速)
之前高速使用時(shí)出現(xiàn)了程序卡死和數(shù)據(jù)亂碼的現(xiàn)象。(高速使用:用阻塞函數(shù)while里不加延時(shí)、主從都用中斷、主從都用DMA)
解決方法如下:
- 1 片選要開(kāi)啟。我直接把兩個(gè)板子的硬件片選打開(kāi),兩邊都使用DMA方式全雙工發(fā)送讀取,數(shù)據(jù)不在亂碼,只是接收到的第一個(gè)數(shù)據(jù)不一定是發(fā)送的第一個(gè)數(shù)據(jù)。
- 2 從機(jī)要比主機(jī)先啟動(dòng)程序。 解決上一步數(shù)據(jù)順序不對(duì)的問(wèn)題。在主機(jī)DMA程序啟動(dòng)前加一個(gè)延時(shí)2s。
直接Debug:(模擬實(shí)際上電,debug先點(diǎn)從機(jī)啟動(dòng),再點(diǎn)主機(jī)啟動(dòng))
4 開(kāi)啟CRC校驗(yàn)(自選)
CRC計(jì)算生成的校驗(yàn)值可以用于檢測(cè)數(shù)據(jù)在傳輸或存儲(chǔ)過(guò)程中是否發(fā)生了錯(cuò)誤或損壞。
開(kāi)啟CRC后,使用DMA函數(shù)的話(huà),SIZE要加一:
HAL_SPI_TransmitReceive_DMA(&hspi1, sendData, receiveData, 8+1);
四、遇到的問(wèn)題
1 高速使用時(shí),程序卡死,或者數(shù)據(jù)出錯(cuò)(已解決)
-
主機(jī)中斷模式發(fā)送,從機(jī)中斷模式接收,不停的收發(fā)清空標(biāo)志,數(shù)據(jù)就會(huì)亂,可能是傳的太快了??想當(dāng)于是全速的在收發(fā)? 非得主機(jī)用輪詢(xún)的方式,間隔個(gè)1ms什么的來(lái)讀取,那這SPI速度咋算的?
-
主機(jī)DMA發(fā),從機(jī)DMA收,直接死機(jī),DMA中斷被刷爆,while里的程序沒(méi)機(jī)會(huì)執(zhí)行,可以屏蔽掉DMA中斷,程序不會(huì)在死機(jī),但是,數(shù)據(jù)會(huì)亂。
-
加了CRC好像要好一點(diǎn),但還是很多亂碼,碰運(yùn)氣碰好的。這能行嗎?是SPI就不是這么用的嗎?還是說(shuō)這事高速傳輸?shù)墓残詥?wèn)題。
-
終于解決:
- 1 片選要開(kāi)啟。我直接把兩個(gè)板子的硬件片選打開(kāi),兩邊都使用DMA方式全雙工發(fā)送讀取,數(shù)據(jù)不在亂碼,只是接收到的第一個(gè)數(shù)據(jù)不一定是發(fā)送的第一個(gè)數(shù)據(jù)。
- 2 從機(jī)要比主機(jī)先啟動(dòng)程序。 解決上一步數(shù)據(jù)順序不對(duì)的問(wèn)題。在主機(jī)DMA程序啟動(dòng)前加一個(gè)延時(shí)2s。
- 3 CRC,開(kāi)不開(kāi)沒(méi)影響。
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-580055.html
?
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-580055.html
2 數(shù)據(jù)莫名其妙亂碼,主機(jī)發(fā)送正常,接收亂碼等
- 杜邦線(xiàn),真的會(huì)出問(wèn)題的,換新,5根線(xiàn),全部換新。再試試
到了這里,關(guān)于【SPI】STM32 SPI 雙機(jī)通信,SPI從機(jī)模式使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!