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

一文詳解IIC總線

SPI總線學(xué)習(xí)筆記

IIC總線和SPI總線的比較

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

一文講透SPI總線和IIC總線通信2

一文講透SPI總線和IIC總線通信3

一文講透SPI總線和IIC總線通信4

評論