IIC協議總結

1.基本理解

? ? ? ? iic通信協議:雙線制串行通信協議,由時鐘線SCL和數據線SDA構成.

? ? ? ? 通信方式:主從模式,主設備發起通信,從設備響應通信

2.通信的基本步驟


?? ?a.主設備發送一個開始信號,表示開始通信,即啟動I2C ?

????????條件:SCL=1,SDA出現下降沿?
?? ??? ?IIC啟動之后,SCL=1時,SDA的電平不允許有變化
? ? ? ? ? ? ? ? ???? ??? ??? ?SCL=0時,數據發送方才能在SDA上改變發送電平
?? ?b.主設備發送一個從設備的地址和(讀寫位) 一般地址的長度是7bit,最后一個bit是讀寫指令,
?? ??? ?1是讀(主機接收從機數據),0是寫(主機發送數據到從機)
?? ?C.仲裁機制和應答,從機只有收到自己的地址信息才會被喚醒,這個過程是以一個低電平的SDA脈沖應答,
?? ??? ?主機檢測這個應答位,0是 1不是
?? ?d.數據傳輸 確認目標后,主設備發送或者接收數據,數據傳輸在每個時鐘周期的上升沿或者下降沿進行
?? ?e.停止:SCL = 1,SDA出現上升沿
?? ??? ?注意:I2C外部需根據傳輸速率匹配上拉電阻,速率越高,上拉電阻越小,否則會影響時序;
? ? ? ? ? ? ? ? ? ? I2C引腳作為輸出時需是開漏輸出,作為輸入時需是浮空輸入,不能匹配內部上拉或下拉電阻;
?? ??? ??? ? ?

? ? 3.軟件模擬


?? ?1.結構體定義總線的SDA和SCL兩個引腳:用于控制兩個引腳的輸入輸出

