STM32 SPI通信(硬件)

一、SPI外設簡介

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

二、SPI框圖

1、2、3、4、5:主要是實現數據連續進入。

6、7、8、9、10:控制邏輯,寄存器位,控制什么部分,有什么效果等等

(3):移位寄存器,首先右邊的數據低位一位位的從MOSI移出去。MISO的數據一位位的移入到左邊的數據高位。顯然是一個低位先行的配置。由(5)來控制:0——高位先行;1——低位先行。

(1):MISO和MOSI交叉了,主要是進行主從模式引腳變換的,SPI作為主機時候,交叉就不用。作為從機時,就需要使用到交叉的這個路線(圖上MISO的箭頭反了)。

(2)、(4):分別為RDR和TDR。

三、傳輸模式

注:

連續傳輸和非連續傳輸的區別,主要體現在當TXE為1時,連續傳輸會把下一個數據放在TDR里面候著。而非連續傳輸時先等第一個時序結束,再把第二個放在DR里面。

四、代碼部分

注:SCK和MOSI是硬件外設控制的輸出信號,配置為復用推挽輸出

? ? ? ?MISO是硬件外設輸入信號,配置為上拉輸入

? ? ? ?CS(SS)是軟件控制的輸出信號,配置為通用推挽輸出

//寫DR數據寄存器
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
//讀DR數據寄存器
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);

?MySPI.c

#include "stm32f10x.h"                  // Device header/*** 函    數:SPI寫SS引腳電平,SS仍由軟件模擬* 參    數:BitValue 協議層傳入的當前需要寫入SS的電平,范圍0~1* 返 回 值:無* 注意事項:此函數需要用戶實現內容,當BitValue為0時,需要置SS為低電平,當BitValue為1時,需要置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* 參    數:ByteSend 要發送的一個字節* 返 回 值:接收的一個字節*/
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);								//讀取接收到的數據并返回
}

W5Q64.c

#include "stm32f10x.h"                  // Device header
#include "MySPI.h"
#include "W25Q64_Ins.h"/*** 函    數:W25Q64初始化* 參    數:無* 返 回 值:無*/
void W25Q64_Init(void)
{MySPI_Init();					//先初始化底層的SPI
}/*** 函    數:W25Q64讀取ID號* 參    數:MID 工廠ID,使用輸出參數的形式返回* 參    數:DID 設備ID,使用輸出參數的形式返回* 返 回 值:無*/
void W25Q64_ReadID(uint8_t *MID, uint16_t *DID)
{MySPI_Start();								//SPI起始MySPI_SwapByte(W25Q64_JEDEC_ID);			//交換發送讀取ID的指令*MID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);	//交換接收MID,通過輸出參數返回*DID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);	//交換接收DID高8位*DID <<= 8;									//高8位移到高位*DID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE);	//或上交換接收DID的低8位,通過輸出參數返回MySPI_Stop();								//SPI終止
}/*** 函    數:W25Q64寫使能* 參    數:無* 返 回 值:無*/
void W25Q64_WriteEnable(void)
{MySPI_Start();								//SPI起始MySPI_SwapByte(W25Q64_WRITE_ENABLE);		//交換發送寫使能的指令MySPI_Stop();								//SPI終止
}/*** 函    數:W25Q64等待忙* 參    數:無* 返 回 值:無*/
void W25Q64_WaitBusy(void)
{uint32_t Timeout;MySPI_Start();								//SPI起始MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);				//交換發送讀狀態寄存器1的指令Timeout = 100000;							//給定超時計數時間while ((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01)	//循環等待忙標志位{Timeout --;								//等待時,計數值自減if (Timeout == 0)						//自減到0后,等待超時{/*超時的錯誤處理代碼,可以添加到此處*/break;								//跳出等待,不等了}}MySPI_Stop();								//SPI終止
}/*** 函    數:W25Q64頁編程* 參    數:Address 頁編程的起始地址,范圍:0x000000~0x7FFFFF* 參    數:DataArray	用于寫入數據的數組* 參    數:Count 要寫入數據的數量,范圍:0~256* 返 回 值:無* 注意事項:寫入的地址范圍不能跨頁*/
void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count)
{uint16_t i;W25Q64_WriteEnable();						//寫使能MySPI_Start();								//SPI起始MySPI_SwapByte(W25Q64_PAGE_PROGRAM);		//交換發送頁編程的指令MySPI_SwapByte(Address >> 16);				//交換發送地址23~16位MySPI_SwapByte(Address >> 8);				//交換發送地址15~8位MySPI_SwapByte(Address);					//交換發送地址7~0位for (i = 0; i < Count; i ++)				//循環Count次{MySPI_SwapByte(DataArray[i]);			//依次在起始地址后寫入數據}MySPI_Stop();								//SPI終止W25Q64_WaitBusy();							//等待忙
}/*** 函    數:W25Q64扇區擦除(4KB)* 參    數:Address 指定扇區的地址,范圍:0x000000~0x7FFFFF* 返 回 值:無*/
void W25Q64_SectorErase(uint32_t Address)
{W25Q64_WriteEnable();						//寫使能MySPI_Start();								//SPI起始MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);	//交換發送扇區擦除的指令MySPI_SwapByte(Address >> 16);				//交換發送地址23~16位MySPI_SwapByte(Address >> 8);				//交換發送地址15~8位MySPI_SwapByte(Address);					//交換發送地址7~0位MySPI_Stop();								//SPI終止W25Q64_WaitBusy();							//等待忙
}/*** 函    數:W25Q64讀取數據* 參    數:Address 讀取數據的起始地址,范圍:0x000000~0x7FFFFF* 參    數:DataArray 用于接收讀取數據的數組,通過輸出參數返回* 參    數:Count 要讀取數據的數量,范圍:0~0x800000* 返 回 值:無*/
void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count)
{uint32_t i;MySPI_Start();								//SPI起始MySPI_SwapByte(W25Q64_READ_DATA);			//交換發送讀取數據的指令MySPI_SwapByte(Address >> 16);				//交換發送地址23~16位MySPI_SwapByte(Address >> 8);				//交換發送地址15~8位MySPI_SwapByte(Address);					//交換發送地址7~0位for (i = 0; i < Count; i ++)				//循環Count次{DataArray[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE);	//依次在起始地址后讀取數據}MySPI_Stop();								//SPI終止
}

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

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

