久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4458|回復: 12
打印 上一主題 下一主題
收起左側

小白菜的IIC學習之路

  [復制鏈接]
跳轉到指定樓層
樓主
ID:70650 發表于 2014-12-19 02:38 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
一,為了那“可惡”的目的
2011 年初,小白菜的工作比較清閑了,于是小白菜就開始IIC 學習之路。
之前在用 IIC 總線(口線模擬)時,總感覺IIC 移植時不夠簡介易懂,使用時,函數不
能夠適應所有IIC 操作,于是小白菜想改寫一下IIC 總線操作,使之成為真正的萬能IIC 總
線驅動。于是小白菜找到目標了:
一是編寫一個移植性極其好的 IIC 總線操作,只需要簡單的改動就能完成移植。
二是編寫兩個函數,一個是向器件發送數據函數,一個是從器件中讀取數據函數。并且
這兩個函數真正適應所有不同的IIC 器伯的操作。
二,過程抽象
為了達到以上的目的,小白菜需要先對 IIC 進行一次抽象。
1 單片機向器件發送數據時的抽象過程
(這里的抽象指的是抽象出不依賴具體器件的 IIC 操作)
發送時的流程:
(1) MCU 啟動總線
(2) 發送器件IIC 地址 接收 ACK 信號
(3) 發送寄存器地址1  接收 ACK 信號 [發送寄存器地址2  接收 ACK 信號]
有些器件可能沒有寄存器地址(小白菜還沒有遇到過),所以該步可能不需要。
(4) 發送數據1  接收 ACK 信號
 發送數據2  接收 ACK 信號
 發送數據3  接收 ACK 信號
