I2C總線之(三)---以C語言理解IIC

為了加深對I2C總線的理解,用C語言模擬IIC總線,邊看源代碼邊讀波形:

如下圖所示的寫操作的時序圖:

?

讀時序的理解同理。對于時序不理解的朋友請參考“I2C總線之(二)---時序”

完整的程序如下:

?

復制代碼
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define write_ADD 0xa0
#define read_ADD 0xa1
uchar a;  
sbit SDA=P2^0;
sbit SCL=P2^1;
void SomeNop();     //短延時
void init();    //初始化
void check_ACK(void);
void I2CStart(void);
void I2cStop(void);
void write_byte(uchar dat);//寫字節
void delay(uint z);
uchar read_byte();     //讀字節
void write(uchar addr,uchar dat);  //指定地址寫
uchar read(uchar addr);       //指定地址讀
bit flag;  //應答標志位
void main()
{init();write_add(5,0xaa); //向地址5寫入0xaadelay(10);      //延時,否則被坑呀!!!P1=read_add(5);      //讀取地址5的值while(1);    
}//***************************************************************************  
void delay()//簡單延時函數  
{ ;; }  
//***************************************************************************  
void start()  //開始信號 SCL在高電平期間,SDA一個下降沿則表示啟動信號  
{     sda=1; //釋放SDA總線  
    delay();  scl=1;  delay();  sda=0;  delay();  
}  
//***************************************************************************  
void stop()   //停止 SCL在高電平期間,SDA一個上升沿則表示停止信號  
{  sda=0;  delay();  scl=1;  delay();  sda=1;  delay();  
}
//***************************************************************************  
void respons()  //應答 SCL在高電平期間,SDA被從設備拉為低電平表示應答  
{  uchar i;  scl=1;  delay(); //至多等待250個CPU時鐘周期 while((sda==1)&&(i<250))i++;  scl=0;  delay();  
}  
//***************************************************************************  
void init()//總線初始化 將總線都拉高一釋放總線  發送啟動信號前,要先初始化總線。即總有檢測到總線空閑才開始發送啟動信號  
{  sda=1;  delay();  scl=1;  delay();  
}  
//***************************************************************************  
void write_byte(uchar date) //寫一個字節  
{  uchar i,temp;  temp=date;  for(i=0;i<8;i++)  {  temp=temp<<1;  scl=0;//拉低SCL,因為只有在時鐘信號為低電平期間按數據線上的高低電平狀態才允許變化;并在此時和上一個循環的scl=1一起形成一個上升沿  
        delay();  sda=CY;  delay();  scl=1;//拉高SCL,此時SDA上的數據穩定  
        delay();  }  scl=0;//拉低SCL,為下次數據傳輸做好準備  
    delay();  sda=1;//釋放SDA總線,接下來由從設備控制,比如從設備接收完數據后,在SCL為高時,拉低SDA作為應答信號  
    delay();  
}  
//***************************************************************************  
uchar read_byte()//讀一個字節  
{  uchar i,k;  scl=0;  delay();  sda=1;  delay();  for(i=0;i<8;i++)  {  scl=1;//上升沿時,IIC設備將數據放在sda線上,并在高電平期間數據已經穩定,可以接收啦  
        delay();      k=(k<<1)|sda;  scl=0;//拉低SCL,使發送端可以把數據放在SDA上  
        delay();      }  return k;  
}  
//***************************************************************************  
void write_add(uchar address,uchar date)//任意地址寫一個字節  
{  start();//啟動  write_byte(0xa0);//發送從設備地址  respons();//等待從設備的響應  write_byte(address);//發出芯片內地址  respons();//等待從設備的響應  write_byte(date);//發送數據  respons();//等待從設備的響應  stop();//停止  
}  
//***************************************************************************  
uchar read_add(uchar address)//讀取一個字節  
{  uchar date;  start();//啟動  write_byte(0xa0);//發送發送從設備地址 寫操作  respons();//等待從設備的響應  write_byte(address);//發送芯片內地址  respons();//等待從設備的響應  start();//啟動  write_byte(0xa1);//發送發送從設備地址 讀操作  respons();//等待從設備的響應  date=read_byte();//獲取數據  stop();//停止  return date;//返回數據  
}

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

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