相關文章

尚硅谷redis7-11-redis10大類型之總體概述

前提&#xff1a;我們說的數據類型一般是value的數據類型&#xff0c;key的類型都是字符串。 redis字符串【String】 string類型是二進制安全的,意思是redis的string可以包含任何數據,比如jpg圖片或者序列化的對象。 string類型是Redis最基本的數據類型,一個redis中字符串va…

【遞歸、搜索與回溯算法】專題一 遞歸

文章目錄 0.理解遞歸、搜索與回溯1.面試題 08.06.漢諾塔問題1.1 題目1.2 思路1.3 代碼 2. 合并兩個有序鏈表2.1 題目2.2 思路2.3 代碼 3.反轉鏈表3.1 題目3.2 思路3.3 代碼 4.兩兩交換鏈表中的節點4.1 題目4.2 思路4.3 代碼 5. Pow(x, n) - 快速冪5.1 題目5.2 思路5.3 代碼 0.理…

C#實現List導出CSV:深入解析完整方案

C#實現List導出CSV&#xff1a;深入解析完整方案 在數據交互場景中&#xff0c;CSV文件憑借其跨平臺兼容性和簡潔性&#xff0c;成為數據交換的重要載體。本文將基于C#反射機制實現的通用CSV導出方案&#xff0c;結合實際開發中的痛點&#xff0c;從基礎實現、深度優化到生產級…

字符串day7

344 反轉字符串 字符串理論上也是一個數組&#xff0c;因此只需要用雙指針即可 class Solution { public:void reverseString(vector<char>& s) {for(int i0,js.size()-1;i<j;i,j--){swap(s[i],s[j]);}} };541 反轉字符串 自己實現一個反轉從start到end的字符串…

Grafana XSSOpenRedirectSSRF漏洞復現(CVE-2025-4123)

免責申明: 本文所描述的漏洞及其復現步驟僅供網絡安全研究與教育目的使用。任何人不得將本文提供的信息用于非法目的或未經授權的系統測試。作者不對任何由于使用本文信息而導致的直接或間接損害承擔責任。如涉及侵權,請及時與我們聯系,我們將盡快處理并刪除相關內容。 前…

私服 nexus 之間遷移 npm 倉庫

本文介紹如何將一個 Nexus 特定倉庫中的 npm 包內容遷移到另一個 Nexus 特定倉庫。此過程適用于需要重構倉庫結構或合并倉庫的場景。 遷移腳本 以下是完整的遷移腳本&#xff0c;它會自動完成以下操作&#xff1a; 從源倉庫獲取所有 npm 包列表下載每個包的 .tgz 文件解壓并…

Django ToDoWeb 服務

我們的任務是使用 Django 創建一個簡單的 ToDo 應用程序,允許用戶添加、查看和刪除筆記。我們將通過設置 Django 項目、創建 Todo 模型、設計表單和視圖來處理用戶輸入以及創建模板來顯示任務來構建它。我們將逐步實現核心功能以有效地管理 todo 項。 Django ToDoWeb 服務 …

阿里云服務器遭遇DDoS攻擊?低成本第三方高防解決方案全解析

阿里云服務器因高性能和穩定性備受青睞&#xff0c;但其DDoS高防服務的價格常讓中小企業望而卻步。面對動輒每月數萬元的防護成本&#xff0c;許多用戶不禁疑問&#xff1a;能否通過第三方高防服務保護阿里云服務器&#xff1f;如何實現低成本高效防御&#xff1f; 本文將結合技…

2025山東CCPC補題