……
(5) MCU 關閉總線,發送完成。
我們來具體的分析一下,
第(1)步啟動總線,
第(2)步發送 1B 數據(IIC 地址),接收一個ACK 信號
第(3)步發送 1B 數據(寄存器地址1),接收一個ACK 信號,發送1B 數據(寄存器地址2),
接收一個ACK 信號
第(4)步發送 1B 數據(數據1),接收一個ACK 信號,發送1B 數據(數據2),接收一個
ACK 信號……
第(5)步關閉總線
寫到這里,有些人可能看出來了,其實發送時不論數據或地址,都是一個相同過程,啟
動總線后,MCU 發送一個字節,等一個ACK 信號,再發送一個字節,等一個ACK 信號,
發送……,哎、發送完了,得了,關閉總線。
繼續進行抽象,我們可以把第(2)、(3)、(4)步進行合并,得到IIC 寫操作抽象:
第(1)步啟動總線,
第(2) (3) (4)步發送 1B 數據,接收一個ACK 信號,直到發送完成
第(5)步關閉總線
到這里之后,似乎是大功告成了,但是小白菜一想,這么多數據,參數肯定是用指針+
數據字節數還進行傳遞,可是像讀寫EEPROM 這樣的器件,地址就丙三字節,但一次寫入
的數據可能有很多個字節,于是小白菜把(2) (3) 合在一起,把數據發送部分(4)單獨拿出來。
小白菜得到了最終的 IIC 寫操作的抽象
第(1)步啟動總線,
第(2) (3)步發送 1B 數據,接收一個ACK 信號,直到發送完成(發送地址)
第(4)步發送 1B 數據,接收一個ACK 信號,直到發送完成 (發送數據)
第(5)步關閉總線
小白菜據此寫出了函數名及形參和流程圖(就是上面的抽象,所以嘛,就不寫了)。
extern uint8 IIC_MCU_Send_Str(uint8 *PAddr, uint8 AddrNum, uint8 *PDataAddr, uint16 DataNum)
*PAddr :I 第1 批發送的數據的首地址。這部分IC 地址以及子地址。PAddr[0]中存放IIC
地址,后面的存放子地址。
AddrNum :IIC 以及子地址的字節數。不可為0.
*PDataAddr :第2 批發送的數據的首地址。這部分是發送的數據。
DataNum :第2 批要發送的字節數(最大為65536 個字節)。為0 時不發送這一部分。
2 單片機從有寄存器的IIC 器件讀取數據時的抽象過程:
發送時的流程:
(1) MCU 啟動總線
(2) 發送器件IIC 地址 接收 ACK 信號
(3) 發送寄存器地址1  接收 ACK 信號 [發送寄存器地址2  接收 ACK 信號]
有些器件可能沒有寄存器地址(小白菜還沒有遇到過),所以該步可能不需要。
(4) MCU 重新啟動總線
(5) 發送器件IIC 地址(最低位置1 以表明是讀操作)  接收 ACK 信號
(6) 接收數據1  發送 ACK 信號
接收數據2  發送 ACK 信號
接收數據3  發送 ACK 信號
……
(7) 接收最后一字節數據 發送非ACK 信號
(8) MCU 關閉總線,接收完成。
根據該流程,我們可以清楚地得到讀取時的抽象:
第(1)步 MCU 啟動總線
第(2) (3) 步發送 1B 數據,接收一個ACK 信號,直到發送完成(發送地址)
第(4) 步 MCU 重新啟動總線
第(5) 步發送器件IIC 地址(最低位置1 以表明是讀操作)  接收 ACK 信號
第(6) 步接收前面的字節,發送ACK 信號
第(7) 步接收最后一字節數據,發送非ACK 信號
第(8) 步 MCU 關閉總線,接收完成。
雖然這里步驟多了,但是,函數參數也用不了幾個,首先要知道地址吧,還要知道數據讀出
來后存放在哪里吧,小白菜想了想,這個函數的參數和寫操作函數的參數一樣就行了,
于是小白菜據寫出了函數名及形參和流程圖(就是上面的抽象,所以嘛,你懂得)
extern uint8 IIC_MCU_Rcv_Str(uint8 *PAddr, uint8 AddrNum, uint8 *PDataAddr, uint16
DataNum)
*PAddr :發送的數據的首地址。這部分IC 地址以及子地址。PAddr[0]中存放IIC 地址,
后面的存放子地址。
AddrNum :IIC 以及子地址的字節數。不可為0.
*PDataAddr :存放所接收數據的首地址
DataNum :要接收的字節數。
三 奮筆疾書 + 代碼移植
小白菜開始了寫代碼了。因為是小白菜嘛,所以一開始也不知道哪些地方在移植時需要
修改,于是就開始先寫代碼,可能在寫的時候就能知道了。寫啊寫,寫啊寫,終于讓小白菜
寫完了。
寫著寫著還真讓小白菜找出了哪里需要移植了。口線需要更改吧,不同的單片機,頭
文件不一樣吧,還得有延時函數需要改吧……
于是小白菜把在移植時需要更改的地方做了一個“表”,放在H 文件中的“移植修改”
部分。這樣,在修改時就可以只修改H 文件中的一個地方,就能快速的完成移植。
現在想想,小白菜有的時候也不是那么菜嘛(偷笑 ing)。
到現在為止,小白菜的目的已經達到了。突然,后背一涼,心里一個想法冒出來了,
剛寫完的代碼還沒測試就飄飄然了!哎,被勝利沖昏了頭腦。于是小白菜自已測試了一番,
Bug 還真是有,改改更健康~~
四使用說明
4.1 移植修改
移植修改都在 H 文件中的移植修改部分。下面進行具體說明。
//----------------------------------------------------------------------------//
// 編號:1
// 名稱:
// 功能:單片機寄存器頭文件,例如reg51.h
//----------------------------------------------------------------------------//
#include "ATT703x.H"
4.1.1 這部分是請您把使用的單片機的頭文件包含進來。大蝦們用過MCU 多了,知道不同
的MCU,其寄存器定義是不一樣滴,不是所有的51 單片機都用Reg51.H 或Reg52.H 頭文
件的。
//----------------------------------------------------------------------------//
// 編號:2
// 名稱:SDA, SCL
// 功能:模擬I2C 數據傳送位
//----------------------------------------------------------------------------//
#if defined(IIC_IO_ENABLE)
sbit SDA = P0^0; // 模擬I2C 數據傳送位。
sbit SCL = P2^6; // 模擬I2C 時鐘控制位。
#endif
4.1.2 SDA 和SCL 口線定義。這里就是您用的口線,如果您告訴我您不知道怎么改,好吧,
你贏了……
//----------------------------------------------------------------------------//
// 編號:3
// 名稱:IIC_Delay_1US()
// 功能:精確的1 微秒延時函數。請根據您所用的單片機來正確設置。
// :如果您的系統中有精確的微妙級延時函數,那么您可以直接使用。
// :例如,您的延時函數是Delay_1us(),那么您可以使用下句
// :#define IIC_Delay_1us() Delay_1us()
// :來實現延時。
//----------------------------------------------------------------------------//
#defineIIC_Delay_500ns() _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
#define IIC_Delay_1US() IIC_Delay_500ns();IIC_Delay_500ns();
4.1.3 軟件延時函數,這里是標準IIC,不是快速IIC。1us 的延時怎么做呢?當然是nop 函
數了。如果您不知道一個nop 的執行時間,那么說明您需要好好看看手冊了。
4.1.4 好多單片機都需要設置時鐘,設置GPIO 狀態,所以在使用IIC 之前,請一定確保MCU
先初始化完畢。
4.2 函數說明
4.2.1 MCU 向IIC 器件發送多字節數據函數
//----------------------------------------------------------------------------//
// MCU 向IIC 器件發送多字節數據函數(對外提供服務)
//函數名稱:IIC_MCU_Send_Str
//函數功能:MCU 向IIC 從器件發送多字節數據。本函數是寫IIC 從器件的抽象函數。
//入口參數:
// *PAddr: IIC 地址以及子地址。PAddr[0]中存放IIC 地址,后面的存放子地址。
// AddrNum : IIC 以及子地址的字節數。不可為0.
//
// *PDataAddr: 第 2 批發送的數據的首地址。這部分是發送的數據。
// DataNum : 第 2 批要發送的字節數(最大為65536 個字節)。為0 時不發送這一部分。
//出口參數:0 = 操作成功,1 = 操作出錯。
//重要說明:這是一個從啟動IIC 總線到發送數據再到最后結束總線為止的完整的發送過程。
// 數據發送的順序是先發送PAddr[0],最后發送PAddr[AddrNum - 1],然后發送
// PDataAddr[0],最后發送PDataAddr[DataNum - 1]。
// 一般地,PAddr 用于發送器件IIC 地址和子地址,PDataAddr 用于發送數據。
// 本函數對有無子地址的IIC 器件都適用。
//----------------------------------------------------------------------------//
extern uint8 IIC_MCU_Send_Str(uint8 *PAddr, uint8 AddrNum, uint8 *PDataAddr, uint16
DataNum)
應用示例:
從 0x00 字節地址開始寫AT24C02,寫入10 個字節數(這里不考慮頁寫等待,因為和
IIC 寫無關),這10B 數據存放在unsigned char Buf[10]中,寫入時要求Buf[0]寫入0x00 字節
地址,Buf[1]寫入0x01 字節地址……。
A2、A1、A0 全接地。(有人說我沒說明WP 的接法……我只有一個問題,你是來砸場
子的么!!!)
首先組織 IIC 地址,設置一數組unsigned char Addr[2],其中Addr[0] = 0xA0,Addr[1] = 0x00;
Addr [0]中存放的是(二進制表示) 1 0 1 0 A2 A1 A0 0(LSB)
Addr [1]中存放的是(二進制表示) a7 a6 a5 a4 a3 a2 a1 a0(LSB)
調用時 IIC_MCU_Send_Str(Addr, 2, Buf, 10);
您還應當查看一下函數的返回值,是0 表示操作成功,否則操作失敗。
4.2.1 MCU 從有子地址的IIC 器件中接收多字節函數
//----------------------------------------------------------------------------//
// MCU 從有子地址的IIC 器件中接收多字節函數(對外接口)
//函數名稱:IICMCURcvStr
//函數功能:本函數用于有子地址的IIC 器件的讀操作。
//入口參數:
// *PAddr: IIC 地址以及子地址。PAddr[0]中存放IIC 地址,后面的存放子地址。
// AddrNum : IIC 以及子地址的字節數。為0 時出錯.
// *PDataAddr:存放所接收數據的首地址
// DataNum : 要接收的字節數。合法值1-65535。為0 時出錯。
//
//出口參數:0 = 操作成功,1 = 操作出錯。
//重要說明:
// 讀取的第一個數據存放在PDataAddr[0]中,第一個存放在PDataAddr[1]中……
// 有子地址的IIC 器件的讀操作是:
// MCU 先啟動總線,然后發送器件的IIC 地址和需要操作的子地址
//(這一部分就是*PAddr),之后重新啟動總線,再次發送器件的IIC 地址且最低位置1 以表
明是讀
// 操作,等待應答后便開始接收數據(這一部分是*PDataAddr),最后關閉總線。
//----------------------------------------------------------------------------//
extern uint8 IIC_MCU_Rcv_Str(uint8 *PAddr, uint8 AddrNum, uint8 *PDataAddr, uint16
DataNum)
讀取的第一個數據存放在 PDataAddr[0]中,第一個存放在PDataAddr[1]中……
應用示例:
從 0x00 字節地址開始讀AT24C02,讀10 個字節數并且存放在unsigned char Buf[10]中,
A2、A1、A0 全接地。(有人說我沒說明WP 的接法……還提這個問題!!)
首先組織 IIC 地址,設置一數組unsigned char Addr[2],其中Addr[0] = 0xA0,Addr[1] = 0x00;
Addr [0]中存放的是(二進制表示) 1 0 1 0 A2 A1 A0 0(LSB)
Addr [1]中存放的是(二進制表示) a7 a6 a5 a4 a3 a2 a1 a0(LSB)
調用時 IIC_MCU_Rcv_Str (Addr, 2, Buf, 10);
這樣,Buf[0]是讀取到的0x00 字節地址的數據,Buf[1]是0x01 字節地址的數據……
您還應當查看一下函數的返回值,是 0 表示操作成功,否則操作失敗。
五 最后的廢話
好吧,有人會說這個實現的有點羅嗦,不如直接以IIC 地址,寄存器地址做參數來的方
便;雖然有時候我也這么覺得。
但是、但是、但是什么呢?下期見!
3htech
我是一顆小白菜