typedef struct{uint32_t SDA_RCC_APB2Periph;//SDA腳的時鐘GPIO_TypeDef* SDA_Port;//SDA腳Portuint16_t SDA_Pin;//SDA腳Pinuint32_t SCL_RCC_APB2Periph;//SCL腳的時鐘GPIO_TypeDef* SCL_Port;//SCL腳Portuint16_t SCL_Pin;//SCL腳Pin}sw_i2c_gpio_t;


? ? ?2.宏定義
?? ? ?

#define I2C_USE_7BIT_ADDR //如果使用的從機地址是7Bit模式,則打開這個宏,否則注釋掉這個宏#define I2C_DELAY ? ? ? ? ? ? ? ?50 // I2C每個Bit之間的延時時間,延時越小I2C的速率越高#define SW_I2C_SCL_LOW ? ? ? ? ?GPIO_ResetBits(gpio->SCL_Port,gpio->SCL_Pin) // I2C SCL腳輸出0 地電平#define SW_I2C_SCL_HIGH ? ? ? ? GPIO_SetBits(gpio->SCL_Port,gpio->SCL_Pin) // I2C SCL腳輸出1 高電平#define SW_I2C_SDA_LOW ? ? ? ? ?GPIO_ResetBits(gpio->SDA_Port,gpio->SDA_Pin) // I2C SDA腳輸出0 低電平#define SW_I2C_SDA_HIGH ? ? ? ? GPIO_SetBits(gpio->SDA_Port,gpio->SDA_Pin) // I2C SDA腳輸出1 高電平#define SW_I2C_SDA_INPUT ? ? ? ?sw_i2c_set_sda_input(gpio) // 將SDA腳方向設置為輸入?#define SW_I2C_SDA_OUTPUT ? ? ? ?sw_i2c_set_sda_output(gpio) // 將SDA腳方向設置為輸出#define SW_I2C_SDA_STATUS ? ? ? ?sw_i2c_sda_status(gpio) // 獲取SDA腳輸入電平狀態 ?#define i2c_delay_us(a) ? ? ? ? ? ?SystemDelayUs(a) // 延時


? ?3,其他準備函數
??

?SDA輸入輸出及狀態/**************************************************************************
*** ? ? ? ? ? ? ? ? ? ? ? ? ?讀取SDA腳的狀態 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ***
***************************************************************************/
static uint8_t sw_i2c_sda_status(sw_i2c_gpio_t *gpio)
{uint8_t sda_status;sda_status = GPIO_ReadInputDataBit(gpio->SDA_Port,gpio->SDA_Pin); ? ?return sda_status?1:0;
}
/**************************************************************************
*** ? ? ? ? ? ? ? ? ? ? ? ? ?設置SDA腳為輸入 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ***
***************************************************************************/
static void sw_i2c_set_sda_input(sw_i2c_gpio_t *gpio)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = gpio->SDA_Pin; ? ?GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init (gpio->SDA_Port, & GPIO_InitStructure );
}
/**************************************************************************
*** ? ? ? ? ? ? ? ? ? ? ? ? ?設置SDA腳為輸出 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ***
***************************************************************************/
static void sw_i2c_set_sda_output(sw_i2c_gpio_t *gpio)
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = gpio->SDA_Pin; ? ?GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; ? //開漏輸出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init (gpio->SDA_Port, & GPIO_InitStructure );
}I2C啟動static void sw_i2c_start(sw_i2c_gpio_t *gpio)
{// I2C 開始時序:SCL=1時,SDA由1變成0.SW_I2C_SDA_HIGH; ? ? ? ??i2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH; ? ? ? ? ??i2c_delay_us(I2C_DELAY);SW_I2C_SDA_LOW;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);
}
I2C停止
static void sw_i2c_stop(sw_i2c_gpio_t *gpio)
{// I2C 開始時序:SCL=1時,SDA由0變成1.SW_I2C_SDA_LOW;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);SW_I2C_SDA_HIGH;
}等待數據接收方反饋
static uint8_t sw_i2c_wait_ack(sw_i2c_gpio_t *gpio)
{uint8_t sda_status;uint8_t wait_time=0;uint8_t ack_nack = 1;//先設置SDA腳為輸入SW_I2C_SDA_INPUT;//等待SDA腳被從機拉低while(SW_I2C_SDA_STATUS){wait_time++;//如果等待時間過長,則退出等待if (wait_time>=200){ack_nack = 0;break;}}// SCL由0變為1,讀入ACK狀態// 如果此時SDA=0,則是ACK// 如果此時SDA=1,則是NACKi2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);//再次將SCL=0,并且將SDA腳設置為輸出SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);SW_I2C_SDA_OUTPUT;i2c_delay_us(I2C_DELAY);return ack_nack;
}發送ACK給數據發送方 ?應答信號
static void sw_i2c_send_ack(sw_i2c_gpio_t *gpio)
{// 發送ACK就是在SDA=0時,SCL由0變成1SW_I2C_SDA_LOW;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);
}發送NACK給數據發生方 非應答信號,表示接受沒有成功
static void sw_i2c_send_nack(sw_i2c_gpio_t *gpio)
{// 發送NACK就是在SDA=1時,SCL由0變成1SW_I2C_SDA_HIGH;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);
}

4.主設備接受和發送字節?

