上一章所講的UART通信屬于異步通信,比如計算機發(fā)送數(shù)據(jù)給單片機,計算機只負責把數(shù)據(jù)通過TXD發(fā)送出來,接收數(shù)據(jù)是單片機自己的事情。而IIC和SPI都屬于同步通信,收發(fā)雙方需要一條時鐘線來控制收發(fā)雙方的通信節(jié)奏。
從應用上來講,UART通信多用于板間通信,比如單片機和計算機,這個設備和另外一個設備之間的通信。而IIC和SPI多用于板內(nèi)通信,比如使用IIC進行單片機和EEPROM的通信,比如使用SPI進行單片機和FLASH之間的通信。
16.1 IIC總線協(xié)議
在硬件上,IIC總線是由時鐘總線SCL和數(shù)據(jù)總線SDA兩條線構成,其中SCL為時鐘線,SDA為數(shù)據(jù)線,如圖6-1所示。總線上可以同時連接多個器件,所有器件的SCL都連到一起,所有SDA都連到一起。
6-1 IIC總線時序圖
起始信號:IIC通信的起始信號的定義是SCL為高電平期間,SDA由高電平變化到低電平產(chǎn)生的一個下降沿,表示一次通信過程的開始,如圖6-2中的Start部分所示。
數(shù)據(jù)傳輸:IIC通信是高位在前,低位在后。IIC通信要求當SCL在低電平的時候,SDA允許變化,也就是說,發(fā)送方必須先保持SCL是低電平,才可以改變數(shù)據(jù)線SDA,輸出要發(fā)送的當前數(shù)據(jù)的一個位;而當SCL在高電平的時候,SDA絕對不可以變化,因為這個時候,接收方要來讀取當前SDA的電平信號是0還是1,因此要保證SDA的穩(wěn)定,如圖6-1中的每一位數(shù)據(jù)的變化,都是在SCL的低電平位置。8位數(shù)據(jù)位后邊跟著的是一位應答位,應答位我們后邊還要具體介紹。
停止信號:IIC通信停止信號的定義是SCL為高電平期間,SDA由低電平向高電平變化產(chǎn)生一個上升沿,表示一次通信過程的結束,如圖6-1中的Stop部分所示。
26.2 IIC尋址模式
上一節(jié)介紹的是IIC每一位信號的時序流程,而IIC通信在字節(jié)級的傳輸中,也有固定的時序要求。IIC通信的起始信號(Start)后,首先要發(fā)送一個從機的地址,這個地址一共有7位,緊跟著的第8位是數(shù)據(jù)方向位(R/W),“0”表示接下來要發(fā)送數(shù)據(jù)(寫),“1”表示接下來是請求數(shù)據(jù)(讀)。
Kingst-32F1板子上的EEPROM器件型號是24C02,在24C02的數(shù)據(jù)手冊3.6節(jié)中可查到,24C02的7位地址中,其中高4位是固定的0b1010,而低3位的地址取決于具體電路的設計,由芯片上的A2、A1、A0這3個引腳的實際電平?jīng)Q定。IIC總線器件是開漏引腳,因此外部要添加上拉電阻,保證總線空閑時為高電平。來看一下24C02的電路圖,如圖6-2所示。
從圖6-2可以看出來,A2、A1、A0都是接的GND,也就是說都是0,因此24C02的7位地址實際上是二進制的0b1010000,也就是0x50。
IIC通信分為標準模式100kbit/s、快速模式400kbit/s和高速模式3.4Mbit/s。因為所有的IIC器件都支持標準模式,但卻未必支持另外兩種速度,所以作為通用的IIC程序我們選擇100k這個速率來實現(xiàn),也就是說實際程序產(chǎn)生的時序必須小于等于100k的時序參數(shù),有特殊速度需求的器件再針對性寫高速通信程序。
IIC引腳屬于開漏并聯(lián)結構,并且STM32的GPIO端口引腳設置為開漏輸出時,可以直接從輸入數(shù)據(jù)寄存器獲取I/O電平狀態(tài),因此將IIC引腳配置為開漏輸出模式。由于IIC總線空閑時默認為高,初始化時還需要設置引腳輸出高電平,不過設置引腳輸出高電平并不是在初始化之后,而應該放在初始化之前。這是因為STM32在上電復位時I/O口為高阻狀態(tài),復位結束后,GPIO端口引腳默認為浮空輸入,由于上拉電阻的存在,IIC引腳被拉高;當程序執(zhí)行到IIC初始化時又被配置為開漏輸出模式,由于GPIO端口輸出數(shù)據(jù)寄存器初始值默認全為0,初始化后I/O口輸出低電平,如果初始化之后再設置引腳輸出高電平,勢必會在I/O口上產(chǎn)生一個低電平的毛刺。如果在IIC引腳初始化之前先設置輸出數(shù)據(jù)寄存器相應位為高,初始化IIC引腳后,I/O口會直接輸出高電平,避免毛刺信號。
以下是IIC總線的驅(qū)動程序:
26.3 初識EEPROM
在實際的應用中,保存在單片機RAM中的數(shù)據(jù),掉電后就丟失了,保存在單片機內(nèi)部FLASH中的數(shù)據(jù),又不能隨意改變。但是在某些場合,我們需要記錄下某些數(shù)據(jù),而它們還需要時常改變或更新,并且掉電之后數(shù)據(jù)還不能丟失,比如我們的家用電表度數(shù),電視機里邊的頻道記憶,一般都是使用EEPROM來保存數(shù)據(jù),特點就是掉電后不丟失。Kingst-32F1板子上使用的這個器件是24C02,是一個容量大小是2Kbits,也就是256個字節(jié)的EEPROM。一般情況下,EEPROM擁有30萬到100萬次的擦除壽命,也就是它可以反復寫入30-100萬次,而讀取次數(shù)是無限的。
24C02是一個基于IIC通信協(xié)議的器件,因此從現(xiàn)在開始,IIC和EEPROM就要合體了。但要分清楚,IIC是一個通信協(xié)議,它擁有嚴密的通信時序邏輯要求,而EEPROM是掉電后數(shù)據(jù)不丟失的一種存儲器件的統(tǒng)稱,24C02就屬于EEPROM,只不過24C02采樣了IIC協(xié)議的接口與單片機相連而已,二者并沒有必然的聯(lián)系,EEPROM可以用其它接口,IIC也可以用在其它很多器件上。
46.4 EEPROM單字節(jié)讀寫操作時序
STM32F103系列單片機本身自帶硬件IIC模塊,可以類似USART通信那樣,通過配置實現(xiàn)數(shù)據(jù)的收發(fā)。本書對IIC協(xié)議的介紹針對的是絕大多數(shù)的應用場合,實際上IIC的配置過程比較復雜,比如要充分考慮沖突和仲裁等處理方式,但是那些處理方式在絕大多數(shù)場合用不到。STM32F103系列自帶的IIC協(xié)議模塊設計的過于復雜,對于實際應用來講實用性不強,因此實際應用IIC時,還是用IO口直接模擬協(xié)議。本書原則就是實際開發(fā)采用何種用法,就重點介紹何種用法,下面用實例來實現(xiàn)一下EEPROM讀寫的基本流程。
1、EEPROM寫數(shù)據(jù)流程
第一步,首先是IIC的起始信號,接著跟上首字節(jié),也就是前邊講的IIC的器件地址,并且在讀寫方向上選擇“寫”操作。
第二步,發(fā)送數(shù)據(jù)的存儲地址。24C02一共256個字節(jié)的存儲空間,地址從0x00~0xFF,想把數(shù)據(jù)存儲在哪個位置此刻寫的就是哪個地址。
第三步,發(fā)送要存儲的數(shù)據(jù),注意在寫數(shù)據(jù)的過程中,EEPROM每個字節(jié)會回應一個“應答位0”,來通知用戶寫EEPROM數(shù)據(jù)成功,如果沒有回應答位,說明寫入不成功。單字節(jié)寫時序如圖6-3所示。
圖6-3 IIC Byte Write時序圖
2、EEPROM讀數(shù)據(jù)流程
第一步,首先是IIC的起始信號,接著跟上首字節(jié),也就是前邊講的IIC的器件地址,并且在讀寫方向上選擇“寫”操作。這個地方可能有讀者會詫異,明明是讀數(shù)據(jù)為何方向也要選“寫”呢?剛才說過了,24C02一共有256個地址,選擇寫操作是為了把所要讀的數(shù)據(jù)的存儲地址先寫進去,告訴EEPROM將要讀取哪個地址的數(shù)據(jù)。這就如同打電話,先撥總機號碼(EEPROM器件地址),而后還要繼續(xù)撥分機號碼(數(shù)據(jù)地址),而撥分機號碼這個動作,主機仍然是發(fā)送方,方向依然是“寫”。
第二步,發(fā)送要讀取的數(shù)據(jù)的地址,注意是地址而非存在EEPROM中的數(shù)據(jù),通知EEPROM要哪個分機的信息。
第三步,重新發(fā)送IIC起始信號和器件地址,并且在方向位選擇“讀”操作。
這三步當中,每一個字節(jié)實際上都是在“寫”,所以每一個字節(jié)EEPROM都會回應一個“應答位0”。
第四步,讀取從器件發(fā)回的數(shù)據(jù),讀一個字節(jié),如果還想繼續(xù)讀下一個字節(jié),就發(fā)送一個“應答位ACK(0)”,如果不想讀了,告訴EEPROM,不想要數(shù)據(jù)了,別再發(fā)數(shù)據(jù)了,那就發(fā)送一個“非應答位NAK(1)”。
每讀一個字節(jié),地址會自動加1,那如果想繼續(xù)往下讀,給EEPROM一個ACK(0)低電平,那再繼續(xù)給SCL完整的時序,EEPROM會繼續(xù)往外送數(shù)據(jù)。如果不想讀了,要告訴EEPROM不要數(shù)據(jù)了,直接發(fā)送一個NAK(1)高電平。24C02讀數(shù)據(jù)時序如圖6-4所示。
圖6-4 IIC Read時序圖
利用EEPROM單字節(jié)讀寫功能設計了一個記錄開發(fā)板復位次數(shù)的小程序。由于EEPROM中的數(shù)據(jù)很容易被擦除或者改寫,為了保證記錄數(shù)據(jù)的準確性,需要對讀出的數(shù)據(jù)進行校驗。這里向大家介紹一種簡單又實用的校驗方法:將復位次數(shù)保存在EEPROM地址0x00中,并對復位次數(shù)按位取反后保存在地址0x01中。開發(fā)板每次復位后先去讀取地址0x00和0x01中的數(shù)據(jù),對其進行異或運算,如果運算結果為0xFF,表明數(shù)據(jù)正確,將地址0x00中的數(shù)據(jù)加1后,重新寫入到EEPROM中,并通過數(shù)碼管顯示讀出的數(shù)據(jù);否則記錄的數(shù)據(jù)被改寫,從0開始重新記錄復位次數(shù)。由于板載數(shù)碼管僅能顯示兩位數(shù),記錄的最大次數(shù)為99,超過99重新開始記錄。具體代碼如下:
56.5 EEPROM多字節(jié)讀寫操作時序
讀取EEPROM很簡單,EEPROM根據(jù)時序直接把數(shù)據(jù)送出來,但是寫EEPROM卻沒有這么簡單了。給EEPROM發(fā)送數(shù)據(jù)后,先保存在EEPROM的緩存,EEPROM必須要把緩存中的數(shù)據(jù)搬移到“非易失”的區(qū)域,才能達到掉電不丟失的效果。而往非易失區(qū)域?qū)懶枰欢ǖ臅r間,每種器件不完全一樣,ATMEL公司的24C02的這個寫入時間最長不超過5ms。在往非易失區(qū)域?qū)懙倪^程,EEPROM是不會再響應用戶訪問的,不僅接收不到用戶的數(shù)據(jù),即使用I^2^C標準的尋址模式去尋址,EEPROM都不會應答,就如同這個總線上沒有這個器件一樣。數(shù)據(jù)寫入非易失區(qū)域完畢后,EEPROM再次恢復正常,可以正常讀寫了。
在向EEPROM連續(xù)寫入多個字節(jié)的數(shù)據(jù)時,如果每寫一個字節(jié)都要等待幾ms的話,整體上的寫入效率就太低了。因此EEPROM的廠商就想了一個辦法,把EEPROM分頁管理。24C01、24C02這兩個型號是8個字節(jié)一個頁,24C04、24C08、24C16是16個字節(jié)一頁。Kingst-32F1開發(fā)板上用的型號是24C02,一共是256個字節(jié),8個字節(jié)一頁,那么就一共有32頁。
分配好頁之后,如果在同一個頁內(nèi)連續(xù)寫入幾個字節(jié)后,最后再發(fā)送停止位的時序。EEPROM檢測到這個停止位后,會一次性把這一頁的數(shù)據(jù)寫到非易失區(qū)域,就不需要寫一個字節(jié)檢測一次了,并且頁寫入的時間也不會超過5ms。如果寫入的數(shù)據(jù)跨頁了,寫完一頁之后要發(fā)送一個停止位,然后等待并且檢測EEPROM的空閑模式,一直等到把上一頁數(shù)據(jù)完全寫到非易失區(qū)域后,再進行下一頁的寫入,這樣就可以在很大程度上提高數(shù)據(jù)的寫入效率,頁寫時序如圖6-5所示。
圖6-5 EEPROM頁寫時序
本節(jié)利用EEPROM多字節(jié)讀寫功能設計了一個通過串口發(fā)送指令控制EEPROM讀寫數(shù)據(jù)的例程。該例程只需要下載一次程序,就能通過串口調(diào)試助手實現(xiàn)對EEPROM任意地址的讀寫操作,避免重復編程控制EEPROM讀寫數(shù)據(jù)的方式,具有很高是實用意義。與第五章串口實用例程類似,通過串口調(diào)試助手發(fā)送控制指令,單片機檢測到指令后做出相應動作。
EEPROM讀數(shù)據(jù)指令格式:“e2read 地址 字節(jié)長度”,其中地址范圍為0~255,e2read、地址、字節(jié)長度之間由空格隔開,比如從地址1開始讀取5字節(jié)數(shù)據(jù):e2read 1 5。單片機收到指令后執(zhí)行多字節(jié)讀操作,通過串口助手返回讀出的數(shù)據(jù)。
EEPROM寫數(shù)據(jù)指令格式:“e2write 地址 數(shù)據(jù)”,地址范圍為0~255,e2write、地址、數(shù)據(jù)之間同樣由空格隔開,比如從地址1開始寫入hello:e2write 1 hello。單片機收到指令后執(zhí)行多字節(jié)寫操作,寫入成功后通過串口助手返回“e2write done.”
如果發(fā)送指令格式錯誤,返回“bad parameter.”,如果發(fā)送指令錯誤,將返回發(fā)送的指令。
-
單片機
+關注
關注
6063文章
44931瀏覽量
647246 -
SPI
+關注
關注
17文章
1784瀏覽量
94818 -
EEPROM
+關注
關注
9文章
1082瀏覽量
83310 -
IIC
+關注
關注
11文章
306瀏覽量
39200 -
uart
+關注
關注
22文章
1269瀏覽量
103318
發(fā)布評論請先 登錄
一文詳解IIC總線

一文詳解IIC總線

IIC總線和SPI總線的比較

一文解讀IIC總線的FPGA實現(xiàn)原理及過程

評論