2025山東CCPC補題 目錄 2025山東CCPC補題K - UNO&#xff01; &#xff08;雙端隊列的簡單應用&#xff09;M - 第九屆河北省大學生程序設計競賽 &#xff08;二進制枚舉模擬&#xff09;J - Generate 01 String 感覺這場比賽的題目挺不錯的&#xff1b;沒有說那些為了算法而算…

體繪制學習

一、基本概念 體繪制是對一個三維物體數據進行采樣與擬合的過程。 在體繪制中用vtkVolume渲染數據 渲染數據類數據轉換類幾何渲染vtkActorvtkPolyDataMapper體渲染vtkVolumevtkVolumeRayCastMapper 體繪制常用算法如下。 光線投射法。 優點是可視化結果質量好。缺點是計算…

告別“盤絲洞”車間:4-20mA無線傳輸如何重構工廠神經網?

4-20ma無線傳輸是利用無線模塊將傳統的溫度、壓力、液位等4-20mA電流信號轉換為無線信號進行傳輸。這一技術突破了有線傳輸的限制&#xff0c;使得信號可以在更廣泛的范圍內進行靈活、快速的傳遞&#xff0c;無線傳輸距離可達到50KM。達泰4-20ma無線傳輸模塊在實現工業現場應用…

VB.NET與SQL連接問題解決方案

1.基本連接步驟 使用SqlConnection、SqlCommand和SqlDataReader進行基礎操作&#xff1a; vb.net Imports System.Data.SqlClient Public Sub ConnectToDatabase() Dim connectionString As String "ServermyServerAddress;DatabasemyDataBase;Integrated Security…

ElasticSearch--DSL查詢語句

ElasticSearch DSL查詢文檔 分類 查詢類型功能描述典型應用場景示例語法查詢所有匹配所有文檔&#xff0c;無過濾條件數據預覽/測試json { "query": { "match_all": {} } }全文檢索查詢對文本字段分詞后匹配&#xff0c;基于倒排索引搜索框模糊匹配、多字段…

DDR4讀寫壓力測試

1.1測試環境 1.1.1整體環境介紹 板卡&#xff1a; pcie-403板卡 主控芯片&#xff1a; Xilinx xcvu13p-fhgb2104-2 調試軟件&#xff1a; Vivado 2018.3 代碼環境&#xff1a; Vscode utf-8 測試工程&#xff1a; pcie403_user_top 1.1.2硬件介紹 UD PCIe-403…

在 Windows 上使用 WSL 安裝 Ansible詳細步驟

在 Windows 上使用 WSL&#xff08;Windows Subsystem for Linux&#xff09; 安裝 Ansible 是目前最推薦的方式&#xff0c;因為 Ansible 本身是為 Linux 環境設計的&#xff0c;不支持原生 Windows 作為控制節點。 下面是一個 詳細步驟指南 &#xff0c;幫助你在 Windows 上…

編寫第一個ros程序

1.下載VScode 下載鏈接如下&#xff1a; Download Visual Studio Code - Mac, Linux, Windows 下載ARM64下的.deb文件 打開虛擬機&#xff0c;再rosnoetic下新建一個文件夾VSCODE&#xff0c;將windows下的文件導入該文件夾下如下圖。 在該文件夾下右鍵選擇在終端中打開 輸入…

代碼隨想錄算法訓練營第60期第四十九天打卡

大家好&#xff0c;今天我們還是繼續我們的動態規劃章節&#xff0c;可能有的朋友已經開始厭倦了說為什么動態規劃怎么這么多題目&#xff0c;大家可以想想我們前面其實刷過好幾種類型的動態規劃的經典題目比如說各式各樣的背包問題當然包括0-1背包&#xff0c;完全背包&#x…

centos7.9離線升級內核到4.19.12詳細教程

cenots7.9默認安裝的內核版本是:3.10.0-1160.119.1.el7.x86_64,在安裝nvidia顯卡驅動的時候,提示內核版本過低,需要升級內核版本,升級完成之后,就可以順利的安裝上nvidia顯卡驅動了,實測有效。 一、查看當前內核版本命令 uname -r二、下載離線內核的rpm包

Vue3 + TypeScript + el-input 實現人民幣金額的輸入和顯示

輸入人民幣金額的參數要求&#xff1a; 輸入要求&#xff1a; 通過鍵盤&#xff0c;只允許輸入負號、小數點、數字、退格鍵、刪除鍵、方向左鍵、方向右鍵、Home鍵、End鍵、Tab鍵&#xff1b;負號只能在開頭&#xff1b;只保留第一個小數點&#xff1b;替換全角輸入的小數點&a…

方正字庫助力華為,賦能鴻蒙電腦打造全場景字體解決方案

2025年5月19日&#xff0c;搭載華為鴻蒙操作系統的鴻蒙電腦&#xff0c;面向用戶推出集AI智能、互聯流暢、安全保障和精致體驗于一體的全新辦公系統。作為鴻蒙生態核心字體服務商&#xff0c;方正字庫為此次提供了全面的系統字體支持&#xff0c;涵蓋中文、西文及符號三大類字庫…