0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

周立功:深入淺出AMetal談SPI總線和IIC 總線

UtFs_Zlgmcu7890 ? 來源:未知 ? 作者:劉勇 ? 2017-12-13 06:27 ? 次閱讀

第五章為深入淺出AMetal,本文內(nèi)容為5.5 SPI 總線和5.6 I2C 總線。

5.5 SPI 總線

>>> 5.5.1 初始化

在使用SPI 通用接口前,必須先完成SPI 的初始化,以獲取標準的SPI 實例句柄。LPC82x支持SPI 功能的外設(shè)有SPI0 和SPI1,為方便用戶使用,AMetal 提供了與各外設(shè)對應(yīng)的實例初始化函數(shù),詳見表5.10。

表5.10 SPI 實例初始化函數(shù)(am_lpc82x_inst_init.h)

這些函數(shù)的返回值均為am_spi_handle_t 類型的SPI 實例句柄,該句柄將作為SPI 通用接口中handle 參數(shù)的實參。類型am_spi_handle_t(am_spi.h)定義如下:

因為函數(shù)返回的SPI 實例句柄僅作為參數(shù)傳遞給SPI 通用接口,不需要對該句柄做其它任何操作,因此完全不需要了解該類型。注意,若函數(shù)返回的實例句柄的值為NULL,則表明初始化失敗,不能使用該實例句柄。

如需使用SPI0,則直接調(diào)用SPI0 實例初始化函數(shù),即可獲取對應(yīng)的實例句柄:

>>>5.5.2 接口函數(shù)

MCU 的SPI 主要用于主從機的通信,AMetal 提供了8 個接口函數(shù),詳見表5.11。

表5.11 SPI 標準接口函數(shù)

1. 從機實例初始化

對于用戶來說,使用SPI 往往是直接操作一個從機器件,MCU 作為SPI 主機,為了與從機器件通信,需要知道從機器件的相關(guān)信息,比如,SPI 模式、SPI 速率、數(shù)據(jù)位寬等。這就需要定義一個與從機器件對應(yīng)的實例(從機實例),并使用相關(guān)信息完成對從機實例的初始化。其函數(shù)原型為:

p_dev 是指向SPI 從機實例描述符的指針,am_spi_device_t 在am_spi.h 文件中定義:

該類型用于定義從機實例,用戶無需知道其定義的具體內(nèi)容,只需要使用該類型定義一個從機實例。即:

mode 指定使用的模式,SPI 協(xié)議定義了4 種模式,詳見表5.12。各種模式的主要區(qū)別在于空閑時鐘極性(CPOL)和時鐘相位選擇(CPHA)的不同。CPOL 和CPHA 均有兩種選擇,因此兩兩組合可以構(gòu)成4 種不同的模式,即模式0~3。當CPOL 為0 時,表示時鐘空閑時,時鐘線為低電平,反之,空閑時為高電平;當CPHA 為0 時,表示數(shù)據(jù)在第1 個時鐘邊沿采樣,反之,則表示數(shù)據(jù)在第2 個時鐘邊沿采樣。

表5.12 SPI 常用模式標志

cs_pin 和pfunc_cs 均與片選引腳相關(guān)。pfunc_cs 是指向自定義片選控制函數(shù)的指針,若pfunc_cs 的值為NULL,驅(qū)動將自動控制由cs_pin 指定的引腳實現(xiàn)片選控制;若pfunc_cs 的值不為NULL,指向了有效的自定義片選控制函數(shù),則cs_pin 不再被使用,片選控制將完全由應(yīng)用實現(xiàn)。當需要片選引腳有效時,驅(qū)動將自動調(diào)用pfunc_cs指向的函數(shù),并傳遞state 的值為1。當需要片選引腳無效時,也會調(diào)用pfunc_cs 指向的函數(shù),并傳遞state的值為0。一般情況下,片選引腳自動控制即可,即設(shè)置pfunc_cs 的值為NULL,cs_pin 為片選引腳,如PIO0_13。使用范例詳見程序清單5.60。

程序清單5.60 am_spi_mkdev()范例程序

2. 設(shè)置從機實例

設(shè)置SPI 從機實例時,會檢查MCU 的SPI 主機是否支持從機實例的相關(guān)參數(shù)和模式。如果不能支持,則設(shè)置失敗,說明該從機不能使用。其函數(shù)原型為:

