STM32快速復習(八)SPI通信

文章目錄

  • 前言
  • 一、SPI是什么?SPI的硬件電路?SPI發送的時序?
  • 二、庫函數
  • 二、庫函數示例代碼
  • 總結


前言

SPI和IIC通信算是我在大學和面試中用的最多,問的最多的通信協議
IIC問到了,一般SPI也一定會問到。
SPI相對于IIC多了一個片選信號(CS)
SPI相對于IIC,最主要特點,傳輸速率增快,不需要等待下位機回復,有了片選信號,可以明確控制信號傳輸的單對單。所以,代碼相對于IIC也簡單一些。(很多時候,芯片不會有那么多的GPIO口給SPI用作片選信號)
IIC可以用兩根線連接多設備,SPI需要再增加片選線,假如連接3個設備,IIC只需要2根通信線,SPI則需要(3+n)條線,n為設備數量,也就是6根線。
在這里插入圖片描述


一、SPI是什么?SPI的硬件電路?SPI發送的時序?

SPI是什么?
SPI(Serial Peripheral Interface,串行外設接口)是由Motorola公司開發的一種通用數據總線,與IIC 差不多,也是為了實現主控芯片和各種外掛芯片之間的數據交流。SPI和IIC都是常用的接口協議,只是根據其不同的特點,應用場景有所不同。

SPI特點:SPI(Serial Peripheral Interface)是由Motorola公司開發的一種通用數據總線
四根通信線:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select)
同步,全雙工
支持總線掛載多設備(一主多從)

SPI沒有應答機制

硬件特點(參考上圖):所有SPI設備的SCK、MOSI、MISO分別連在一起
主機另外引出多條SS控制線,分別接到各從機的SS引腳
輸出引腳配置為推挽輸出,輸入引腳配置為浮空或上拉輸入

STM32的SPI電路:
STM32內部集成了硬件SPI收發電路,可以由硬件自動執行時鐘生成、數據收發等功能,減輕CPU的負擔
可配置8位/16位數據幀、高位先行/低位先行
時鐘頻率: fPCLK / (2, 4, 8, 16, 32, 64, 128, 256)
支持多主機模型、主或從操作
可精簡為半雙工/單工通信
支持DMA
兼容I2S協議

STM32F103C8T6 硬件SPI資源:SPI1、SPI2
在這里插入圖片描述
在這里插入圖片描述
***寄存器配合介紹: ***
**移位寄存器:**右側的數據一位一位地從MOSI輸出,MOSI的數據一位一位地移到左側數據位。
LSBFIRST控制位:用于控制移位寄存器是低位先行(1)還是高位先行(0)。
MISO和MOSI的交叉:用于切換主從模式。不交叉時為主機模式,交叉時為從機模式。
接收緩沖區、發送緩沖區:實際上分別就是接收數據寄存器RDR、發送數據緩沖區TDR。TDR和RDR占用同一個地址,統一叫作DR。移位寄存器空時,TXE標志位置1,TDR移入數據,下一個數據移入到TDR;移位寄存器接收完畢(同時也標志著移出完成),RXNE標志位置1,數據轉運到RDR,此時需要盡快讀出RDR,以防止被下一個數據覆蓋。
細節:SPI為全雙工同步通信,所以為一個移位寄存器、兩個緩沖區;IIC為單工通信,所以只需要一個移位寄存器、一個緩沖區;USRT為全雙工異步通信,所以需要兩個移位寄存器、兩個緩沖區,且這兩套分別獨立。
***控制邏輯介紹: ***
波特率發生器:本質是一個分頻器,用于產生SCK時鐘。輸入時鐘就是外設時鐘f =72MHz/36MHz。每產生一個時鐘,就移入/移出一個比特。SPI_CR1中的[BR2,BR1,BR0]用于產生分頻系數。
SPI_CR1:SPI控制寄存器1,下面簡單介紹一下。詳細可以參考中文數據手冊“23.5 SPI和I2S寄存器描述”一節。
SPE(SPI Enable):SPI使能,就是SPI_Cmd函數配置的位。
BR(Baud Rate):配置波特率,也就是SCK時鐘頻率。
MSTR(Master):配置主機模式(1)、從機(0)模式。
CPOL、CPHA:用于選擇SPI的四種模式。

