Analog Devices ADF4113 - 4 GHz 頻率合成器驅動程式

  說到這個驅動程式,又是一個 long long story 了.... 因為故事很無聊,以下可忽略不看~

***************************    我是廢話分隔線 ***************************  
  我的研究生 D 君,做 Synthesizer,買了商用 IC 結果不會用。只會使用 vendor 提供的電腦版控制軟體。後來,我執行某個 2.4 GHz RFID reader 的計畫,內部需要一個本地振盪源(LO).... 然後,我們也是直接買商用的 module 回來用.... 但是讀取器是一個可隨身攜帶的東西,總不能每次都要「身上背著一台電腦」吧!所以咧,當然要在讀取器裡面塞一顆microcontroller。我們不只是要控制 LO,還要做基頻解調,還要作人機介面,通通都交給MCU來處理啦!!! 不過,這個計畫不是 D 君所執行的,而是 K 君跟M君。然後,我就叫他們兩個去找 D 君,畢竟 D 君是做 Synthesizer 的啊!!! 他是專家!!!!

  結果,搞了老半天,D 君完全就是亂做一通 (他可是花了半年以上的時間在這上面阿!! 靠!!!)。因為計畫有時程壓力,最後搞到我自己也受不了,就在某個禮拜天的下午,我就乖乖地窩在辦公室把ADF4113的驅動程式寫完。這就是,這支 Driver 誕生的故事。
**********************************************************************

目標硬體:ADF4113 Frequecy Synthesizer

我們採用的 module 是 Mini-Circuits 的DSN-3019A,裡面用的頻率合成器晶片是 Analog Devices ADF4113。ADF4113 沒有內建振盪器,所以你如果懶得做振盪器,那麼像 DSN-3019A 這種 module 就會是你需要的。不過呢!其實很多合成器 IC 內部都已經有振盪器啦,倒不一定真的要買 module。只不過,你如果要特殊的 spec,例如 high output power、wideband,通常還是像這種 module 會比較有得挑.....

  這邊要稍微碎碎念一下。我發現很多人 (學生) 都很不愛看 Datasheet,不然就是根本不會看 Datasheet。阿你不看 Datasheet,你怎麼會知道東西怎麼使用啦!有甚麼限制阿!不是東西拿起來,接了就會動的耶~ 怎麼大家都有這種幻覺呢???!! 我實在搞不懂。我們高頻電子實驗,要求學生做的第一件事情,就是學會看電晶體的Datasheet。不管是電晶體,還是MCU,還是什麼 IC,反正不管啦!拜託一定要看,特別是寫 Driver,你不看 Datasheet 你是要怎麼寫驅動程式啦~ 吼~ 就好像你要用 Library,然後又不看 API Guide 一樣。用了不會動,就開始呼天搶地、該該叫.... 很多學生就有這種毛病,都該打屁股!

  好啦!進入主題,這個驅動程式有四支檔案,還有一份投影片可以看。裡面用到的 3-wire driver 是採用 bit banging 的作法 (直接控制GPIO)。雖然說,要控制一顆 IC,把介面的需求搞清楚後,要在 main() 裡面直接硬幹也是可以。不過,我們的計劃還需要作人機介面、基頻解調器之類的東西,所以如果要靠一個 main() 硬幹恐怕是不太可行。所以呢!很直覺的想法就是把各種功能給模組化,如果是對底層的硬體,那個模組所做的事情就是在包裝硬體的操作,這個模組也就是驅動程式的意思。把各功能模組化,這樣就讓 main() 專注去處理「應用層」的邏輯就好。

檔案說明

  • hal_types.h: 自訂的基礎型別跟使用#define常數
  • hal_adf4113.h: 此header file是指定I/O與ADF4113相關的控制暫存器定義、指令等
  • hal_adf4113.c: ADF4113的驅動程式,它開放了4支API給外部調用
    • HalSynInit(): 合成器初始化
    • HalSynStart(): 啟動合成器
    • halSynSetFunc(): 設定合成器功能 (power down/電流泵增益/合成頻率等)
    • delayms(): 延時函式
  • main.c: 主程式
  • 說明投影片與Driver測試
  • 原始碼

程式簡要說明

// 略
typedef signed   char   int8;
typedef unsigned char   uint8;
// ...
#ifndef TRUE
#define TRUE  1
#endif

#ifndef FALSE
#define FALSE 0
#endif
// ...
// 略
// 設定I/O
#define TriWire_Port  P2OUT
#define TriWire_IO    BV(0)
#define TriWire_SCLK  BV(1)
#define TriWire_LE    BV(2)
#define TriWireDELAY  1
//...

// 定義指令 Function Set Name (funSet)
// halSynSetFunc(uint8 funcSet, uint8 mode);
#define ADF4113_SET_RESYNC        0
#define ADF4113_SET_LD_PREC       1
#define ADF4113_SET_TEST          2
// ...