其中的p_dev 是指向SPI 從機實例描述符的指針,如果返回AM_OK,說明設(shè)置成功;如果返回-AM_ENOTSUP,說明設(shè)置失敗,不支持的位寬、模式等,詳見程序清單5.61。

程序清單5.61 am_spi_setup()范例程序

3. 傳輸初始化

在AMetal 中,將收發(fā)一次數(shù)據(jù)的過程抽象為一個“傳輸”的概念,要完成一次數(shù)據(jù)傳輸,首先就需要初始化一個傳輸結(jié)構(gòu)體,指定該次數(shù)據(jù)傳輸?shù)南嚓P(guān)信息。其函數(shù)原型為:

其中,p_trans 為指向SPI 傳輸結(jié)構(gòu)體的指針,am_spi_transfer_t 類型是在am_spi.h 中定義的。即:

在實際使用時,只需要定義一個該類型的傳輸結(jié)構(gòu)體即可。比如:

表5.13 傳輸特殊控制標志

因為SPI 是全雙工通信協(xié)議,所以單次傳輸過程中同時包含了數(shù)據(jù)的發(fā)送和接收。函數(shù)的參數(shù)中,p_txbuf 指定了發(fā)送數(shù)據(jù)的緩沖區(qū),p_rxbuf 指定了接收數(shù)據(jù)的緩沖區(qū),nbytes 指定了傳輸?shù)淖止?jié)數(shù)。特別地,有時候可能只希望單向傳輸數(shù)據(jù),若只發(fā)送數(shù)據(jù),則可以設(shè)置p_rxbuf 為NULL;若只接收數(shù)據(jù),則可以設(shè)置p_txbuf 為NULL。

當傳輸正常進行時,片選會置為有效狀態(tài),cs_change 的值將影響片選何時被置為無效狀態(tài)。若cs_change 的值為0,表明不影響片選,此時,僅當該次傳輸是消息(多次傳輸組成一個消息,消息的概念后文會介紹)的最后一次傳輸時,片選才會被置為無效狀態(tài)。若cs_change 的值為1,表明影響片選,此時,若該次傳輸不是消息的最后一次傳輸,則在本次傳輸結(jié)束后會立即將片選設(shè)置為無效狀態(tài),若該次傳輸是消息的最后一次傳輸,則不會立即設(shè)置片選無效,而是保持有效直到下一個消息的第一次傳輸開始,詳見程序清單5.62。

程序清單5.62 am_spi_mktrans()范例程序

4. 消息初始化

一般來說,與實際的SPI 器件通信時,往往采用的是“命令”+“數(shù)據(jù)”的格式,這就需要兩次傳輸:一次傳輸命令,一次傳輸數(shù)據(jù)。為此,AMetal 提出了“消息”的概念,一個消息的處理即為一次有實際意義的SPI 通信,其間可能包含一次或多次傳輸。