簡化后:
在這里插入圖片描述
波特率發生器:用于產生SCK時鐘。
數據控制器:根據配置,控制SPI外設電路的運行。
字節交換過程:交換完畢,移位寄存器空,則TXE位置1、RXNE位置1,TDR會自動轉運數據到移位寄存器,RDR數據等待用戶讀取。
開關控制【代碼】:SPI外設使能。
GPIO【代碼】:用于各引腳的初始化。
從機使能引腳SS【代碼】:并不存在于SPI硬件外設中,實際使用隨便指定一個GPIO口(例如PA4)即可。在一主多從模式下,GPIO模擬SS是最佳選擇。

在實際書寫代碼的過程中,使用一個結構體便可以直接配置 波特率發生器 和 字節交換的默認模式,這是SPI外設內部便會自動工作,用戶額外需要關心的只是何時讀寫DR。下面介紹讀寫時序的流程,分別是性能更高、使用復雜的“主模式全雙工連續傳輸”,以及性能較低、常用且簡單易學的“非連續傳輸”:

不常用:
在這里插入圖片描述
本模式可以實現數據的連續傳輸。
連續寫入數據:只要TXE置1,就立馬進中斷寫入數據(會同時清除TXE位);當寫入到最后一個數據時,等待BSY位清除,發送流程完畢。
連續讀出數據:只要RXNE位置1,就立馬進中斷讀出數據(會同時清除RXNE位)。若不及時讀出,現有數據就會被新的數據覆蓋。
評價:連續數據流傳輸對于軟件的配合要求較高,需要在每個標志位產生后及時讀寫數據,整個發送和接收的流程是交錯的,但是傳輸效率是最高的。對傳輸效率有嚴格要求才會用到此模式,否則一般采用下面更為簡單的“非連續傳輸”。

常用:
在這里插入圖片描述

本模式對于程序設計非常友好。(示例代碼基于此)
字節交換流程:最開始等待TXE位置1,發送一個數據(會自動清除TXE);等待RXNE置1,讀取數據。再進行下一次的字節交換。
評價:非連續傳輸會損失數據傳輸效率,數據傳輸速率越快,損失越明顯。

SPI發送的時序
SPI通信的基礎是交換字節。也就是說,每次SPI通信的過程中,通過各自的MOSI、MISO線,主機和從機的寄存器會形成一個循環移位操作,每個比特的通信都是轉圈的循環移位,8個時鐘周期完整的交換一個字節。那么根據需求有選擇的忽略交換過來的數據,就可以實現(以主機舉例,從機同理)主機只發送、主機只接收、主從機交換數據這三類操作。

在這里插入圖片描述
工作原理:
波特率發生器上升沿:所有寄存器左移一位。
波特率發生器下降沿:將采樣輸入的數據放到寄存器的最低位。
重復8個時鐘周期,便可以實現主機和從機的數據交換。
注:實際上,何時移位、何時采樣、時鐘極性都是可以設置的,下面將介紹。
功能介紹:顯然存在資源浪費現象。
同時進行發送和接收:正常的交換字節。
只想發送、不想接收:不看接收過來的數據。
只想接收、不想發送:隨便發一個數據,比如0x00/0xFF。

時序舉例:SPI交換單個字節的時序:
起始條件和終止條件:起始條件是SS從高電平切換到低電平,終止條件是SS從低電平切換到高電平。
在這里插入圖片描述

交換一個字節:兩個配置位分別為CPOL(Clock Polarity, 時鐘極性)規定空閑狀態的時鐘高低電平、CPHA(Clock Phase, 時鐘相位)規定數據移入(數據采樣)、移出的時機。
總共有四種模式可以選擇,常用模式0,會配置一個就足夠,其他的只是改變時鐘電平。

  1. 【模式0】[CPOL,CPHA] = [0,0],SCK低電平為空閑狀態;SCK第一個邊沿(上升沿)移入數據,第二個邊沿(下降沿)移出數據。

  2. 【模式1】[CPOL,CPHA] = [0,1],SCK低電平為空閑狀態;SCK第一個邊沿移出數據,第二個邊沿移入數據。
    在這里插入圖片描述

  3. 【模式2】[CPOL,CPHA] = [1,0],SCK高電平為空閑狀態;SCK第一個邊沿移入數據,第二個邊沿移出數據。
    在這里插入圖片描述

  4. 【模式3】[CPOL,CPHA] = [1,1],SCK高電平為空閑狀態;SCK第一個邊沿移出數據,第二個邊沿移入數據。

