STM32學習筆記14-I2C硬件控制

I2C外設簡介


  • STM32內部集成了硬件I2C收發電路(硬件收發器:自動生產波形,自動翻轉電平等),可以由硬件自動執行時鐘生成、起始終止條件生成、應答位收發、數據收發等功能,減輕CPU的負擔——軟件只需要寫入控制寄存器CR和DR,還有實時監控時序狀態的狀態寄存器SR
  • 支持多主機模型
  • 支持7位/10位地址模式
  • 支持不同的通訊速度,標準速度(高達100 kHz),快速(高達400 kHz)
  • 支持DMA
  • 兼容SMBus協議
  • STM32F103C8T6 硬件I2C資源:I2C1、I2C2

補:多主機模型:固定多主機(有固定的主機數和固定的從機數)和可變多主機(任何設備,都可以從空閑的狀態跳出來作為主機,然后指定通信,之后又跳回來),采用10位地址的時序:起始條件后的兩個字節都是尋址,其中前一個字節,是幀頭:內容是5位的標志位11110+2位地址+1位讀寫位,后一個字節:純粹的8位地址。

I2C框圖

引腳對應關系

I2C基本結構(一主多從)

硬件I2C的操作流程:

主機發送

主機接收

軟件/硬件波形對比

手冊——對應24章

接線圖

10-2 硬件I2C讀寫MPU6050


  1. 開啟I2C外設和對應GPIO口的時鐘
  2. 把I2C外設對應的GPIO口初始化為復用開漏模式
  3. 使用結構體,對整個I2C進行配置
  4. I2C_Cmd,使能I2C

相關函數:

void I2C_DeInit(I2C_TypeDef* I2Cx);

void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);

void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);

void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);? //生產起始條件

void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);? //生產結束條件

void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);? //配置應答ACK

void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);? //數據寫入DR寄存器

uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);? //讀取DR的數值

void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);? //發送7位地址的專用函數

//EV——多種監控

I2C_CheckEvent()? //基本

I2C_GetLastEvent()? //高級

I2C_GetFlagStatus()?? //基于狀態位的標準監控

void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);

ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT);

void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT);