一次消息處理中可能包含很多次的傳輸,耗時可能較長,為避免阻塞,消息的處理采用異步方式。這就要求指定一個完成回調(diào)函數(shù),當消息處理完畢時,自動調(diào)用回調(diào)函數(shù)以通知用戶消息處理完畢?;卣{(diào)函數(shù)的指定在初始化函數(shù)中完成,初始化函數(shù)的原型為:

其中的p_msg 為指向SPI 消息結(jié)構(gòu)體的指針,am_spi_message_t 類型是在am_spi.h 中定義的。即:

實際使用時,僅需使用該類型定義一個消息結(jié)構(gòu)體。即:

pfn_callback 指向的是消息處理完成回調(diào)函數(shù),當消息處理完畢時,將調(diào)用指針指向的函數(shù)。其類型am_pfnvoid_t 在am_types.h 中定義的。即:

由此可見,函數(shù)指針指向的是參數(shù)為void *類型的無返回值函數(shù)。驅(qū)動調(diào)用回調(diào)函數(shù)時,傳遞給該回調(diào)函數(shù)的void*類型的參數(shù)即為p_arg 的設(shè)定值,詳見程序清單5.63。

程序清單5.63 am_spi_msg_init()范例程序

5. 在消息中添加傳輸

一次消息處理中包含單次或多次的傳輸,在消息處理前,需要將消息和相關(guān)的傳輸關(guān)聯(lián)起來。該函數(shù)用于添加一個傳輸至消息中,其函數(shù)原型為:

其中,p_msg 指向am_spi_msg_init()初始化的消息,p_trans 指向am_spi_mktrans()初始化的傳輸。可以多次使用該函數(shù)以便向一個消息中添加多個傳輸,由于每次都將傳輸添加在消息的尾部,因此先添加的傳輸先處理,后添加的傳輸后處理,詳見程序清單5.64。

程序清單5.64 am_spi_trans_add_tail()范例程序

6. 啟動SPI 消息處理

該函數(shù)用于啟動消息的處理,其函數(shù)原型為:

其中,p_dev 為指向SPI 從機實例描述符的指針,用于指定本次消息處理中收發(fā)數(shù)據(jù)的從機對象;p_msg 為指向本次需要處理的SPI 消息結(jié)構(gòu)體的指針。如果返回AM_OK,說明啟動成功,當消息中所有的傳輸依次處理完畢時,將調(diào)用初始化消息時指定的處理完畢回調(diào)函數(shù);如果返回-AM_EINVAL,說明因參數(shù)錯誤啟動失敗,詳見程序清單5.65。

程序清單5.65 am_spi_msg_start ()范例程序

在這里,定義了一個初始值為0 的變量complete_flag,在初始化消息時,將它的地址作為回調(diào)函數(shù)的參數(shù),因此在回調(diào)函數(shù)中,p_arg 就是指向complete_flag 的指針,可以通過該指針將complete_flag 的值修改為1,如果檢測complete_flag 的值為1,表明消息處理完成。

7. 先寫后讀

SPI 傳輸和SPI 消息實現(xiàn)數(shù)據(jù)的發(fā)送和接收使得SPI 的使用非常靈活,可以支持豐富的SPI 從機器件。但正因為其靈活性,使得接口較多,使用起來較為繁瑣。對于絕大部分SPI從機器件,并不需要如此靈活,只需要實現(xiàn)簡單的數(shù)據(jù)發(fā)送和接收就可以了,基于此,AMetal提供了兩種十分常用的情形:寫入一段數(shù)據(jù)后讀取一段數(shù)據(jù)(先寫后讀);寫入一段數(shù)據(jù)后再寫入一段數(shù)據(jù)(連續(xù)兩次寫)。

先寫后讀即是主機先發(fā)送數(shù)據(jù)至從機(寫),再自從機接收數(shù)據(jù)(讀)。注意,該函數(shù)會等待數(shù)據(jù)傳輸完成后才會返回,因此該函數(shù)是阻塞式的,不應(yīng)在中斷環(huán)境中調(diào)用。其函數(shù)原型為:

如果返回AM_OK,說明數(shù)據(jù)寫和讀成功完成;如果返回-AM_EINVAL,說明由于參數(shù)錯誤導(dǎo)致數(shù)據(jù)寫和讀失??;如果返回-AM_EIO,說明在數(shù)據(jù)寫或讀的過程中發(fā)生錯誤,詳見程序清單5.66。

程序清單5.66 am_spi_write_then_read()范例程序

8. 連續(xù)兩次寫

連續(xù)兩次寫即是主機先發(fā)送緩沖區(qū)0 的數(shù)據(jù)至從機(寫),再發(fā)送緩沖區(qū)1 的數(shù)據(jù)至從機(寫)。如果只需要發(fā)送一次數(shù)據(jù),可以將第二次發(fā)送的數(shù)據(jù)緩沖區(qū)設(shè)置為NULL,并設(shè)置發(fā)送長度n_tx1 為0。值得注意的是,該函數(shù)同樣是阻塞式的,會等待兩次數(shù)據(jù)發(fā)送完成后才會返回,不應(yīng)在中斷環(huán)境中調(diào)用。其函數(shù)原型為:

如果返回AM_OK,說明消息處理成功;如果返回-AM_EINVAL,說明參數(shù)錯誤導(dǎo)致數(shù)據(jù)發(fā)送失?。蝗绻祷?AM_EIO,說明在發(fā)送數(shù)據(jù)的過程中發(fā)生錯誤,詳見程序清單5.67。

程序清單5.67 am_spi_write_then_write()范例程序

>>> 5.5.3 SPI 擴展接口

LPC824 與74HC595 的硬件連接詳見表5.14,當74HC595 作為SPI 從機時,數(shù)據(jù)僅需從MCU主機傳送至SPI 從機,無需讀取數(shù)據(jù)。對于MCU主機,數(shù)據(jù)是單向傳輸,只有數(shù)據(jù)輸出而沒有輸入,因此無需使用MISO。顯然,擴充74HC595僅占用MCU 的SCK、MOSI 與SSEL 引腳,即可實現(xiàn)8 位數(shù)據(jù)的輸出。

表5.14 74HC595 硬件連接

在使用SPI 驅(qū)動74HC595 時,必須先調(diào)用am_spi_mkdev()初始化與74HC595 對應(yīng)的SPI從機實例。為此需要獲取到數(shù)據(jù)寬度、SPI 模式、最高時鐘頻率和片選引腳等信息。即:

  • 數(shù)據(jù)寬度:74HC595 只有8 個并行輸出口,因此每次傳輸?shù)臄?shù)據(jù)寬度為8 位。

  • SPI 模式:8 位數(shù)據(jù)是在CP 時鐘信號上升沿作用下依次送入74HC595 的,因此在空閑時對時鐘沒有要求。如果選擇空閑時鐘極性為低電平(CPOL=0),則必須在第一個時鐘邊沿(上升沿)采樣數(shù)據(jù)(CPHA=0),即模式0。反之,如果選擇空閑時鐘極性為高電平(CPOL=1),則必須在第二個時鐘邊沿(上升沿)采樣數(shù)據(jù)(CPHA=1),即模式3。因此選擇模式0 和模式3 均可,后續(xù)的程序選擇模式3 作為范例。

  • 最高時鐘頻率:雖然74HC595 最高時鐘頻率高達100MHz,但MCU 最高主頻只有30MHz,因此最高時鐘頻率設(shè)置為一個相對合理的范圍,比如,3000000Hz(3MHz)。

  • 片選引腳:片選引腳為PIO0_13。