在這里插入圖片描述
由于從機SPI協議由硬件控制,所以從機發送過來的數據,其數據變化邊沿都是緊貼著時鐘下降沿完成的。并且,如果最后接收完一個字節后時鐘仍為低電平,那么從機會繼續將下一個地址的數據發送過來,就實現了“連續地址讀”。

二、庫函數

SPI/I2S常用設置:
SPI_I2S_DeInit :將SPI或I2S外設恢復到默認的初始狀態。
SPI_Init 【必需】:初始化SPI(串行外設接口)外設,并配置其相關參數,包括數據傳輸模式、時鐘極性和相位、數據位長度等。
I2S_Init :初始化I2S(串行音頻接口)外設,并配置其相關參數,包括數據格式、數據位長度、時鐘極性和相位等。
SPI_StructInit :將SPI外設的配置結構體初始化為默認值。
I2S_StructInit :將I2S外設的配置結構體初始化為默認值。
SPI_Cmd 【必需】:使能或禁用SPI外設。
I2S_Cmd :使能或禁用I2S(串行音頻接口)外設。
SPI_I2S_SendData 【常用】:用于向SPI或I2S外設發送數據。但只是將數據送到發送緩沖區。
SPI_I2S_ReceiveData 【常用】:從SPI或I2S外設接收數據。但只是將數據從接收緩沖區讀出。
關于中斷及標志位【必需】:
SPI_I2S_GetFlagStatus :常用于非中斷函數。獲取SPI或I2S外設的特定標志位的狀態。常見的標志位包括傳輸完成標志(TXE或BTF)、接收緩沖區非空標志(RXNE)、傳輸錯誤標志(OVR、CRCERR等)以及其他特定功能的標志。
SPI_I2S_ClearFlag :常用于非中斷函數。用于軟件清除SPI或I2S外設的特定標志位。
SPI_I2S_ITConfig :配置SPI或I2S外設的中斷使能狀態。注意在使用中斷功能之前,還需要配置中斷優先級、編寫中斷服務程序以及使能全局中斷。
SPI_I2S_GetITStatus :常用于中斷函數。用于獲取SPI或I2S外設的特定中斷標志位的狀態。
SPI_I2S_ClearITPendingBit :常用于中斷函數。用于清除SPI或I2S外設的特定中斷標志位。
單獨參數的配置:
SPI_DataSizeConfig :配置SPI外設的數據位長度。
SPI_NSSInternalSoftwareConfig :配置SPI外設的NSS(多主機模式)的內部軟件控制模式。
SPI_SSOutputCmd :使能或禁用SPI外設的SS(片選信號)輸出功能。
SPI_BiDirectionalLineConfig :用于配置SPI外設的雙向數據線模式。
DMA配置(連續數據傳輸):
SPI_I2S_DMACmd :使能或禁用SPI或I2S外設的DMA傳輸。
CRC配置:
SPI_TransmitCRC :向SPI外設發送CRC(循環冗余校驗)值。
SPI_CalculateCRC :用于計算SPI外設接收到的數據的CRC(循環冗余校驗)值。
SPI_GetCRC :用于從SPI外設獲取計算得到的CRC(循環冗余校驗)值。
SPI_GetCRCPolynomial :用于從SPI外設獲取當前配置的CRC(循環冗余校驗)多項式值

二、庫函數示例代碼

代碼如下(示例):

 #include "stm32f10x.h"                  // Device header//SPI-SS引腳寫操作
void SPI_User_W_SS(uint8_t BitValue){GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);}//SPI初始化
void SPI_User_Init(void){//1.開啟外設時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//GPIO時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //SPI1時鐘//2.初始化端口//初始化SS-推挽輸出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);//初始化CLK、MOSI-外設復用推挽輸出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);//初始化MISO-上拉輸入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);//3.配置SPISPI_InitTypeDef SPI_InitStructure;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //APB2的2分頻-36MHzSPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                       //第一個邊沿采樣,第二個邊沿輸出SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                         //時鐘空閑時低電平SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                  //數據位寬8bitSPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //SPI雙線全雙工SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                 //高位先行SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                      //主機模式SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                          //軟件自定義片選信號SPI_InitStructure.SPI_CRCPolynomial = 0x0007;                      //CRC用不到,所以默認值7SPI_Init(SPI1, &SPI_InitStructure);//4.SPI使能SPI_Cmd(SPI1, ENABLE);SPI_User_W_SS(1);//默認不選中從機
}//SPI起始信號
void SPI_User_Start(void){SPI_User_W_SS(0);}//SPI終止信號
void SPI_User_Stop(void){SPI_User_W_SS(1);}//SPI交換一個字節(模式0)uint8_t SPI_User_SwapByte(uint8_t SendByte){while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET); //等待TXE置1SPI_I2S_SendData(SPI1,SendByte);                          //發送數據到TDRwhile(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//等待RNXE置1return SPI_I2S_ReceiveData(SPI1);                         //從RDR接收數據
}

