【stm32】標準庫學習——I2C

目錄

一、I2C

1.I2C簡介

2.MPU6050參數?

3.I2C時序基本單元

二、I2C外設

1.I2C外設簡介

2.配置I2C基本結構

3.初始化函數模板

4.常用函數?


一、I2C

1.I2C簡介


本節課使用的是MPU6050硬件外設

2.MPU6050參數?


3.I2C時序基本單元

這里發送應答是指主機發送,即STM32作為主機,MPU6050或其他I2C通信外設作為從機,我們接收到從機的數據后要給從機發送應答位以供從機判斷我們是不是還需要數據。

接收應答則是判斷從機有沒有接收到數據,并且我們要將SDA的控制權轉交給從機,即釋放SDA(拉高)。

結合以下兩種時序理解上面6種基本時序單元

?在起始條件后緊跟著的一個字節就是七位從機地址和一位讀寫位,0代表寫,1代表讀。

不同的芯片廠商對第二位字節數據的作用要求不同,MPU6050規定第二個字節數據是指定寄存器地址

在對寄存器進行讀寫時,地址指針會自動加1,比如這里地址一開始指向0x19,寫入數據后指向0x1A,所以想要對特定地址進行讀操作,就要先寫入寄存器地址,再重復起始條件發送從機地址和讀操作,這時候沒有指定寄存器的操作,從機會自動將數據發送給你。?

以上就是I2C通信的時序,可以通過GPIO口軟件模擬I2C通信,本節主要學習STM32的硬件I2C外設


二、I2C外設

1.I2C外設簡介


2.配置I2C基本結構


由于硬件I2C不同于軟件模擬,我們不知道一個字節的數據是否發送完畢等等,因此STM32設置了許多代表不同事件的標志位


3.初始化函數模板

void MPU6050_Init(void)
{	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);//I2C1和2都是APB1的設備RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;//復用開漏輸出GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);//初始化I2CI2C_InitTypeDef I2C_InitStructure;I2C_InitStructure.I2C_Mode=I2C_Mode_I2C;//選擇I2C模式I2C_InitStructure.I2C_ClockSpeed=50000;//時鐘速度 可配置SCL時鐘頻率I2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;//配置占空比I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;//應答位配置I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;//作為從機時能響應多少位的地址I2C_InitStructure.I2C_OwnAddress1=0x00;//STM32作為從機時的地址,長度和上面參數對應I2C_Init(I2C2,&I2C_InitStructure);I2C_Cmd(I2C2,ENABLE);
}

這里GPIO口模式選擇復用開漏輸出,雖然是輸出,但仍然可以輸入,應為這里默認高電平是一種弱上拉,從機要發送數據只需要進行拉低電平或釋放這一種操作,“拉”或“不拉”,主機讀取電平就能接收從機發送的數據。PB10和PB11是I2C2的引腳。


初始化I2C后,封裝指定地址寫和指定地址讀兩個函數

//指定地址寫
void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data)//參數為寄存器地址和要寫入的數據
{
//	MyI2C_Start();
//	MyI2C_SendByte(0xD0);從機地址
//	MyI2C_ReceiveAck();
//	MyI2C_SendByte(RegAddress);
//	MyI2C_ReceiveAck();
//	MyI2C_SendByte(Data);
//	MyI2C_ReceiveAck();
//	MyI2C_Stop(); I2C_GenerateSTART(I2C2,ENABLE);//起始條件//判斷EV5事件while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);I2C_Send7bitAddress(I2C2,0xD0,I2C_Direction_Transmitter);//發送從機地址,選擇“寫”//判斷EV6事件,這里的EV6選擇“發送事件已選擇”while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);I2C_SendData(I2C2,RegAddress);//發送寄存器地址//判斷EV8事件,“字節正在發送”while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING)!=SUCCESS);I2C_SendData(I2C2,Data);//發送數據//判斷EV8_2事件,即移位寄存器空,且沒有新數據要發while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS);I2C_GenerateSTOP(I2C2,ENABLE);//終止條件
}

