STM32-SPI通信協議

串行外設接口SPI(Serial Peripheral Interface)是由Motorola公司開發的一種通用數據總線。
????????在某些芯片上,SPI接口可以配置為支持SPI協議或者支持I2S音頻協議。 SPI接口默認工作在SPI方式,可以通過軟件把功能從SPI模式切換到I2S模式,具體需參考操作手冊
????????串行外設接口(SPI)允許芯片與外部設備以半/全雙工、同步、串行方式通信。此接口可以被配置成主模式,并為外部從設備提供通信時鐘(SCK)。接口還能以多主配置方式工作。
它可用于多種用途,包括使用一條雙向數據線的雙線單工同步傳輸,還可使用CRC校驗的可靠通信。
????????I2S也是一種3引腳的同步串行接口通訊協議。它支持四種音頻標準,包括飛利浦I2S標準, MSB和LSB對齊標準,以及PCM標準。它在半雙工通訊中,可以工作在主和從2種模式下。當它作為主設備時,通過接口向外部的從設備提供時鐘信號。

SPI特點

  1. 四根通信線:SCK、MOSI、MISO、SS
  2. 支持全雙工同步傳輸
  3. 支持總線掛載多設備(一主多從)
  4. 支持多主機模型,主或從操作
  5. 支持DMA
  6. 可配置8位/16位數據幀
  7. 時鐘頻率:f(PCLK)/(2, 4, 8, 16, 32, 64, 128, 256)
  8. 兼容I2S協議等

電路連接

  • 所有SPI設備的SCK、MOSI、MISO、分別連接在一起。
  • 主機另外引出多條SS控制線,分別接到各從機的SS引腳,需要找誰通信就置誰的SS為低電平,同一時間主機只能選擇一個從機。
  • 輸出引腳配置為推挽輸出,輸入引腳配置為浮空或上拉輸入。
  • 所有設備需要共地。

?SPI移位示意圖

?SPI時序

起始條件:SS從高電平切換到地點哦

終止條件:SS從低電平切換到高電平

SPI模式

SPI有四種模式通過CPOL時鐘極性和CPHA時鐘相位來定義

  • CPOL=0,表示當SCLK=0時處于空閑態,所以有效狀態就是SCLK處于高電平時
  • CPOL=1,表示當SCLK=1時處于空閑態,所以有效狀態就是SCLK處于低電平時

  • CPHA=0,在時鐘的第一個跳變沿(上升沿或下降沿)進行數據采樣。在第2個邊沿發送數據
  • CPHA=1,在時鐘的第二個跳變沿(上升沿或下降沿)進行數據采樣。在第1個邊沿發送數據

?軟件SPI設置時序單元

數據采樣==移入數據

模式0

模式1

模式2
模式3

軟件SPI代碼

以模式0為例,只需對相位和極性修改即可得到其他模式


//SPI寫SS引腳電平
void MySPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);//根據BitValue,設置SS引腳的電平
}//SPI寫SCK引腳電平
void MySPI_W_SCK(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);//根據BitValue,設置SCK引腳的電平
}//SPI寫MOSI引腳電平
void MySPI_W_MOSI(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);		//根據BitValue,設置MOSI引腳的電平,BitValue要實現非0即1的特性
}//SPI讀MISO引腳電平
uint8_t MySPI_R_MISO(void)
{return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);			//讀取MISO電平并返回
}//SPI初始化
void MySPI_Init(void)
{/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//開啟GPIOA的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);			//將PA4、PA5和PA7引腳初始化為推挽輸出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);					//將PA6引腳初始化為上拉輸入/*設置默認電平*/MySPI_W_SS(1);											//SS默認高電平MySPI_W_SCK(0);											//SCK默認低電平
}//SPI起始
void MySPI_Start(void)
{MySPI_W_SS(0);				//拉低SS,開始時序
}//SPI終止
void MySPI_Stop(void)
{MySPI_W_SS(1);				//拉高SS,終止時序
}//SPI交換傳輸一個字節,使用SPI模式0
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{uint8_t i, ByteReceive = 0x00;		            //定義接收的數據,并賦初值0x00,此處必須賦初值0x00,后面會用到for (i = 0; i < 8; i ++)						//循環8次,依次交換每一位數據{MySPI_W_MOSI(ByteSend & (0x80 >> i));		//使用掩碼的方式取出ByteSend的指定一位數據并寫入到MOSI線MySPI_W_SCK(1);								//拉高SCK,上升沿移出數據if (MySPI_R_MISO() == 1){ByteReceive |= (0x80 >> i);}	//讀取MISO數據,并存儲到Byte變量//當MISO為1時,置變量指定位為1,當MISO為0時,不做處理,指定位為默認的初值0MySPI_W_SCK(0);								//拉低SCK,下降沿移入數據}return ByteReceive;								//返回接收到的一個字節數據//	for(i=0;i<8;i++)
//	{
//		MySPI_W_MOSI(ByteSend & 0x80);
//		ByteSend<<=1;
//		MySPI_W_SCK(1);
//		if(MySPI_R_MISO()==1){ByteSend|=0x01;}
//		MySPI_W_SCK(0);
//	}
//	 return ByteSend;
}