流程:開時鐘 — 配置串口 — 配置SPI — 開啟SPI使能 — 交換數據 — 關使能


總結

IIS是一種用于將數字音頻設備連接在一起的電氣串行總線接口標準。 在工作中音頻采集,AD和主芯片之間的通信都是使用IIS進行的,它用于在電子設備中的集成電路之間傳送PCM音頻數據。在IIS總線上,只能同時存在一個主設備和發送設備。主設備可以是發送設備,也可以是接收設備,或是協調發送設備和接受設備的其它控制設備。在IIS系統中,提供時鐘的設備為主設備。(知道有這么個東西就行,工作和大學沒用到,我也不會)

關于是否清除標志位。手冊上寫明了TXE和RXNE“由硬件置位并由軟件清除”,但是這并不代表需要一條專門的語句來清除標志位,比如SPI中就是讀寫數據的過程中就自動清除了,所以具體還需要查看數據手冊的描述。

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

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

相關文章

heml之樣式布局技巧博客

在編寫關于 HEML(HTML CSS JavaScript)的樣式布局技巧博客時,可以涵蓋很多不同的方面 1. 響應式設計 介紹媒體查詢(Media Queries)以及如何根據設備尺寸調整樣式。使用百分比寬度、視口單位(vw、vh&…

含并行連結的網絡

一、Inception塊 1、白色部分通過降低通道數來控制模型復雜度,藍色做特征提取工作,每條路上的通道數可能不同,大概我們會把更重要的那部分特征分配更多的通道數 2、Inception只改變高寬,不改變通道數 3、在不同的情況下需要選擇…

pin是什么?管腳

1.平面分割 1)啟動Allegro PCB design ,打開.brd。深色部分屬于一個net,要做一下修改,將上面的pin包含進shape中,i進行a,b兩步操作,刪除以前存在的Anti Etch下的line,再將其進行補齊 使它保住上…

【幀中繼實驗-ensp】

實驗要求 在R1上開啟一個點對點子接口,用于連接 R1–R2,兩端IP地址為12.1.1.x 。開啟一個多點子接口 ,用于連接R1–R3,R4,兩段IP地址為134.1.1.x。 具體DLCI分配和映射關系如下: R1 102 R2 201—動態映射…

python獲取海康威視所有攝像頭的OSD通道名稱

讀取IP地址的txt文檔 根據IP地址獲取監控攝像頭的OSD通道名稱 # codingutf-8 import os import time import requests from requests.auth import HTTPBasicAuth, HTTPDigestAuth import xml.etree.ElementTree as ET #注意:和ip.txt放在一個文件夾,會生…

論文略讀:Can Long-Context Language Models Subsume Retrieval, RAG, SQL, and More?

202406 arxiv 1 intro 傳統上,復雜的AI任務需要多個專門系統協作完成。 這類系統通常需要獨立的模塊來進行信息檢索、問答和數據庫查詢等任務大模型時代,尤其是上下文語言模型(LCLM)時代,上述問題可以“一體化”完成…

【程序大俠傳】大表分庫分表切換數據庫類型導致pagehelper生成sql語法報錯

前序 代碼劍宗等級分明,其門下弟子等級劃分如下: 入門弟子 剛剛拜入代碼劍宗,學習基礎編程語言和基本劍法(語法和基礎概念)。他們的代碼還顯得生澀,但已經開始展現出對優雅代碼的追求。 江湖小蝦 初步掌握…

《python程序語言設計》2018版第5章第53題利用turtle繪制sin和cos函數 sin藍色,cos紅色和52題類似

直接上題和代碼 5.53 (Turtle:繪制sin和cos函數)編寫程序繪制藍色的sin函數和紅色的cos函數。 代碼和結果 turtle.speed(10) turtle.penup() # sin 用藍色 turtle.color("blue") #這道題和上道題一樣,先把turtle放到起始…