這里判斷各個標志位用I2C_CheckEvent?()函數,完成各個標志位會返回SUCCESS,這里判斷等于SUCCESS跳出循環,以免數據沒有發送完全等。硬件I2C和軟件I2C不同的是:軟件I2C因為是手動模擬,發送字節數據都是完整的,是通過發送和接收應答位來判斷雙方交流是否正常;而硬件I2C則是判斷標志位,并不需要管應答位,只需要使能ACK應答位即可。

//指定地址讀
uint8_t MPU6050_ReadReg(uint8_t RegAddress)//參數為寄存器地址
{uint8_t Data;//	MyI2C_Start();
//	MyI2C_SendByte(0xD0);從機地址
//	MyI2C_ReceiveAck();
//	MyI2C_SendByte(RegAddress);
//	MyI2C_ReceiveAck();
//	
//	MyI2C_Start();
//	MyI2C_SendByte(0xD0|0x01);
//	MyI2C_ReceiveAck();
//	Data=MyI2C_ReceiveByte();
//	MyI2C_SendAck(1);
//	MyI2C_Stop();//這里和指定地址寫的前三步一樣,即指定寄存器地址I2C_GenerateSTART(I2C2,ENABLE);//起始條件while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);I2C_Send7bitAddress(I2C2,0xD0,I2C_Direction_Transmitter);//發送從機地址,選擇“寫”while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=SUCCESS);I2C_SendData(I2C2,RegAddress);//發送寄存器地址while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING)!=SUCCESS);I2C_GenerateSTART(I2C2,ENABLE);//重復起始條件//判斷EV5while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);I2C_Send7bitAddress(I2C2,0xD0,I2C_Direction_Receiver);//發送從機地址,選擇“讀”//等待EV6事件,選擇“接收事件已選擇”while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS);//在接收最后一個字節時,要提前將ACK置0,并且產生終止條件I2C_AcknowledgeConfig(I2C2,DISABLE);//ACK=0,不給應答I2C_GenerateSTOP(I2C2,ENABLE);//STOP=1,申請產生終止條件//判斷EV7事件,意味著數據移到DR寄存器,可以讀走了while(I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED)!=SUCCESS);Data=I2C_ReceiveData(I2C2);//讀取數據//最后將應答位置1I2C_AcknowledgeConfig(I2C2,ENABLE);return Data;
}

?指定地址讀的前三步和指定地址寫一樣,起始條件后發送從機地址,寫寄存器地址,然后重復起始條件,發送從機地址選擇“讀”,這里判斷EV6事件就不同于指定地址寫。

因為我們寫和讀都是只有一個字節的數據,所以指定地址讀后就是接收最后一個字節,如果接收多個字節則是判斷EV7事件,這里接收一個字節也是最后一個字節,要提前將ACK置0(失能),同時申請終止條件。最后終止條件產生后判斷EV7事件,讀走DR寄存器的數據。最后將ACK置1(使能)(我的理解是因為要在主循環里不斷調用讀的操作,在初始化函數里通過結構體參數I2C_Ack使能ACK,意味著正常讀寫ACK都是處于使能的狀態,而函數I2C_AcknowledgeConfig可以單獨配置ACK的狀態,為了后續正常運行,所以最后還要將ACK使能)

附:在主發送和主接收的序列圖中,發送從機地址后,我們會判斷EV6事件,可以看到后面還接了一個EV8_1事件,這個事件是提醒我們該寫入數據發送出去了,因此我們不需要判斷EV8_1事件

參數列表里也沒有EV8_1事件。


4.常用函數?

I2C_GenerateSTART,生成起始條件

I2C_GenerateSTOP,生成終止條件

l2C_SendData,發送數據

I2C_ReceiveData,接收數據

I2C_AcknowledgeConfig,使能或失能ACK,給ENABLE就是就是給從機應答

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

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