// 定義 Error Code
#define HAL_SYN_OK                0x00
#define HAL_SYN_NOT_OK            0x01
#define HAL_SYN_INVALID_FUNC      0x02
// ...

// 跟ADF4113控制暫存器相關的資料結構
typedef struct
{ 
  uint8  control : 2;
  uint16 r_val : 14;
  uint8  abp : 2;
  uint8  testmode : 2;
  uint8  ldprec : 1;
  uint8  sync : 1;
  uint8  dly : 1;
  uint8  resrv : 1;
} halRCounter_t;
// ...
/************************
 * FUNCTIONS - API
 ************************/
extern uint8 HalSynInit(void);
extern uint8 HalSynStart(uint16 rf_Freq);
extern uint8 halSynSetFunc(uint8 funcSet, uint8 mode);
extern void delayms(uint8 time);

// 略
// 4支開放的API在hal_adf4113.h header中宣告
// .c檔中宣告的function是這支driver的local function
// 實作細節請見原始碼
/***************************
 * FUNCTIONS - Local
 */
uint8 HalSynConfig(void);
uint8 halSynSetFreq(uint16 rf_Freq);
uint8 halSynSetCounter(uint16 R_val, uint16 B_val, uint8 A_val, uint8 P_mode);
uint8 halSynSetRLatch(halRCounter_t* RCounter, uint8* RLatch);
uint8 halSynSetNLatch(halNCounter_t* NCounter, uint8* NLatch);
uint8 halSynSetFuncLatch(halFuncLatch_t* Func, uint8* FuncLatch);
uint8 halSynWriteLatch(uint8* Latch);
void TriWire_WriteByte(uint8 output_data);
void delay_time(uint8 time);

// 略
// 初始化頻率合成器,然後按某個按鈕就啟動合成器,合成頻率為2.4 GHz
void main()
{
    //...
    HalSynInit();
  
    while(1)
    {
        if ((P1IN & BTN1) == 0) {
            delayms(50);
            if ((P1IN & BTN1 ) == 0) {
                while((P1IN & BTN1) == 0);
                HalSynStart(2400);
            }       
        }
    }
}

後記

以我自己的經驗,我覺得學 RF 的人,常常會發現要兜出一個系統都比較麻煩。

第一是會跑去讀電波的人,大概都是異常痛恨數位跟軟體的人.... 哈哈哈.... 所以,沒轍。

第二是,當你要兜系統的時候,你拿到的IC都需要設定、需要被控制,但往往這些IC根本不可能提供給你甚麼 library 使用啊!!所以,免不了就是要讀Datasheet,準備自幹,但往往Datatsheet一攤開,就先軟一半了。不過!!!! 大家都很聰明,耍一點小手段,其實靠外部的一些陽春電路啊、AWG啊,拼拼湊湊的也是有辦法讓東西動起來啦,只不過每次要做實驗,就比較土法煉鋼,完全都是在做純手工的事情,很不科學啊....  (但是我們要得到的卻是科學數據.... 用很不科學的方法,得到科學數據.... 真的很有趣!)

  啊!! 我想,這也是做 RF 會比較悶的原因吧.... 通常做的都不是甚麼有趣的東西,感受不到啊!!! 頂多就是看著網儀啊、頻譜啊、VSA的螢幕傻笑.... 然後不知道自己在幹嘛....哈哈哈哈..... 上面的驅動程式,我覺得是一個很好的範例,其實RF上面會用到的IC,就差不多像那樣控制控制一下而已,所以應該是套用的模式都很像.... 有志者,加減學一點,範例拿去改一改,我想應該會蠻有幫助的,兜系統也會兜得比較愉快一點。

這支驅動程式我當初是寫給8051去跑的,後來學生移植到 MSP430 跟 Silicon Labs的某顆MCU去跑(忘記型號了),都很OK,因為只要把 mcu 的 header 換掉,把GPIO改成你要的port,其它的都不需要動。

本文沒有版權,歡迎轉載。
如您喜歡本部落格,歡迎至 E. E.狂想曲 Facebook 粉絲專頁持續追蹤最新文章!

2 則留言:

  1. 幫補充datasheet那段~ 前陣子被指導教授念作IC之前要去看製成model檔~ 這應該是一樣的道理唄~ 就像玩遊戲之前也要知道規則阿~~ 不過抱怨一下 以前在北科只有虛擬製成 電晶體都是給個偏壓去取參數 再靠經驗微調阿QQ 又不像台大有台GG贊助先進製程跟面積

    回覆刪除
    回覆
    1. 對阿, 規則要先知道.... 想要亂搞, 也要先知道「規則就是沒有規則」吧!哈哈哈哈~~~

      沒資源有沒資源的作法嘛~~~~ 北科的人都是這樣「練」出來的,科科....

      刪除

技術提供:Blogger.