有了這些信息,即可配置與74HC595 對應(yīng)的SPI 從機實例,詳見程序清單5.68。

程序清單5.68 初始化與74HC595 對應(yīng)的從機實例范例程序

接下來,可以使用消息的方式或者am_spi_write_then_write()和am_spi_write_then_read()進行數(shù)據(jù)的發(fā)送與接收。由于使用消息的方式進行數(shù)據(jù)發(fā)送時參數(shù)較多,因此暫不使用消息的方式。因為MCU 不需要從74HC595 中讀取數(shù)據(jù),所以直接使用am_spi_write_then_write()進行數(shù)據(jù)發(fā)送,詳見程序清單5.69。

程序清單5.69 驅(qū)動74HC595 輸出的范例程序

為了方便后續(xù)使用,不妨封裝74HC595 的驅(qū)動程序,這樣就可以將74HC595 當作8 位I/O 口擴展接口來使用了。顯然,需要為74HC595 編寫初始化接口和數(shù)據(jù)輸出接口,其分別用于初始化與74HC595 對應(yīng)的SPI 從機實例和用于輸出指定的8 位數(shù),函數(shù)的聲明和實現(xiàn)詳見程序清單5.70 所示的hc595.h 和程序清單5.71 所示的hc595.c。

程序清單5.70 hc595.h 接口文件

程序清單5.71 hc595.c 實現(xiàn)文件

基于74HC595 的數(shù)據(jù)發(fā)送函數(shù),可以實現(xiàn)使用74HC595 驅(qū)動數(shù)碼管顯示,以節(jié)省引腳。同I/O 驅(qū)動數(shù)碼管一致,使用軟件定時器實現(xiàn)數(shù)碼管的自動掃描,詳見程序清單5.72。

程序清單5.72 新增使用軟件定時器相關(guān)函數(shù)

同樣地,將新的代碼添加到digitron1.c 中,其相應(yīng)的函數(shù)接口添加到程序清單4.47 所示的digitron1.h 中,詳見程序清單5.73。

程序清單5.73 digitron1.h 文件內(nèi)容