硬件SPI

SPI采用高位先行的模式

SPI框圖

數據寄存器DR分為TDR和RDR

1.當需要發送數據時,第一個數據寫入TDR,當移位寄存器沒有數據進行移位時,TDR數據會立刻轉入移位寄存器開始移位。

轉入時刻會置狀態寄存器的TXE位1,表示發送寄存器空,當檢查TXE為1后,下一個數據便可寫入TDR等候。

2.移位寄存器檢測到有數據也會自動產生時鐘將數據移出,在移出的過程中MISO的數據也會移入。

3.一旦數據移出完成,數據移入也完成了,這是移位寄存器就會將數據整體轉出到RDR,

這時會置狀態寄存器RXNE為1,表示接收寄存器非空。當檢測到RXNE為1就需在下一個數據到來之前將數據讀出來,不然數據會被覆蓋。

SPI時序框圖
連續傳輸

模式三

非連續傳輸?

硬件SPI代碼
?
#include "stm32f10x.h"                  // Device header//SPI寫SS引腳電平,SS仍由軟件模擬
void MySPI_W_SS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);//根據BitValue,設置SS引腳的電平
}//SPI初始化
void MySPI_Init(void)
{/*開啟時鐘*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//開啟GPIOA的時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);	//開啟SPI1的時鐘/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);					//將PA4引腳初始化為推挽輸出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);				//將PA5和PA7引腳初始化為復用推挽輸出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);					//將PA6引腳初始化為上拉輸入/*SPI初始化*/SPI_InitTypeDef SPI_InitStructure;						//定義結構體變量SPI_InitStructure.SPI_Mode = SPI_Mode_Master;			//模式,選擇為SPI主模式SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	//方向,選擇2線全雙工SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//數據寬度,選擇為8位SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;		//先行位,選擇高位先行SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;	//波特率分頻,選擇128分頻SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;				//SPI極性,選擇低極性SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;			//SPI相位,選擇第一個時鐘邊沿采樣,極性和相位決定選擇SPI模式0SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;				//NSS,選擇由軟件控制SPI_InitStructure.SPI_CRCPolynomial = 7;			//CRC多項式,暫時用不到,給默認值7SPI_Init(SPI1, &SPI_InitStructure);				//將結構體變量交給SPI_Init,配置SPI1/*SPI使能*/SPI_Cmd(SPI1, ENABLE);									//使能SPI1,開始運行/*設置默認電平*/MySPI_W_SS(1);											//SS默認高電平
}//SPI起始
void MySPI_Start(void)
{MySPI_W_SS(0);				//拉低SS,開始時序
}//SPI終止
void MySPI_Stop(void)
{MySPI_W_SS(1);				//拉高SS,終止時序
}//SPI交換傳輸一個字節,使用SPI模式0
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != SET);	//等待發送數據寄存器空SPI_I2S_SendData(SPI1, ByteSend);				//寫入數據到發送數據寄存器,開始產生時序while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != SET);//等待接收數據寄存器非空return SPI_I2S_ReceiveData(SPI1);							//讀取接收到的數據并返回
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/718165.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/718165.shtml
英文地址,請注明出處:http://en.pswp.cn/news/718165.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python·算法·每日一題(3月4日)最長公共前綴