相關文章

結對編程總結

這個項目我和我的結對伙伴共花了兩個月時間&#xff0c;之所以選這個項目&#xff0c;因為我們之前都學習過Python&#xff0c;也做過類似的程序&#xff0c;相比較其他項目而言&#xff0c;這個項目更合適&#xff0c;也讓我們對詞頻統計方面的知識加深了了解。寫這個程序我們…

JavaScript初學者必看“new”

2019獨角獸企業重金招聘Python工程師標準>>> 譯者按: 本文簡單的介紹了new, 更多的是介紹原型(prototype)&#xff0c;值得一讀。 原文: JavaScript For Beginners: the ‘new’ operator 譯者: Fundebug 為了保證可讀性&#xff0c;本文采用意譯而非直譯。 <di…

libGDX-wiki發布

為方便大家學習和訪問&#xff0c;我將libgdx的wiki爬取到doku-wiki下&#xff0c;專門建立了以下地址。歡迎大家來共同完善。 http://wiki.v5ent.com 轉載于:https://www.cnblogs.com/mignet/p/ligbdx_wiki.html

I2C讀寫時序

1. I2C寫時序圖&#xff1a; 注意&#xff1a;最后一個byte后&#xff0c;結束標志在第十個CLK上升沿之后&#xff1a; 2. I2C讀時序圖&#xff1a; 注意&#xff1a;restart信號格式&#xff1b;讀操作結束前最后一組clk的最后一個上升沿&#xff0c;主機應發送NACK&#xff0…

網站性能優化

基本概念 1、網站吞吐量&#xff1a;TPS/每秒的事務數&#xff0c;QPS/每秒的查詢數&#xff0c;HPS/每秒的HTTP請求數 2、服務器性能指標&#xff1a;系統負載&#xff0c;內存使用&#xff0c;CPU使用&#xff0c;磁盤使用以及網絡I/O等 前端優化方法 1、減少HTTP請求&#x…

JAVA-容器(2)-Collection

&#xff08;基于JDK1.8源碼分析&#xff09; 一&#xff0c;Collection 所有實現Collection接口的類原則上應該提供兩種構造函數&#xff1a; 【1】無參構造-創建一個空的容器 【2】有參構造-創建一個新的Collection&#xff0c;這個新的Collection和傳入的Collection具有相同…

軟件測試工具LoadRunner中如何定義SLA?--轉載

軟件測試工具LoadRunner中如何定義SLA&#xff1f; 瀏覽&#xff1a;2242|更新&#xff1a;2017-04-09 22:50SLA 是您為負載測試場景定義的具體目標。Analysis 將這些目標與軟件測試工具LoadRunner在運行過程中收集和存儲的性能相關數據進行比較&#xff0c;然后確定目標的 SLA…

最近閱讀20171106

java面試題 線上服務內存OOM問題定位三板斧 JVM的GC ROOTS存在于那些地方 mysql innodb怎樣做查詢優化 ----未閱讀 JAVA CAS原理深度分析----未閱讀 轉載于:https://www.cnblogs.com/Tpf386/p/7793248.html

LinuxI2C驅動--從兩個訪問eeprom的例子開始

本小節介紹兩個在linux應用層訪問eeprom的方法&#xff0c;并給出示例代碼方便大家理解。第一個方法是通過sysfs文件系統對eeprom進行訪問&#xff0c;第二個方法是通過eeprom的設備文件進行訪問。這兩個方法分別對應了i2c設備驅動的兩個不同的實現&#xff0c;在后面的小結會詳…

Cookie詳解整理