顯然,程序與之前的代碼基本相同,僅僅是回調(diào)函數(shù)調(diào)用的掃描函數(shù)變化了,測試程序詳見程序清單5.74。

程序清單5.74 測試軟件定時器自動掃描

由于回調(diào)函數(shù)運行在中斷環(huán)境,而am_spi_write_then_write()要等到數(shù)據(jù)發(fā)送完畢后才會返回,因此是阻塞式的,所以調(diào)用該函數(shù)實現(xiàn)的hc595_send_data()不能在中斷環(huán)境中使用。為了實現(xiàn)非阻塞式的(異步)數(shù)據(jù)發(fā)送函數(shù),可以使用SPI 消息的方式實現(xiàn)發(fā)送數(shù)據(jù)。為了區(qū)分與之前的hc595_send_data(),將其命名為hc595_send_data_async(),詳見程序清單5.75。

程序清單5.75 hc595_send_data_async()函數(shù)范例

在發(fā)送數(shù)據(jù)時,要先將數(shù)據(jù)data 保存g_tx_buf 中。因為使用SPI 消息的方式發(fā)送數(shù)據(jù)時,函數(shù)是異步的,會立即返回,函數(shù)返回后,因data 是局部變量,其地址空間就被釋放了。驅(qū)動獲取需要發(fā)送的數(shù)據(jù)時,是在緩沖區(qū)表明的地址中取數(shù)據(jù),因此必須保證緩沖區(qū)在整個數(shù)據(jù)傳輸過程中都是有效的。這里使用了一個全局變量來保存數(shù)據(jù),使得緩沖區(qū)一直有效。為什么使用am_spi_write_then_write()函數(shù)不需要這樣做呢?因為這個函數(shù)是同步的,會等到數(shù)據(jù)發(fā)送完畢后才返回,在整個數(shù)據(jù)傳輸過程中,data 的地址是有效的,不會被釋放。

這樣的異步傳輸函數(shù)可行嗎?如果使用者以較長的時間間隔來調(diào)用該函數(shù),每次調(diào)用前,上一個數(shù)據(jù)傳輸都已經(jīng)正確完成,則可以正常進行數(shù)據(jù)發(fā)送,不會出現(xiàn)問題。但是如果時間間隔很短,比如,連續(xù)2 次調(diào)用了該函數(shù)分別發(fā)送兩個數(shù)據(jù),將導(dǎo)致上一個transfer 被覆蓋,造成一種嚴重錯誤。可以類似SPI 消息一樣增加一個回調(diào)函數(shù),當數(shù)據(jù)發(fā)送完成后,調(diào)用回調(diào)函數(shù)通知用戶數(shù)據(jù)發(fā)送完畢。由于消息本身就有這一特性,因此只需要直接將用戶傳遞的回調(diào)函數(shù)作為SPI 消息初始化的回調(diào)函數(shù)參數(shù)即可,詳見程序清單5.76。

程序清單5.76 修改hc595_send_data_async()函數(shù)

為了便于后續(xù)使用,則將該函數(shù)的聲明存放到程序清單5.70 所示的hc595.h 中,詳見程序清單5.77。

程序清單5.77 hc595.h 文件內(nèi)容

實現(xiàn)該異步數(shù)據(jù)發(fā)送函數(shù)后,即可實現(xiàn)在中斷環(huán)境中發(fā)送數(shù)據(jù)。顯然,使用軟件定時器實現(xiàn)數(shù)碼管自動掃描需要修改digitron_hc595_disp_scan(),使其調(diào)用hc595_send_data_async()來實現(xiàn)掃描。不妨使用一個標志位,當標志位置1 時,說明傳輸完成,詳見程序清單5.78。

程序清單5.78 修改digitron_hc595_disp_scan()函數(shù)(1)

程序使用g_flag 變量來標志消影段碼是否傳輸結(jié)束,初看起來并沒有什么問題,這是一種通用的編程方法。但的確犯了一個很嚴重的錯誤,由于該函數(shù)直接使用了阻塞式while()循環(huán)等待語句,雖然hc595_send_data_async()是異步的,但加上等待語句后,又將掃描函數(shù)

變成阻塞式的了,因此該掃描函數(shù)還是無法在中斷環(huán)境中使用。