題目 編寫一個函數來查找字符串數組中的最長公共前綴。 如果不存在公共前綴&#xff0c;返回空字符串 “”。 示例 示例 1&#xff1a; 輸入&#xff1a;strs ["flower","flow","flight"] 輸出&#xff1a;"fl"示例 2&#xff1a;…

【數據結構與算法】常見排序算法(Sorting Algorithm)

文章目錄 相關概念1. 冒泡排序&#xff08;Bubble Sort&#xff09;2. 直接插入排序&#xff08;Insertion Sort&#xff09;3. 希爾排序&#xff08;Shell Sort&#xff09;4. 直接選擇排序&#xff08;Selection Sort&#xff09;5. 堆排序&#xff08;Heap Sort&#xff09;…

【腦科學相關合集】有關腦影像數據相關介紹的筆記及有關腦網絡的筆記合集

【腦科學相關合集】有關腦影像數據相關介紹的筆記及有關腦網絡的筆記合集 前言腦模板方面相關筆記清單 基于腦網絡的方法方面數據基本方面 前言 這里&#xff0c;我將展開有關我自己關于腦影像數據相關介紹的筆記及有關腦網絡的筆記合集。其中&#xff0c;腦網絡的相關論文主要…

【錯誤處理】【Hive】【Spark】ERROR FileFormatwriter: Aborting job null.

問題背景 近日&#xff0c;使用 Spark 在讀寫 Hive 表時發生了報錯&#xff1a;Aborting job null&#xff0c;如果怎么都使用不了那張表的話&#xff0c;大概率是那張表有臟數據&#xff0c;導致整張表無法正常使用。 ERROR FileFormatwriter: Aborting job null.解決方法 …

SpringBoot 如何快速過濾出一次請求的所有日志?

前言 在現網出現故障時&#xff0c;我們經常需要獲取一次請求流程里的所有日志進行定位。如果請求只在一個線程里處理&#xff0c;則我們可以通過線程ID來過濾日志&#xff0c;但如果請求包含異步線程的處理&#xff0c;那么光靠線程ID就顯得捉襟見肘了。 華為IoT平臺&#x…

《自然》:人工智能在創造性思維方面超越人類

發散性思維被認為是創造性思維的指標。ChatGPT-4 在三項有151名人類參與的**發散思維測試中&#xff0c;**展現出比人類更高水平的創造力&#xff0c;結果顯示人工智能在創意領域持續發展。 發散性思維的特點是能夠針對沒有預期解決方案的問題提出獨特的解決方案&#xff0c;例…

TOMCAT的安裝與基本信息

一、TOMCAT簡介 Tomcat 服務器是一個免費的開放源代碼的Web 應用服務器&#xff0c;屬于輕量級應用服務器&#xff0c;在中小型系統和并發訪問用戶不是很多的場合下被普遍使用&#xff0c;是開發和調試JSP 程序的首選。對于一個初學者來說&#xff0c;可以這樣認為&#xff0c…

IO 與 NIO

優質博文&#xff1a;IT-BLOG-CN 一、阻塞IO / 非阻塞NIO 阻塞IO&#xff1a;當一條線程執行read()或者write()方法時&#xff0c;這條線程會一直阻塞直到讀取到了一些數據或者要寫出去的數據已經全部寫出&#xff0c;在這期間這條線程不能做任何其他的事情。 非阻塞NIO&…

記錄踩過的坑-macOS下使用VS Code

目錄 切換主題 安裝插件 搭建Python開發環境 裝Python插件 配置解釋器 打開項目 打開終端 切換主題 安裝插件 方法1 方法2 搭建Python開發環境 裝Python插件 配置解釋器 假設解釋器已經通過Anaconda建好&#xff0c;只需要在VS Code中關聯。 打開項目 打開終端

ArmV8架構

Armv8/armv9架構入門指南 — Armv8/armv9架構入門指南 v1.0 documentation 上面只是給了一個比較好的參考文檔 其他內容待補充

網絡-httpclient調用https服務端繞過證書的方法