程序下載: IIC.rar (94 KB, 下載次數: 53)

評分

參與人數 1黑幣 +5 收起 理由
ssfc + 5 很給力!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:72947 發表于 2015-1-31 21:25 來自手機 | 只看該作者
樓下高手,謝謝分享!!
回復

使用道具 舉報

板凳
ID:29438 發表于 2015-2-7 09:02 | 只看該作者
只能說謝謝。
回復

使用道具 舉報

地板
ID:70330 發表于 2015-2-10 11:20 | 只看該作者
只能說謝謝了
回復

使用道具 舉報

5#
ID:70330 發表于 2015-2-10 11:20 | 只看該作者
樓主強大,學習了
回復

使用道具 舉報

6#
ID:73775 發表于 2015-2-21 16:47 | 只看該作者
只能說謝謝。
回復

使用道具 舉報

7#
ID:73775 發表于 2015-2-21 16:53 | 只看該作者
學習一下,看看效果
回復

使用道具 舉報

8#
ID:72238 發表于 2015-2-23 19:50 | 只看該作者
謝謝樓主
學習一下
回復

使用道具 舉報

9#
ID:79694 發表于 2016-3-6 08:57 | 只看該作者

謝謝樓主
學習一下
回復

使用道具 舉報

10#
ID:110516 發表于 2016-9-29 13:16 | 只看該作者
好用, 學習了
回復