掃描一次數(shù)碼管,首先需要傳送消影段碼(0xFF),接著確定相應(yīng)的位選,然后傳送顯示段碼,即會在極短的時間內(nèi)調(diào)用2 次段碼傳送函數(shù)(消影段碼和顯示的段碼)。顯然,消影段碼沒有傳送完畢不能傳送顯示段碼,由于消影段碼傳送完畢后會調(diào)用回調(diào)函數(shù),為何不將后續(xù)代碼放到消影段碼傳送完成的回調(diào)函數(shù)中執(zhí)行呢?詳見程序清單5.79。

程序清單5.79 修改digitron_hc595_disp_scan()函數(shù)(2)

程序只是將之前的掃描函數(shù)分成了兩部分,將消影段碼后的內(nèi)容放到了回調(diào)函數(shù)中實現(xiàn),解決了等待消影段碼傳送完畢的問題。那么后續(xù)發(fā)送正常顯示的段碼,還需要等待其結(jié)束嗎?其實在正常顯示的段碼傳送完成后,并不需要再做其它操作,因此可以不用設(shè)置回調(diào)函數(shù)。如果不利用回調(diào)函數(shù)判斷其是否傳送完畢,那再次掃描時,是否會因上次消息處理還未完成

而產(chǎn)生錯誤呢?下次掃描是在5ms 之后,由于SPI 傳輸速率很快,3MHz 的速率傳輸8 位數(shù)據(jù)只需要幾微秒,因此5ms 的時間足以使其傳輸完畢,因此能夠確保正常顯示的段碼傳送在下一次傳輸數(shù)據(jù)前成功完成。修改后的使用軟件定時器實現(xiàn)自動掃描的函數(shù),由于接口并沒有改變,只是修改了實現(xiàn),因此可以直接使用程序清單5.74 的范例程序來進行測試。

5.6 I2C 總線

絕大部分情況下,MCU 都作為I2C 主機與I2C 從機器件通信,因此這里僅介紹AMetal中與I2C 主機相關(guān)的接口函數(shù)。

>>> 5.6.1 初始化

在使用I2C 通用接口傳輸數(shù)據(jù)前,必須先完成I2C 的初始化,便于獲取I2C 實例句柄。在LPC824 中,支持I2C 功能的外設(shè)有:I2C0、II2C1、I2C2 和I2C3,各I2C 外設(shè)都提供了對應(yīng)的實例初始化函數(shù),詳見表5.15。

表5.15 I2C 實例初始化函數(shù)(am_lpc82x_inst_init.h)

這些函數(shù)返回值均為am_i2c_handle_t 類型的I2C 實例句柄,該句柄將作為I2C 通用接口中handle 參數(shù)的實參。類型am_i2c_handle_t(am_i2c.h)定義如下:

因為函數(shù)返回的I2C 實例句柄僅作為參數(shù)傳遞給I2C 通用接口,不需要對該句柄作其它任何操作,因此完全不需要對該類型作任何了解。注意,如果函數(shù)返回的實例句柄的值為NULL,表明初始化失敗,該實例句柄不能被使用。

如果使用I2C0,則直接調(diào)用I2C0 實例初始化函,即可獲取對應(yīng)的實例句柄:

>>> 5.6.2 接口函數(shù)

在AMetal 中,MCU 作為I2C主機與I2C從機器件通信的相關(guān)接口函數(shù)詳見表5.16。

表5.16 I2C標準接口函數(shù)

1. 從機實例初始化

對于用戶來講,使用I2C的目的就是直接操作一個從機器件,比如,LM75、E2PROM等。MCU 作為I2C主機與從機器件通信,需要知道從機器件的相關(guān)信息,比如,I2C從機地址等。這就需要定義一個與從機器件對應(yīng)的實例,即從機實例,并使用相關(guān)信息完成對從機實例的初始化。從機實例初始化函數(shù)的原型為:

其中,p_dev 為指向am_i2c_device_t 類型(am_i2c.h)I2C 從機實例的指針,該類型定義如下:

使用時無需知道該類型定義的具體內(nèi)容,僅需使用該類型完成一個I2C 從機實例的定義:

