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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4618|回復(fù): 12
打印 上一主題 下一主題
收起左側(cè)

小白菜的IIC學(xué)習(xí)之路

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

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

評分

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

查看全部評分

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

使用道具 舉報

沙發(fā)
ID:72947 發(fā)表于 2015-1-31 21:25 來自觸屏版 | 只看該作者
樓下高手,謝謝分享!!
回復(fù)

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

5#
ID:70330 發(fā)表于 2015-2-10 11:20 | 只看該作者
樓主強(qiáng)大,學(xué)習(xí)了
回復(fù)

使用道具 舉報

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

使用道具 舉報

7#
ID:73775 發(fā)表于 2015-2-21 16:53 | 只看該作者
學(xué)習(xí)一下,看看效果
回復(fù)

使用道具 舉報

8#
ID:72238 發(fā)表于 2015-2-23 19:50 | 只看該作者
謝謝樓主
學(xué)習(xí)一下
回復(fù)

使用道具 舉報

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

謝謝樓主
學(xué)習(xí)一下
回復(fù)

使用道具 舉報

10#
ID:110516 發(fā)表于 2016-9-29 13:16 | 只看該作者
好用, 學(xué)習(xí)了
回復(fù)

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

使用道具 舉報

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

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 成人免费毛片在线观看 | 91精品一区二区三区久久久久久 | 日韩中出| 久久国产免费 | 国产精品久久国产精品久久 | 欧美视频免费在线 | 中文字幕精品一区二区三区精品 | 中文一区 | 久久久精 | 亚洲精品久久久久久下一站 | 久久久久久久久久久久亚洲 | 激情av在线 | 看黄在线| 亚洲精品久久久久avwww潮水 | 我爱操| 欧美在线观看一区二区 | 国产精品久久久久久久久久久久冷 | 国产精品综合一区二区 | 男人天堂网址 | 欧美日韩在线观看视频网站 | 亚洲精品在线观看网站 | 久久综合伊人一区二区三 | 九九热精品在线 | 成人欧美一区二区三区在线观看 | a级片网站 | 一级日批片 | 91传媒在线播放 | 成人免费毛片片v | 久久久久国产一区二区三区四区 | 波多野结衣中文视频 | 久久婷婷国产麻豆91 | 国产成人啪免费观看软件 | www.成人在线视频 | 亚洲国产精品一区二区第一页 | 免费看国产一级特黄aaaa大片 | 免费观看黄网站 | 国产亚洲精品久久午夜玫瑰园 | 在线看亚洲 | 一区二区三区视频 | 人人爽日日躁夜夜躁尤物 | 特黄毛片视频 |