使用道具 舉報

11#
ID:128463 發表于 2017-4-4 12:03 | 只看該作者
謝謝分享!!
回復

使用道具 舉報

12#
ID:383525 發表于 2019-7-16 10:03 | 只看該作者
感謝樓主
回復

使用道具 舉報

13#
ID:585455 發表于 2019-7-17 20:00 | 只看該作者
感謝再感謝。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产欧美在线 | 精品网| 欧美精品久久一区 | 在线观看av网站永久 | 国产欧美精品一区二区 | 91精品国产综合久久久久久蜜臀 | 久久久久久成人 | 天天操夜夜操 | 亚洲欧洲综合av | 午夜爽爽爽男女免费观看影院 | 91精品国产一区二区 | 日韩中文字幕免费在线观看 | 一级毛片播放 | 国产一级电影在线 | 亚洲一区二区在线播放 | 中文字幕乱码一区二区三区 | 亚洲成人免费av | 99热.com | 91精品久久久久久久久99蜜臂 | 国产一区二区三区免费 | 成人h动漫精品一区二区器材 | 亚洲精品在线看 | 99精品视频免费观看 | 九九热热九九 | 中文字幕在线电影观看 | 九九伦理片 | 懂色中文一区二区在线播放 | 91av视频在线播放 | 欧美freesex黑人又粗又大 | 粉嫩粉嫩芽的虎白女18在线视频 | 成人欧美一区二区三区在线播放 | 黄网址在线观看 | 久久久精品一区 | 国产一区二区三区在线 | 国产精品久久av | 欧美高清一区 | 手机看黄av免费网址 | 久久这里只有 | 国产成人免费在线 | 高清人人天天夜夜曰狠狠狠狠 | 国产免费一区二区三区 |