其中,dev 為用戶自定義的從機實例,其地址作為p_dev 的實參傳遞。dev_flags 為從機實例的相關(guān)屬性標志,可分為3 大類:從機地址的位數(shù)、是否忽略無應(yīng)答和器件內(nèi)子地址(通常又稱之為“寄存器地址”)的字節(jié)數(shù)。具體可用屬性標志詳見表5.17,可使用“|”操作連接多個屬性標志。

表5.17 從機設(shè)備屬性

使用范例詳見程序清單5.80。

程序清單5.80 am_i2c_mkdev()范例程序

2. 寫操作

I2C 從機實例指定的子地址中寫入數(shù)據(jù)的函數(shù)原型為:

如果返回值為AM_OK,表明寫入數(shù)據(jù)成功;如果返回值為其它值,表明寫入數(shù)據(jù)失敗。范例程序詳見程序清單5.81。

程序清單5.81 am_i2c_write()使用范例

3. 讀操作

I2C從機實例指定的子地址中讀出數(shù)據(jù)的函數(shù)原型為:

如果返回值為AM_OK,表明讀取數(shù)據(jù)成功;如果返回值為其它值,表明讀取數(shù)據(jù)失敗,其相應(yīng)的范例程序詳見程序清單5.82。

程序清單5.82 am_i2c_read()使用范例

>>> 5.6.3 I2C擴展接口

在使用am_i2c_read()函數(shù)前,需要先使用am_i2c_mkdev()初始化與LM75B 對應(yīng)的I2C從機實例,便于LPC824 讀取溫度值。初始化從機實例時,還需要知道兩個重要的信息:器件從機地址和實例屬性。

LM75B 的從機地址為7 位,1001xxx,其中地址位0~2 分別與硬件連接的A0~A2 一一對應(yīng)。由于A0~A2 均與地連接,因此xxx 的值均為0,LM75B 的從機地址為0x48。

實例屬性可分為從機地址屬性、應(yīng)答屬性和器件內(nèi)子地址屬性,LM75B 的從機地址為7 位,其對應(yīng)的屬性標志為AM_I2C_ADDR_7BIT。如果從機實例不能應(yīng)答,則設(shè)置AM_I2C_IGNORE_NAK 標志。一般來說,標準的I2C從機實例可產(chǎn)生應(yīng)答信號,除非特殊說明,否則都不需要該標志。

LM75B 共計有4 個寄存器,詳見表5.18。由于寄存器的地址都為8 位,因此器件內(nèi)子地址為一個字節(jié),對應(yīng)的屬性標志為:AM_I2C_SUBADDR_1BYTE。由于只有一個字節(jié),所以沒有高字節(jié)與低字節(jié)之分, 也就不需要AM_I2C_SUBADDR_MSB_FIRST 或AM_I2C_SUBADDR_LSB_FIRST 標志。

表5.18 寄存器功能

使用am_i2c_mkdev()初始化一個LM75 從機實例的示例代碼詳見程序清單5.83。

程序清單5.83 初始化一個與LM75 對應(yīng)的I2C 從機實例

初始化從機實例后,即可使用am_i2c_read()讀取溫度值,由表5.18 可知,溫度值存于地址為0x00 的寄存器中,包含了兩個字節(jié)的溫度值,且是只讀的。因此,可以直接使用am_i2c_read()讀取子地址為0x00 的兩字節(jié)內(nèi)容,即溫度值,使用范例詳見程序清單5.84。

程序清單5.84 讀取溫度值

讀取的這兩字節(jié)數(shù)據(jù)表示的溫度值是多少呢?這兩個字節(jié)具體表示的溫度值的含義可從芯片的數(shù)據(jù)手冊獲取。溫度是以雙字節(jié)16 位二進制補碼方式表示的,分別保存在字節(jié)0和字節(jié)1 中,首先讀出的是字節(jié)0 的數(shù)據(jù)。字節(jié)0 中保存了溫度的整數(shù)部分,字節(jié)1 中保存溫度的小數(shù)部分,僅高3 位有效,因此溫度的分辨率為1/23 = 0.125℃。

如果將字節(jié)0 和字節(jié)1 合并為一個16 位有符號整數(shù)的話,則這個16 位有符號整數(shù)便是實際溫度的256(28)倍。如果系統(tǒng)支持浮點數(shù),則使用以下公式即可獲得當前溫度值:

當前溫度值(浮點數(shù)變量)= (字節(jié)0 的值×28 + 字節(jié)1 的值)/ 256.0

在沒有硬件浮點運算單元的MCU 中,這樣的公式在計算時效率是非常低的。在實際使用過程中,一般也并不需要得出浮點數(shù)的溫度值,僅僅在使用時稍加處理即可。比如,對于數(shù)碼管顯示溫度值,只需要分別顯示溫度值的整數(shù)部分(使用整數(shù)表示)和小數(shù)部分(使用整數(shù)表示)即可,并不需要計算出浮點數(shù)。LM75 的接口函數(shù)聲明詳見程序清單5.85。

程序清單5.85 LM75 接口(lm75.h)

其中,lm75_read()的作用是讀取LM75 溫度值,其返回值(16 位有符號數(shù))為實際溫度的256 倍,其相應(yīng)的實現(xiàn)(lm75.c)詳見程序清單5.86。

程序清單5.86 LM75 接口的實現(xiàn)(lm75.c)


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 總線
    +關(guān)注

    關(guān)注

    10

    文章

    2817

    瀏覽量

    87710
  • 周立功
    +關(guān)注

    關(guān)注

    38

    文章

    130

    瀏覽量

    37438

原文標題:周立功:深入淺出AMetal—— SPI 總線和 IIC 總線

文章出處:【微信號:Zlgmcu7890,微信公眾號:周立功單片機】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    詳解ametal_uart總線控制技術(shù)的核心要點

    第五章為深入淺出AMetal,本文內(nèi)容為5.8 UART 總線
    的頭像 發(fā)表于 12-19 08:03 ?4732次閱讀
    詳解<b class='flag-5'>ametal</b>_uart<b class='flag-5'>總線</b>控制技術(shù)的核心要點

    深入淺出AVR

    深入淺出AVR,一本書。
    發(fā)表于 07-15 12:02

    深入淺出玩轉(zhuǎn)FPGA

    深入淺出玩轉(zhuǎn)FPGA
    發(fā)表于 07-21 09:21

    深入淺出ARM7

    深入淺出ARM7
    發(fā)表于 08-18 10:12

    HDMI技術(shù)深入淺出

    HDMI技術(shù)深入淺出
    發(fā)表于 08-19 10:52

    深入淺出Android

    深入淺出Android
    發(fā)表于 08-20 10:14

    深入淺出Android

    深入淺出Android
    發(fā)表于 04-26 10:48

    深入淺出安防視頻監(jiān)控系統(tǒng)

    深入淺出安防視頻監(jiān)控系統(tǒng)深入淺出安防視頻監(jiān)控系統(tǒng)
    發(fā)表于 05-22 19:28

    深入淺出AVR

    深入淺出AVR
    發(fā)表于 08-23 10:10

    深入淺出高速串行信號測試(二)

      繼“深入淺出高速串行信號測試(一)”獲得大家鼓勵后,也有網(wǎng)友以及來自客戶拜訪中對于抖動的提問,使我萌發(fā)了寫下篇的念頭。在這篇博文中我們深入討論一下高速信號
    發(fā)表于 10-16 17:43 ?17次下載

    深入淺出防火墻

    深入淺出防火墻 隨著計算機網(wǎng)絡(luò)技術(shù)的突飛猛進,網(wǎng)絡(luò)安全的問題已經(jīng)日益突出地擺在各類用戶的面前。僅從
    發(fā)表于 08-01 10:25 ?583次閱讀

    深入淺出數(shù)據(jù)分析

    深入淺出數(shù)據(jù)分析,有需要的朋友下來看看。
    發(fā)表于 01-15 14:22 ?0次下載

    深入淺出多層面板布線技巧

    深入淺出多層面板布線技巧
    發(fā)表于 12-13 22:20 ?0次下載

    深入淺出數(shù)字信號處理

    深入淺出數(shù)字信號處理
    發(fā)表于 12-07 20:14 ?487次閱讀

    深入淺出學(xué)習(xí)250個通信原理資源下載

    深入淺出學(xué)習(xí)250個通信原理資源下載
    發(fā)表于 04-12 09:16 ?28次下載