1.Cookie的誕生 由于HTTP協議是無狀態的&#xff0c;而服務器端的業務必須是要有狀態的。Cookie誕生的最初目的是為了存儲web中的狀態信息&#xff0c;以方便服務器端使用。比如判斷用戶是否是第一次訪問網站。目前最新的規范是RFC 6265&#xff0c;它是一個由瀏覽器服務器共同…

驍龍820和KryoCPU:異構計算與定制計算的作用 【轉】

本文轉載自&#xff1a;https://www.douban.com/group/topic/89037625/ Qualcomm驍龍820處理器專為提供創新用戶體驗的頂級移動終端而設計。為實現消費者所期望的創新&#xff0c;移動處理器必須滿足日益增長的計算需求且降低功耗&#xff0c;同時還要擁有比以往更低的溫度&…

LNMP

準備工作 建立一個軟件包目錄存放 mkdir -p /usr/local/src/ 清理已經安裝包 rpm -e httpd rpm -e mysql rpm -e php yum -y remove httpd yum -y remove mysql yum -y remove php #搜索apache包 rpm -qa http* #強制卸載apache包 rpm -e --nodeps 查詢出來的文件名 #檢查是否卸…

算法復習——計算幾何基礎(zoj1081)

題目&#xff1a; Statement of the Problem Several drawing applications allow us to draw polygons and almost all of them allow us to fill them with some color. The task of filling a polygon reduces to knowing which points are inside it, so programmers have …

亞馬遜Rekognition發布針對人臉檢測、分析和識別功能的多項更新

今天亞馬遜Rekognition針對人臉檢測、分析和識別功能推出了一系列更新。這些更新將為用戶帶來多項能力的改今&#xff0c;包括從圖像中檢測出更多人臉、執行更高精度的人臉匹配以及獲得圖像中的人臉得到更準確的年齡、性別和情感屬性。Amazon Rekognition的客戶可以從今天開始使…

(轉)CentOS分區操作詳解

CentOS分區操作詳解 原文&#xff1a;http://blog.csdn.net/yonggeit/article/details/77924393 磁盤分區 分區格式的兩種選擇&#xff1a;MBR和GPT 分區命令&#xff1a; parted的操作都是實時生效的&#xff0c;小心使用&#xff0c;主要是用于大于2T硬盤&#xff0c;支持MBR…

linux驅動中地址空間轉換

在linux kernel 中&#xff0c;物理地址是不能直接使用的&#xff0c;必須通過轉換才可以。轉換分為兩種&#xff0c; 靜態和動態。 靜態就是下面那種&#xff0c;不過&#xff0c;靜態的地址轉換&#xff0c;還需要在kernel 初始化的時候作映射。 動態映射是使用 ioremap 函…

getClass()和.class的區別

getClass()和.class的區別 在學習反射時想到了這個問題&#xff0c;.getClass()和.class有沒有什么區別&#xff1f; 當然&#xff0c;最明顯的區別就是.getClass()是一個對象實例的方法&#xff0c;只有對象實例才有這個方法&#xff0c;具體的類是沒有的。類的Class類實例是通…

華為敏捷 DevOps 實踐:產品經理如何開好敏捷回顧會議

開篇小故事&#xff1a;前幾年&#xff0c;一本叫《沉思錄》的書在國內突然曝光度很多&#xff0c;因為前某國家領導人“擺案頭&#xff0c;讀百遍”。《沉思錄》是古羅馬皇帝馬可奧勒寫給自己的書&#xff0c;內容大部分是在鞍馬勞頓中寫的。其實有一句“我們所聽到的不過只是…

斐波那契數列的鬼畜的性質

斐波那契數列的鬼畜的性質 斐波那契數列定理1 \(gcd(f[i],f[i1])1\) 利用輾轉相減法 證明&#xff1a;\(gcd(f[i],f[i1])\)\(gcd(f[i1]-f[i],f[i])\)\(gcd(f[i-1],f[i])\)\(....\)\(gcd(f[1],f[2])1\) 斐波那契數列定理2 \(f[mn]f[m-1]f[n]f[m]f[n1]\) 證明&#xff1a;\(f[mn]…