static void sw_i2c_write_byte(sw_i2c_gpio_t *gpio,uint8_t aByte)
{uint8_t i;for (i=0;i<8;i++){//先將SCL拉低;SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);//然后在SDA輸出數據if(aByte&0x80){SW_I2C_SDA_HIGH;}else{SW_I2C_SDA_LOW;}i2c_delay_us(I2C_DELAY);//最后將SCL拉高,在SCL上升沿寫入數據SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);aByte = aByte<<1;//數據位移}//寫完一個字節只后要將SCL拉低SW_I2C_SCL_LOW;i2c_delay_us(I2C_DELAY);
}主設備從從設備讀取字節
static uint8_t sw_i2c_read_byte(sw_i2c_gpio_t *gpio)
{uint8_t i,aByte;//先將SDA腳設置為輸入SW_I2C_SDA_INPUT;for (i=0;i<8;i++){//數據位移aByte = aByte << 1;//延時等待SDA數據穩定i2c_delay_us(I2C_DELAY);//SCL=1,鎖定SDA數據SW_I2C_SCL_HIGH;i2c_delay_us(I2C_DELAY);//讀取SDA狀態if(SW_I2C_SDA_STATUS){aByte |= 0x01;}//SCL=0,解除鎖定SW_I2C_SCL_LOW;}//讀完一個字節,將SDA重新設置為輸出SW_I2C_SDA_OUTPUT;return aByte;
}

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

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

相關文章

Python開源項目月排行 2024年2月

Python 趨勢月報&#xff0c;按月瀏覽往期 GitHub,Gitee 等最熱門的Python開源項目&#xff0c;入選的項目主要參考GitHub Trending,部分參考了Gitee和其他。排名不分先后&#xff0c;都是當前月份內相對熱門的項目。 入選公式&#xff1d;70%GitHub Trending20%Gitee10%其他 …

jvm面試題-背誦版

按照思維導圖抽查和記憶&#xff0c;答案見&#xff1a;四、面試-多線程/并發_scheduledfuture釋放-CSDN博客

Jmeter系列(4) 線程屬性詳解

線程屬性 線程組是配置壓測策略的一個重要環節線程組決定了測試執行的請求數量 線程數 在這里線程數相當于一個虛擬用戶每個線程數大約占內存1M特別注意?? 單臺機器最大線程數不要超過1000&#xff0c;不然可能會造成內存溢出 Ramp-Up時間 所有線程在多長時間內全部啟動…

【網絡工程設計】用GNS3和VMware搭建網絡環境

&#x1f4dd;本文介紹 本文主要是使用GNS3和VMware來搭建網絡環境 &#x1f44b;作者簡介&#xff1a;一個正在積極探索的本科生 &#x1f4f1;聯系方式&#xff1a;943641266(QQ) &#x1f6aa;Github地址&#xff1a;https://github.com/sankexilianhua &#x1f511;Gitee地…

計算機網絡-第2章 物理層

本章內容&#xff1a;物理層和數據通信的概念、傳輸媒體特點&#xff08;不屬于物理層&#xff09;、信道復用、數字傳輸系統、寬帶接入 2.1-2.2 物理層和數據通信的概念 物理層解決的問題&#xff1a;如何在傳輸媒體上傳輸數據比特流&#xff0c;屏蔽掉傳輸媒體和通信手段的差…

文獻閱讀筆記《Spatial-temporal Forecasting for Regions without Observations》13頁

目錄 目錄 目錄 發行刊物 ABSTRACT 1 INTRODUCTION 2 RELATED WORK&#xff08;相關工作 2.1 Spatial-temporal Forecasting&#xff08;時空預測 2.2 Spatial-temporal Forecasting withIncomplete Data&#xff08;不完全數據的時空預測 2.3 Graph Contrastive Lear…

藍橋杯集訓·每日一題2024 (前綴和)

筆記&#xff1a; 例題&#xff1a; #include<bits/stdc.h> using namespace std; const int N 5000010; char str[N]; int s[N]; int main(){int t;cin>>t;for(int a1;a<t;a){int n;cin>>n;scanf("%s",str1);for(int i1;i<n;i){s[i]s[i-1]…

【MySQL】:約束全解析

&#x1f3a5; 嶼小夏 &#xff1a; 個人主頁 &#x1f525;個人專欄 &#xff1a; MySQL從入門到進階 &#x1f304; 莫道桑榆晚&#xff0c;為霞尚滿天&#xff01; 文章目錄 &#x1f4d1;前言一. 約束概述二. 約束演示三. 外鍵約束3.1 介紹3.2 語法3.3 刪除/更新行為 &…

Mybatis - generator(自動生成)

1、生成數據庫數據 2、配置pom文件 這個plugin文件里有配置項和依賴以及版本號 修改configurationFile路徑為項目里存在的generatorConfig.xml文件&#xff0c;因為后續的配置都在這個文件中進行。 <plugin><groupId>org.mybatis.generator</groupId><…

Netty的InboundHandler 和OutboundHandler

一、InboundHandler 和OutboundHandler的區別 在Netty中&#xff0c;"inbound"表示來自外部來源&#xff08;如網絡連接&#xff09;的數據&#xff0c;而"outbound"則表示從應用程序發送到外部目標&#xff08;如網絡連接或其他服務&#xff09;的數據。…

Git——Upload your open store

0.default config ssh-keygen -t rsa #之后一路回車,當前目錄.ssh/下產生公私鑰 cat ~/.ssh/id_rsa.pub #復制公鑰到賬號 git config --global user.email account_email git config --global user.name account_name1. 上傳一個公開倉庫 查看當前分支&#xff1a; git branc…

MATLAB基于隱馬爾可夫模型-高斯混合模型-期望最大化的MR圖像分割

隱馬爾可夫模型是一種統計模型&#xff0c;它描述了馬爾可夫過程&#xff0c;隱馬爾可夫過程中包含隱變量&#xff0c;語音識別和詞性自動標注等一些領域常常使用隱馬爾可夫模型方法來處理。馬爾可夫過程是一類隨機過程&#xff0c;馬爾可夫鏈是它的原始模型&#xff0c;馬爾可…

GPT對話知識庫——FreeRTOS中寄存器BASEPRI的作用

提問模型&#xff1a;GPT-4-TURBO-PREVIEW 提問時間&#xff1a;2024.03.02 1&#xff0c;問&#xff1a; 舉例詳細說明寄存器BASEPRI在freertos中作用 1&#xff0c;答&#xff1a; 在使用FreeRTOS這樣的實時操作系統時&#xff0c;確保系統的實時性和響應能力至關重要。其中…

【C++那些事兒】深入理解C++類與對象:從概念到實踐(中)| 默認構造函數 | 拷貝構造函數 | 析構函數 | 運算符重載 | const成員函數

&#x1f4f7; 江池俊&#xff1a; 個人主頁 &#x1f525;個人專欄&#xff1a; ?數據結構冒險記 ?C那些事兒 &#x1f305; 有航道的人&#xff0c;再渺小也不會迷途。 文章目錄 1. 類的6個默認成員函數2. 構造函數2.1 概念2.2 特性 3. 析構函數3.1 概念3.2 特性 4. 拷貝…

國際視頻編解碼標準提案下載地址

H.266 相關提案下載地址&#xff1a;http://phenix.it-sudparis.eu/jvet/ 更新的地址&#xff1a;https://jvet-experts.org/ H.265 提案下載地址&#xff1a;http://phenix.int-evry.fr/jct/ 標準文檔下載地址&#xff1a;http://www.itu.int/rec/T-REC-H.265 H.264 提案下載…

QT多語言切換功能

一.目的 在做項目時&#xff0c;有時希望我們的程序可以在不同的國家使用&#xff0c;這樣最好的方式是一套程序能適應于多國語言。 Qt提供了這樣的功能&#xff0c;使得一套程序可以呈現出不同的語言界面。本文將介紹QT如何實現多語言&#xff0c;以中文和英文為例。 QT開發…

過于老舊的pytorch_ssim包 請從github下載源碼

有些冷門算法真的不要隨便pip&#xff0c;有可能下載到史前版本…最好還是找源代碼 汗 今天要用到SSIM損失函數&#xff0c;從網上簡單看了一下原理就想測試一下&#xff0c;偷了一下懶就直接在命令行輸入pip install pytorch_ssim了&#xff0c;結果報了一堆錯誤&#xff08;汗…

Qt將Unicode轉換成UTF8中文

解析字符串&#xff0c;并將里面的Unicode轉換成中文 QString unicodeToUtf8(QString unicode) {QString result;for (int i 0; i < unicode.length(); i){QString flag unicode.mid(i,2); if (flag "\\u"){QString s1 unicode.mid(i 2, 4);result.append(s…

如何自定義一個spring-boot-starter

在我的理解中&#xff0c;spring-boot-starter就是一個依賴工具包&#xff0c;但是它和普通的依賴又有所區別&#xff0c;那么首先spring-boot-starter-一定是一個spring-boot項目&#xff0c;然后它和一般的依賴有什么區別呢&#xff0c;我們可以在它的resources目錄下定義一個…

Mysql實戰(1)之環境安裝

1&#xff0c;進入&#xff1a;MySQL :: MySQL Downloads 2&#xff0c; 3&#xff0c; 4&#xff0c;