在開發(fā)的進程中我們常常會碰到1些新的芯片,首先要做的就是拿到數(shù)據(jù)手冊,弄懂它的功能,然后就是寫代碼去驅動這個芯片。到了寫驅動代碼這1環(huán)節(jié),依照通常的習慣就是去網(wǎng)上先找1下有無類似的可以參考的代碼,然后從別的平臺移植到自己的平臺,再調試1段時間,基本上就通了(我是在讀的學生,公司的開發(fā)流程還不懂)。
如果常常這樣做,心里總是有種不舒服的感覺,我仔細想了1下,大概有這么1些東西。首先就是,不管這個芯片最后有無調通,運行的怎樣樣,自己心里明白這是他人的代碼。其次就是,如果移植的代碼跑的很順利,那末很自但是然的就不再理睬其中的細節(jié),數(shù)據(jù)手冊也馬上就拋到腦后,這類做法有個很大的弊端就是如果有1天代碼出問題了,這時候你對這個芯片的熟習程序是遠遠不夠的,以致于不能快速的找出問題并解決,還有就是從他人的代碼中找到蛛絲馬跡并順藤摸瓜解決問題,我感覺是相當頭疼的1件事。最后1點也是最重要的1點,俗語說不想當將軍的兵士不是好兵士,既然踏進這個行業(yè),就勵志做1名牛逼的工程師,所以不能滿足于抄抄他人的代碼,做1些移植工作,由于你所移植的代碼,究其原點,終究是有人通過數(shù)據(jù)手冊1行1行寫出來的。還有就是,如果你開發(fā)的東西是相當高精尖的領域,總有時候是你在網(wǎng)上找不到可參考的代碼。那末問題來了,這個踏足高精尖領域的工程師,不就是我們的理想嗎。最后再說1下,移植代碼其實不可恥,乃至說1些重復代碼是在浪費時間和精力,但是我們必須具有的1項素質就是通過瀏覽數(shù)據(jù)手冊,能非常熟練的寫出它的驅動代碼。
今天就拿1個非常簡單的AD芯片,不參考任何他人的代碼,手頭能用的資料就是數(shù)據(jù)手冊和原理圖,寫出它的驅動代碼。我們的平臺是stm32f407,AD芯片是ADS1118,裸機程序。假定硬件工程師已做好了完全的硬件電路。
作為軟件,我們最首先關心的是芯片各個引腳的描寫,1下是數(shù)據(jù)手冊中關于引腳的描寫
這樣1看我們就會發(fā)現(xiàn),芯片對外的接口是非常經(jīng)常使用的SPI接口,SPI的SCLK接SCLK,MOSI接DIN,MISO接DOUT。CS接普通IO口,VDD供電,有4路輸入信號,AIN0-AIN4,通過描寫可以發(fā)現(xiàn),這4路可以接成單極性的4路輸入,或雙極性的兩路輸入。看完這些我們基本明白了這些引腳的功能,大體明白了芯片如何與MCU連接(SPI和I2C接口是兩種非常經(jīng)常使用的接口,所以兩種通訊協(xié)議爛熟于心)。
接下來要關心的東西就是寄存器,MCU控制1些外圍芯片,最最多見的方式就是通過通訊接口(本次是SPI接口)去讀寫芯片的寄存器,來到達控制的目的。以下是ADS1118的寄存器
ADS1118的寄存器可以說是非常簡單,通過瀏覽數(shù)據(jù)手冊會發(fā)現(xiàn)有兩個16位寄存器,1個是轉換結果的寄存器,它的屬性是只讀,也就是說這個16位寄存器保存著AD轉換以后的結果。另外一個就是配置寄存器,它的屬性是讀寫,我們的控制全都是通過配置這個寄存器中的值來實現(xiàn),所以接下來要非常仔細的瀏覽1下這個寄存器中各個位所代表的含義。以下是寄存器各個位的說明
我們可以看到bit15分兩種情況,如果是讀,那末就唆使了芯片當前的工作狀態(tài),如果是在掉電模式也就是單次轉換模式下寫1,就開始1次數(shù)據(jù)轉換,寫0無影響。
bit14⑴2代表了當前輸入信號的接法,也能夠說是選擇通道。以000為例,選擇通過0和1,雙極性輸入。
bit11⑼代表了轉換芯片的量程,并且下面有1段注意事項的說明。
bit8代表了芯片的工作模式,連續(xù)轉換和掉電兩種模式。
bit7⑸代表了轉換速率。
bit4代表了溫度傳感器模式和ADC模式,也就是說這個芯片還可以作為溫度傳感器使用。
bit3代表了上拉模式的是不是使能。
bit2⑴代表了數(shù)據(jù)是不是寫入寄存器,這個和SPI的特性有關,而且這個芯片還有1定的特殊性,下面再解釋為何設置這個位。
bit0數(shù)據(jù)轉換就緒標志,也就是標志了當前的是正在轉換還是轉換結束。
寄存器的說明就看完了,也就死明白了要控制這個芯片,需要往寄存器中寫入甚么樣的值,來到達自己的目的。雖然我們明白了數(shù)據(jù)通過SPI接口寫進芯片,也明白了該寫的值,但是我們不明白數(shù)據(jù)要組織成怎樣的格式,寫進芯片。所以我們最后還需要知道讀寫數(shù)據(jù)的幀格式,也就是時序,也能夠說是簡單的通訊協(xié)議。就是說MCU要依照芯片的要求,把要寫的數(shù)據(jù)組織成1定的格式,芯片才能明白你寫進來的數(shù)據(jù)所代表的含義。
以下是ADS1118數(shù)據(jù)手冊中的時序圖
我們可以看到連續(xù)轉換模式和單次轉換模式有兩種不同的時序,二者的不同只表現(xiàn)在DOUT引腳。在連續(xù)模式下,DOUT引腳變低,唆使本次轉換完成,數(shù)據(jù)必須在16/FCLK時間內讀出,在單次模式下DOUT引腳不會變低。這樣我們就會發(fā)現(xiàn),要操作這個芯片,首先將CS拉低,然后從MOSI數(shù)據(jù)線上將數(shù)據(jù)以CONFIGMSB、CONFIGLSB、CONFIGMSB、CONFIGLSB的格式寫進芯片,同時在MISO數(shù)據(jù)線上會讀到DATAMSB、DATALSB、CONFIGMSB、CONFIGLSB。這樣我們就明白了數(shù)據(jù)以何種形似組織。接下來就能夠寫驅動代碼,寫代碼之前,最好有個流程圖,如果是比較簡單的流程,可以再頭腦里大體構思1下。本次我們的流程很簡單,就是配置寄存器->讀取轉換結果。
然后我們按步驟開始寫代碼。
1、新建 .c和 .h文件,把需要對外提供的接口函數(shù)寫進 .h文件,本次我們新建ads1118.c和ads1118.h兩個文件,ads1118.h文件中對外提供配置函數(shù)ADS_Configure()和操作函數(shù)ADS_SetReg()和ADS_ReadData()。
2、實現(xiàn)配置函數(shù),在配置函數(shù)中打開外設的時鐘,本次用到的外設就是SPI和IO口,所以就需要打開相應外設的時鐘。配置外設參數(shù),本次用到了SPI和IO口,就需要配置SPI的工作參數(shù)和IO的模式參數(shù)等等。
3、實現(xiàn)操作函數(shù),在實現(xiàn)操作函數(shù)之前,先需要把兩個操作函數(shù)中公用的部份抽留出來,寫成1個獨立的函數(shù),供兩個函數(shù)調用。本次兩個操作函數(shù),不論是配置芯片寄存器還是讀取轉換值,都需要1個發(fā)送數(shù)據(jù)的公共函數(shù),同時這個函數(shù)還要能回SPI MISO線上的數(shù)據(jù),這個函數(shù)以下
最后再實現(xiàn)ADS_ReadData()函數(shù),這個函數(shù)實現(xiàn)思想就是依照讀時序圖,發(fā)送兩次CONFIG MSB、CONFIG LSB,同時在MISO數(shù)據(jù)線上讀回數(shù)據(jù),函數(shù)的實現(xiàn)以下
這樣驅動代碼就算是寫完了,我們只需要依照寄存器各個位的說明,結合你自己的接線方法、控制要求寫出各個位的值,然后組成1個16bit的數(shù)據(jù),假定依照控制要求,終究寫成的數(shù)據(jù)是0XC2EB,那末我們在需要處調用ADS_SetReg(0XC2EB),就會將配置的這些值寫進芯片的寄存器。假定數(shù)據(jù)轉換結束,我們再調用ADS_ReadData()函數(shù),轉換的結果依照MSB、LSB的順序保存在buf中。
為了更有說服力,看1下實驗現(xiàn)象,首先將0XC2EB的值寫進芯片的寄存器,為了直觀起見,看1下示波器上的信號。黃色為時鐘線,藍色為數(shù)據(jù)線
降落沿讀數(shù)據(jù),第1張圖可以非常清楚地看到0XC2,第2張圖可以看到0XEB。
電壓表上讀到的電壓值,
程度中讀到的值,(0X2F8A/65536)*4.096*2=1.52125V。由于電表丈量和程序中不是同步的,有1些偏差。
最后總結1下:ADS1118雖然比較簡單,但是還是大體說明了1般的流程,別的芯片復雜的只是寄存器變多,功能變復雜,時序變復雜,只要細細的讀數(shù)據(jù)手冊,寄存器和時序圖,穩(wěn)扎穩(wěn)打,創(chuàng)造出屬于自己的驅動代碼還是很容易的,