相關文章

HSA22HSA29美光固態芯片D8BJVC8BJW

HSA22HSA29美光固態芯片D8BJVC8BJW 美光固態芯片D8BJVC8BJW系列:技術革新與行業應用深度解析 一、技術解析:核心架構與創新突破 美光D8BJVC8BJW系列固態芯片(如MT29F8T08EQLEHL5-QAES:E、MT29F512G08CUCABH3-12Q等)的技術競爭力…

【Linux網絡與網絡編程】06.應用層協議HTTP

前言 雖然應用層協議是我們程序猿自己定的,但實際上已經有大佬們定義了一些現成的又非常好用的應用層協議供我們直接參考使用,HTTP(超文本傳輸協議)就是其中之一。 在互聯網世界中,HTTP(HyperText Transfer Protocol&#xff0c…

磁懸浮軸承的“生死線”:磁軸承氣隙與保護軸承氣隙的可靠性設計

在高速旋轉機械的尖端領域,磁懸浮軸承(AMB)憑借無摩擦、超高轉速、免潤滑等優勢傲視群雄。然而,其核心參數——氣隙的設置,尤其是額定工作氣隙與保護軸承(輔助軸承)氣隙之間的大小關系與具體數值…

QT 學習筆記摘要(一)

第一節 QT介紹 1. QT概述 簡單來說,QT就是一個跨平臺的客戶端技術,HTML畫網頁一樣,而QT就是畫客戶端的,它不僅可以繪制界面而且可以做單機應用開發,還可以做網絡程序的客戶端界面開發 更專業的說法是:Qt 是…

QCustomPlot 疊加對象(Overlay Items)

QCustomPlot 提供了一系列可以在圖表上疊加顯示的對象(items),這些對象不屬于數據本身,而是用于標注、輔助線等用途。以下是主要疊加對象的詳細說明和使用方法。 1. QCPItemStraightLine (無限直線) 特性: 無限延伸的…

Flink源碼閱讀環境準備全攻略:搭建高效探索的基石

想要深入探索Flink的底層原理,搭建一套完整且適配的源碼閱讀環境是必經之路。這不僅能讓我們更清晰地剖析代碼邏輯,還能在調試過程中精準定位關鍵環節。接下來,結合有道云筆記內容,從開發工具安裝、源碼獲取導入到調試配置&#x…

Dify,FastGPT,RagFlow有啥區別,在智能問答方面有啥區別

Dify、FastGPT、RagFlow都是當前非常流行的低代碼AI應用開發平臺,它們都專注于讓用戶能夠快速構建AI應用,但在設計理念、功能特色和適用場景上有明顯區別。 讓我詳細對比一下這三個平臺: 1. 平臺定位對比 Dify 定位:全棧AI應用…

基站定位接口如何如何用PHP實現調用?

隨著“新基建”戰略的推進,我國移動通信基站數量快速增長。截至2024年底,全國基站總數已達1265萬個,其中5G基站超425萬個,構建起全球規模最大、技術領先的通信網絡。 在這一基礎上,基站查詢API通過整合三大運營商數據…

Day 4:Shell流程控制——從“直線思維“到“智能決策“的進化

目錄 一、if語句:你以為簡單其實暗藏殺機1. 基礎語法(看似簡單卻容易踩坑)2. 安全寫法規范(企業級建議) 二、條件測試的六大門派1. 文件測試(運維最愛)2. 字符串比較(引號是靈魂&…

分布式訓練中的隨機種子策略:深入理解與實踐指南

分布式訓練中的隨機種子策略:深入理解與實踐指南 引言:一個容易被忽視的關鍵細節 在深度學習的分布式訓練中,你是否見過這樣的代碼? torch.manual_seed(process_seed) # PyTorch操作 random.seed(process_seed) # Pyth…

金山辦公發布WPS智慧教育平臺,發力教育AI意義何在?

鈦媒體消息,金山辦公發布面向教育用戶的 WPS 智慧教育平臺,面對著金山辦公的發力,我們該怎么分析呢? 首先,從市場拓展與用戶需求響應角度看,金山辦公此次推出WPS智慧教育平臺,直接瞄準了教育領…

無人機航電系統之語音通信技術篇

無人機航電系統的語音通信技術是確保無人機與地面控制站、其他無人機或相關人員之間實現高效、穩定語音交互的關鍵技術,在軍事偵察、應急救援、物流運輸、航拍測繪等眾多領域發揮著至關重要的作用。 一、技術原理 無人機航電系統的語音通信技術主要基于無線通信原理…

element plus 的樹形控件,如何根據后臺返回的節點key數組,獲取節點key對應的node節點

在使用 Element Plus 的 el-tree 組件時,如果后端返回的節點 key 數組中包含了部分選中的父級節點的 key,可能會導致該父級節點下的所有子節點也被默認選中。這是因為 el-tree 的默認行為是:如果一個父節點被選中,那么其所有子節點…

什么是Sentinel

什么是 Sentinel? 在分布式系統中,服務間的依賴關系錯綜復雜。一個服務的故障,很可能像多米諾骨牌一樣,迅速蔓延并導致整個系統崩潰,這就是我們常說的“雪崩效應”。為了避免這種災難性后果,我們需要一種強大的機制來保護我們的系統,而 Sentinel 正是為此而生。 Senti…

AWS 使用圖形化界面創建 EKS 集群(零基礎教程)

無需命令行!通過 AWS 控制臺圖形化操作,輕松創建 Kubernetes 集群。 文章目錄 文章簡介 一、準備工作:登錄 AWS 控制臺 二、創建 EKS 集群(控制面) 1. 創建 EKS 集群 2. 設置集群基本信息 3. 配置網絡設置 三、添加…

[C#] Winform - 進程間通信(SendMessage篇)

一、發送端 // 窗體:發送端 public partial class SendForm : Form {public SendForm(){InitializeComponent();}// 按鈕:發送private void btnSend_Click(object sender, System.EventArgs e){IntPtr hwnd User32Helper.FindWindow(null, "接收端…

鋰電池保護板測試儀:守護電池安全的幕后保障

在電動汽車、儲能電站和便攜式電子設備中,鋰電池作為核心動力源,其能量密度與安全性始終是行業關注的焦點。鋰電池在過充、過放、短路等異常情況下可能引發起火甚至爆炸,而鋰電池保護板正是解決這一問題的關鍵組件。為確保保護板性能可靠&…

Qemu搭建RISC-V,運行opensbi+u-boot+img

?1.先下載一個Ubuntu鏡像 https://cdimage.ubuntu.com/releases/24.04/release/ 我這里下載的是這個RISC-V的 🌟1.2.解壓鏡像 xz -d ubuntu-24.04.2-preinstalled-server-riscv64.img.xz ?2.準備RISC-V的QEMU 打開qemu官網https://www.qemu.org/&#xff0c…

【實戰手冊】銀河麒麟服務器系統進入單用戶模式修改密碼(root)指南

目錄 前言 一、銀河麒麟單用戶模式簡介 二、進入單用戶模式修改密碼 三、登錄驗證新密碼 結語 前言 在日常服務器運維工作中,忘記root密碼是系統管理員偶爾會遇到的問題。作為國產操作系統的優秀代表,銀河麒麟服務器系統提供了通過單用戶模式重置r…

偏微分方程通解求解2

題目 求下列方程的通解: { u x y = u x u y u ? 1 ; u x y = u x u y ; u x y = u x u y u u 2 + 1 ; \begin{cases} u_{xy} = u_x u_y u^{-1}; \\ u_{xy} = u_x u_y; \\ u_{xy} = \dfrac{u_x u_y u}{u^2 + 1}; \end{cases} ????????uxy?=ux?uy?u?1;uxy?=ux?…