httpclient調用https服務端繞過證書的方法 在日常開發或者測試中&#xff0c;通常會遇到需要用httpclient客戶端調用對方http是服務器的場景&#xff0c;由于沒有證書&#xff0c;所以直接是無法調用的。采用下面的方法可以繞過證書驗證&#xff1a; TrustManager[] trustAll…

AutoSAR(基礎入門篇)13.5-Mcal Mcu時鐘的配置

目錄 一、EB的Mcu模塊結構 二、時鐘的配置 對Mcu的配置主要就是其時鐘樹的配置,但是EB將GTM、ERU等很多重要的模塊也都放在了Mcu里面做配置,所以這里的Mcu是一個很龐大的模塊, 我們目前只講時鐘樹的部分 一、EB的Mcu模塊結構 1. 所有的模塊都基本上是這么些配置類別,Mc…

單詞級文本攻擊—論文閱讀

TAAD2.2論文概覽 0.前言1-101.Bridge the Gap Between CV and NLP! A Gradient-based Textual Adversarial Attack Frameworka. 背景b. 方法c. 結果d. 論文及代碼 2.TextHacker: Learning based Hybrid Local Search Algorithm for Text Hard-label Adversarial Attacka. 背景b…

閱讀筆記 | Transformers in Time Series: A Survey

閱讀論文&#xff1a; Wen, Qingsong, et al. “Transformers in time series: A survey.” arXiv preprint arXiv:2202.07125 (2022). 這篇綜述主要對基于Transformer的時序建模方法進行介紹。論文首先簡單介紹了Transformer的基本原理&#xff0c;包括位置編碼、多頭注意力機…

OPENAI SORA:未來視頻創作的新引擎——淺析其背后的人工智能算法

Sora - 探索AI視頻模型的無限可能 隨著人工智能技術的飛速發展&#xff0c;AI視頻模型已成為科技領域的新熱點。而在這個浪潮中&#xff0c;OpenAI推出的首個AI視頻模型Sora&#xff0c;以其卓越的性能和前瞻性的技術&#xff0c;引領著AI視頻領域的創新發展。本文將探討SORA的…

回歸預測 | Matlab實現RIME-BP霜冰算法優化BP神經網絡多變量回歸預測

回歸預測 | Matlab實現RIME-BP霜冰算法優化BP神經網絡多變量回歸預測 目錄 回歸預測 | Matlab實現RIME-BP霜冰算法優化BP神經網絡多變量回歸預測預測效果基本描述程序設計參考資料 預測效果 基本描述 1.Matlab實現RIME-BP霜冰算法優化BP神經網絡多變量回歸預測&#xff08;完整…

自動化測試介紹、selenium用法(自動化測試框架+爬蟲可用)

文章目錄 一、自動化測試1、什么是自動化測試&#xff1f;2、手工測試 vs 自動化測試3、自動化測試常見誤區4、自動化測試的優劣5、自動化測試分層6、什么項目適合自動化測試 二、Selenuim1、小例子2、用法3、頁面操作獲取輸入內容模擬點擊清空文本元素拖拽frame切換窗口切換/標…

十五 超級數據查看器 講解稿 外觀設置

十五 超級數據查看器 講解稿 外觀設置 視頻講座地址 講解稿全文: 大家好&#xff0c;今天講解超級數據查看器,詳情界面的外觀設置。 首先&#xff0c;我們打開超級數據查看器。 本節課以成語詞典為例來做講述。 我們打開成語詞典這個表&#xff0c;隨便選一條記錄點擊&#x…

AutoSAR(基礎入門篇)13.4-Mcal Dio代碼分析

目錄 一、文件結構 二、動態代碼 1、arxml文件 2、Dio_Cfg.h 3、Dio_PBCfg.c 4、小結

【虛擬機安裝centos7后找不到網卡問題】

最近開始學習linux&#xff0c;看著傳智播客的教學視頻學習&#xff0c;里面老師用的是centos6.5&#xff0c;我這邊裝的是centos7最新版的 結果到了網絡配置的這一節&#xff0c;卡了我好久。 我在centos一直找不到我的網卡eth0&#xff0c;只有一個回環網口&#xff0c;在/…