架構面試-數據庫優化問題

文章目錄 如何定位慢查詢1. 開啟慢查詢日志MySQL示例:PostgreSQL示例: 2. 分析慢查詢日志MySQL:PostgreSQL: 3. 使用數據庫性能工具MySQL:PostgreSQL: 4. 優化慢查詢5. 監控與持續優化 sql語句執行的很慢&a…

從0到1制作單只鰲蝦運動軌跡追蹤軟件

前言 需要準備windows10操作系統,python3.11.9,cuDNN8.9.2.26,CUDA11.8,paddleDetection2.7 流程: 準備數據集-澳洲鰲蝦VOC數據集 基于RT-DETR目標檢測模型訓練導出onnx模型進行python部署平滑濾波處理視頻幀保留的…

簡介時間復雜度

好了,今天我們來了解一下,我們在做練習題中常出現的一個名詞。時間復雜度。我相信大家如果有在練習過題目的話。對這個名詞應該都不陌生吧。但是可能很少的去思考它是干什么的代表的什么意思。反正我以前練習的時候就是這樣。我只知道有這么一個名詞在題…

【全面講解下iPhone新機官網驗機流程】

🎥博主:程序員不想YY啊 💫CSDN優質創作者,CSDN實力新星,CSDN博客專家 🤗點贊🎈收藏?再看💫養成習慣 ?希望本文對您有所裨益,如有不足之處,歡迎在評論區提出…

MybatisPlus實現插入/修改數據自動設置時間

引言 插入數據時自動設置當前時間,更新數據時自動修改日期為修改時的日期。 使用MybatisPlus的擴展接口MetaObjectHandler 步驟 實現接口 實體類加注解 實現接口 package com.example.vueelementson.common;import com.baomidou.mybatisplus.core.handlers.M…

C++ 模版進階

目錄 前言 1. 非類型模版參數 1.1 概念與講解 1.2 array容器 2. 模版的特化 2.1 概念 2.2 函數模版特化 2.3 類模版特化 2.3.1 全特化 2.3.2 偏特化 3.模版的編譯分離 3.1 什么是分離編譯 3.2 模版的分離編譯 3.3 解決方法 4. 模版總結 總結 前言 本篇文章主要…

包/final/權限修飾符/代碼塊

包package 1、包的作用 包用來管理不同的類。 2、包名 包名要全部小寫,一般是域名反寫,如com.liu。在Java中,java解釋器會將package中的.解釋為目錄分隔符/,也就是說該文件的目錄結構為:...com/liu/... 3、全類名…

1.pwn的匯編基礎(提及第一個溢出:整數溢出)

匯編掌握程度 能看懂就行,絕大多數情況不需要真正的編程(shellcode題除外) 其實有時候也不需要讀匯編,ida F5 通常都是分析gadget,知道怎么用, 調試程序也不需要分析每一條匯編指令,單步執行然后查看寄存器狀態即可 但…

Text2SQL提問中包括時間的實戰方案

大家好,我是herosunly。985院校碩士畢業,現擔任算法研究員一職,熱衷于機器學習算法研究與應用。曾獲得阿里云天池比賽第一名,CCF比賽第二名,科大訊飛比賽第三名。擁有多項發明專利。對機器學習和深度學習擁有自己獨到的見解。曾經輔導過若干個非計算機專業的學生進入到算法…

實現多數相加,但是傳的參不固定

一、情景 一般實現的加法和減法等簡單的相加減函數的話。一般都是寫好固定傳的參數。比如: function add(a,b) {return a b;} 這是固定的傳入倆個,如果是三個呢,有人說當然好辦! 這樣寫不就行了! function add(a…

vue中自定義設置多語言(包括使用vue-i18n),并且運行js腳本自動生成多語言文件

在項目中需要進行多個國家語言的切換時,可以用到下面方法其中一個 一、自定義設置多語言 方法一: 可以自己編寫一個設置多語言文件 在項目新建js文件,命名為:language.js,代碼如下 // language.js 文檔 let languagePage {CN…

聊一下Maven打包的問題(jar要發布)

文章目錄 一、問題和現象二、解決方法(1)方法一、maven-jar-pluginmaven-dependency-plugin(2)方法二、maven-assembly-plugin 一、問題和現象 現在的開發一直都是用spring boot,突然有一天,要自己開發一個…