MPU6050.c//27硬件I2C讀寫MPU6050
//與軟件的區別就是MyI2C.c這個文件,硬件是不需要的
//意思是:底層的邏輯會有不同,其他是一樣的
#include "stm32f10x.h"                  // Device header#define MPU_ADD   0xD0
#include "MPU_Reg.h"
//封裝指定地址寫和指定地址讀的時序
//優化:在代碼中,存在很多死循環的地方——超時退出void CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT){uint32_t TimeOut;TimeOut=100;	while(I2C_CheckEvent(I2Cx, I2C_EVENT)!=SUCCESS){TimeOut--;if(TimeOut==0){break;//錯誤處理}}
}void MPU_WriteReg(uint8_t RegAddress,uint8_t Data){//用此函數,則會一直傳輸數據,所以我們需要用標志位去確定它是否操作成功了,這里就要用EV5事件來確定I2C_GenerateSTART(I2C2, ENABLE);//while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS);//封裝
//		while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS){
//			TimeOut--;
//			if(TimeOut==0){
//				return;
//			}
//		}CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);//發送函數會自帶應答位,所以我們不需要考慮應答,只需要考慮發送后的事件EV6即可I2C_Send7bitAddress(I2C2,MPU_ADD, I2C_Direction_Transmitter); CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//EV8_1的事件是提醒應該寫入DR數據,不需要等待I2C_SendData(I2C2, RegAddress); //同理,等待對應的事件EV8CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING); I2C_SendData(I2C2, Data);//當發送為最后一個數據時,就需要等待EV8_2事件CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);I2C_GenerateSTOP(I2C2, ENABLE); }uint8_t MPU_ReadingReg(uint8_t RegAddress){uint8_t Data;I2C_GenerateSTART(I2C2, ENABLE);CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); //發送函數會自帶應答位,所以我們不需要考慮應答,只需要考慮發送后的事件EV6即可I2C_Send7bitAddress(I2C2,MPU_ADD, I2C_Direction_Transmitter); CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //EV8_1的事件是提醒應該寫入DR數據,不需要等待I2C_SendData(I2C2, RegAddress); //在最后一個數據,用EV8_2while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)!=SUCCESS); I2C_GenerateSTART(I2C2, ENABLE);while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)!=SUCCESS); //主機接收I2C_Send7bitAddress(I2C2,MPU_ADD, I2C_Direction_Receiver); while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)!=SUCCESS); //接收從機的數據:規定:在接收數據之前,需要把ACK置0,同時設置停止位STOP//如果讀取多個字節,那直接等待EV7事件,讀取DR,就能收到數據,在接收最后一個字節之前EV7_1事件,需要把ACK置0,同時設置停止位STOP//如果讀取一個字節,那在EV6事件之后,需要把ACK置0,同時設置停止位STOP,在等待EV7事件,不然會多一個字節I2C_AcknowledgeConfig(I2C2, DISABLE);I2C_GenerateSTOP(I2C2,ENABLE);while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED)!=SUCCESS); //讀取DRData=I2C_ReceiveData(I2C2); I2C_AcknowledgeConfig(I2C2, ENABLE);  //應答值設為1,給從機應答,這樣可以使指定地址收多個字節return Data;}void MPU6050_Init(void){RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11;GPIO_Init(GPIOB, &GPIO_InitStructure);I2C_InitTypeDef I2C_InitStructure;I2C_InitStructure.I2C_Mode =I2C_Mode_I2C;  //I2C的模式I2C_InitStructure.I2C_ClockSpeed=50000;  //時鐘頻率,要低于400KHzI2C_InitStructure.I2C_DutyCycle=I2C_DutyCycle_2;//時鐘占空比,只有在時鐘頻率大于100KHz才有用,小于則固定的1:1;——能更快的傳輸I2C_InitStructure.I2C_Ack=I2C_Ack_Enable;  //應答配置I2C_InitStructure.I2C_AcknowledgedAddress=I2C_AcknowledgedAddress_7bit;  //STM做從機,可以被響應幾位地址I2C_InitStructure.I2C_OwnAddress1=0x00;  //自身寄存器,當STM32做從機時,指定STM32的自身地址,方便主機呼叫I2C_Init(I2C2,&I2C_InitStructure);I2C_Cmd(I2C2,ENABLE);MPU_WriteReg(MPU6050_PWR_MGMT_1,0x01);  //解除睡眠,選擇陀螺儀時鐘MPU_WriteReg(MPU6050_PWR_MGMT_2,0x00);	//6個軸均不待機MPU_WriteReg(MPU6050_SMPLRT_DIV,0x09);	//采樣分頻為10MPU_WriteReg(MPU6050_CONFIG,0x06);	//濾波參數最大MPU_WriteReg(MPU6050_GYRO_CONFIG,0x18);	//陀螺儀和加速度選擇最大MPU_WriteReg(MPU6050_ACCEL_CONFIG,0x18);
//	//此時的MPU就在進行大量的數據轉換,數據存放在其他的寄存器里
}void MPU_Getdata(int16_t *AccX, int16_t *AccY, int16_t *AccZ, int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)  
{//讀取加速度寄存器XYZ軸的高8位和低8位uint8_t DataH, DataL;								//定義數據高8位和低8位的變量DataH = MPU_ReadingReg(MPU6050_ACCEL_XOUT_H);		//讀取加速度計X軸的高8位數據DataL = MPU_ReadingReg(MPU6050_ACCEL_XOUT_L);		//讀取加速度計X軸的低8位數據*AccX = (DataH << 8) | DataL;						//數據拼接,通過輸出參數返回DataH = MPU_ReadingReg(MPU6050_ACCEL_YOUT_H);		//讀取加速度計Y軸的高8位數據DataL = MPU_ReadingReg(MPU6050_ACCEL_YOUT_L);		//讀取加速度計Y軸的低8位數據*AccY = (DataH << 8) | DataL;						//數據拼接,通過輸出參數返回DataH = MPU_ReadingReg(MPU6050_ACCEL_ZOUT_H);		//讀取加速度計Z軸的高8位數據DataL = MPU_ReadingReg(MPU6050_ACCEL_ZOUT_L);		//讀取加速度計Z軸的低8位數據*AccZ = (DataH << 8) | DataL;						//數據拼接,通過輸出參數返回DataH = MPU_ReadingReg(MPU6050_GYRO_XOUT_H);		//讀取陀螺儀X軸的高8位數據DataL = MPU_ReadingReg(MPU6050_GYRO_XOUT_L);		//讀取陀螺儀X軸的低8位數據*GyroX = (DataH << 8) | DataL;						//數據拼接,通過輸出參數返回DataH = MPU_ReadingReg(MPU6050_GYRO_YOUT_H);		//讀取陀螺儀Y軸的高8位數據DataL = MPU_ReadingReg(MPU6050_GYRO_YOUT_L);		//讀取陀螺儀Y軸的低8位數據*GyroY = (DataH << 8) | DataL;						//數據拼接,通過輸出參數返回DataH = MPU_ReadingReg(MPU6050_GYRO_ZOUT_H);		//讀取陀螺儀Z軸的高8位數據DataL = MPU_ReadingReg(MPU6050_GYRO_ZOUT_L);		//讀取陀螺儀Z軸的低8位數據*GyroZ = (DataH << 8) | DataL;						//數據拼接,通過輸出參數返回}

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

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

相關文章

電子電氣架構 --- 軟件開發數字化轉型

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 簡單,單純,喜歡獨處,獨來獨往,不易合同頻過著接地氣的生活,除了生存溫飽問題之外,沒有什么過多的欲望,表面看起來很高冷,內心熱情,如果你身…

我國空間站首次應用專業領域 AI大模型

據中國載人航天工程辦公室消息&#xff0c;北京時間2025年8月15日22時47分&#xff0c;經過約6.5小時的出艙活動&#xff0c;神舟二十號乘組航天員陳冬、陳中瑞、王杰密切協同&#xff0c;在空間站機械臂和地面科研人員的配合支持下&#xff0c;圓滿完成既定任務&#xff0c;出…

WPF真入門教程35--手搓WPF出真汁【蜀味正道CS版】

1、項目介紹 本項目采用多層架構設計&#xff0c;使用wpf&#xff0c;Panuon.UI.Silver控件庫&#xff0c;AduSkin皮膚&#xff0c;MVVM等技術開發具有復雜交互和視覺效果的CS應用程序。WPF適用于企業級桌面應用&#xff1a;如ERP、CRM系統&#xff0c;需復雜表單和報表。WPF適…

JMeter與大模型融合應用之構建AI智能體:評審性能測試腳本

JMeter與大模型融合應用之構建AI智能體&#xff1a;評審性能測試腳本 一、引言 隨著DevOps和持續測試的普及&#xff0c;性能測試已成為軟件開發生命周期中不可或缺的環節。Apache JMeter作為最流行的開源性能測試工具之一&#xff0c;被廣泛應用于各種性能測試場景。然而&…

K8s 和 Docker的區別

一、各自誕生背景——為什么需要兩個東西Docker&#xff08;2013&#xff0c;Docker Inc.&#xff09; ? 目的&#xff1a;解決“我的代碼在你機器跑不起來”的經典環境問題。 ? 做法&#xff1a;用 Linux 內核的 cgroup/namespace 做輕量隔離&#xff0c;把“應用 依賴”打…

10.0 UML的介紹以及VisualStudio中查看類圖

本文介紹UML圖的含義、以及如何在VisualStudio中查看類圖。 一、UML圖介紹 UML(Unified Modeling Language,統一建模語言)是一種標準化的建模語言,用于可視化、規范、構建和記錄軟件系統的各個方面的圖表工具。 UML圖分為結構圖和行為圖兩大類: 結構圖?…

【Virtual Globe 渲染技術筆記】6 著色

著色&#xff08;Shading&#xff09; 曲面細分只是地球渲染的第一步。接下來是著色——通過模擬光線與材質的相互作用&#xff0c;計算每個像素的最終顏色。本節先回顧基礎的光照與紋理映射&#xff0c;再講解虛擬地球特有的經緯網格和夜景燈光效果。6.1 光照&#xff08;Ligh…

OpenCV Python——圖像拼接(一)(圖像拼接原理、基礎知識、單應性矩陣 + 圖像變換 + 拼接)

1 圖像拼接基礎知識1.1 特征匹配 原理及代碼示例1.2 單應性矩陣 原理及代碼示例2 圖像拼接&#xff08;一&#xff09;&#xff08;直接拼接&#xff09;3 圖像拼接&#xff08;二&#xff09;&#xff08;單應性矩陣 圖像變換 拼接&#xff09;3.1 單應性矩陣函數3.2 拼接函…

Git 中切換到指定 tag

在 Git 中切換到指定 tag&#xff08;比如 v1.22.1&#xff09;的正確做法如下&#xff1a;1?? 查看已有的 taggit tag會列出所有可用的版本&#xff0c;比如&#xff1a;v1.21.0 v1.22.0 v1.22.1 v1.23.02?? 切換到指定 taggit checkout tags/v1.22.1 -b v1.22.1解釋&…

rust 從入門到精通之變量和常量

變量和常量 隨著軟件系統安全的重要性與日俱增, rust這門集聚高并發, 安全, 適配云環境的編程語言在市場上得到了越來越高的認可和關注。但其復雜的機制使其難以學習。且其很多特性對于其他語言是全新的&#xff0c;這加劇了學習的困難程度。教程主要針對rust基礎進行講解, 雖然…

2508C++,支持rdma通信的高性能rpc庫

原文 [重磅]支持rdma通信的高性能的rpc庫–yalantinglibs.coro_rpc yalantinglibs的coro_rpc是基于C20的協程的高性能的rpc庫,提供了簡潔易用的接口,讓用戶幾行代碼就可實現rpc通信,現在coro_rpc除了支持tcp通信之外還支持了rdma通信(ibverbs). 通過簡單示例來感受一下rdma通…

FastAPI + React:現代 Web 前后端分離開發的全棧實踐指南

一、為什么選 FastAPI React&#xff1f; 性能&#xff1a;FastAPI 基于 Starlette Uvicorn&#xff0c;QPS 與 Node/Go 同級&#xff0c;實測 3 倍于 Flask&#xff1b;React 虛擬 DOM 代碼分割&#xff0c;首屏 < 1.2 s。效率&#xff1a;FastAPI 內置 Swagger/OpenAPI…

嵌入式硬件篇---電平轉換電路

電平轉換電路是電子電路中用來實現不同電壓信號之間轉換的關鍵電路&#xff0c;比如把 3.3V 的信號轉換成 5V&#xff0c;或者把 5V 轉換成 1.8V&#xff0c;確保不同電壓的芯片、模塊能正常通信。下面用通俗易懂的方式介紹幾種常見的電平轉換電路&#xff1a;一、電阻分壓電路…

SAP ABAP IS SUPPLIED

效果 此謂詞表達式用于檢查過程的某個形式參數“para”是否已賦值或被請求使用。如果在調用時實際參數被賦值給了該形式參數&#xff0c;則該表達式為真。 這種關系表達式僅能在函數模塊和方法中使用。而對于“para”而言&#xff0c;所有可選的形參都可以進行指定。 加上“NOT…

視頻內容提取與AI總結:提升學習效率的實用方法

文章目錄1、前言2、方法介紹2.1 B站視頻處理方案2.2 通用視頻處理方案2.3 AI內容總結3、實際效果4、使用建議5、技術發展趨勢6、總結&#x1f343; 作者介紹&#xff1a;25屆雙非本科網絡工程專業&#xff0c;阿里云專家博主&#xff0c;專注于 AI 原理、AI 應用開發、AI 產品設…

JVM 面試精選 20 題

目錄1. 什么是 JVM、JDK 和 JRE&#xff1f;它們之間的關系是什么&#xff1f;2. Java 內存區域&#xff08;運行時數據區&#xff09;有哪些&#xff1f;3. 說說你對 JVM 垃圾回收機制的理解。4. 常用的垃圾回收算法有哪些&#xff1f;5. 什么是 Minor GC、Major GC 和 Full G…

CMIP6 氣候模式核心特性解析

在全球氣候變化研究中&#xff0c;CMIP6&#xff08;第六次耦合模式比較計劃&#xff09;的氣候模式是關鍵工具。以下從研發背景與核心能力角度&#xff0c;解析五類主流模式的技術特點與適用場景。 一、主流模式技術特性 1. CanESM5/CanESM5-1&#xff08;加拿大環境與氣候變…

【牛客刷題】BM63 跳臺階:三種解法深度解析(遞歸/DP動態規劃/記憶化搜索)

文章目錄 一、題目介紹 1.1 題目描述 1.2 示例 二、算法設計思路 2.1 核心問題分析 2.2 斐波那契數列關系 三、流程圖 解法1:遞歸法(自頂向下) 解法2:動態規劃(自底向上) 解法3:記憶化搜索(遞歸優化) 解法4: 優化DP流程(推薦) 四、解法實現 五、復雜度分析對比 六、…

《解構WebSocket斷網重連:指數退避算法的前端工業級實踐指南》

WebSocket作為客戶端與服務器雙向通信的核心載體,支撐著從在線協作、金融行情到即時通訊等各類高實時性場景。然而,網絡環境的動態變化—從用戶設備的Wi-Fi與蜂窩網絡切換,到公共網絡的臨時擁塞,再到服務器的短暫重啟—都可能導致WebSocket連接中斷,進而引發數據傳輸停滯、…

醫療潔凈間的“隱形助手”:富唯智能復合機器人如何重塑手術器械供應鏈

當手術刀片在無影燈下傳遞時&#xff0c;0.01mm的抓取偏差可能意味著感染風險——而富唯智能復合機器人以0.02mm的重復定位精度與99.999%無菌操作的硬實力&#xff0c;正成為高端醫療產線中替代人力的關鍵技術支點。一、醫療上下料的三大痛點&#xff1a;精度、潔凈與連續性1.毫…