2013年3月11日 星期一

使用 Visual Studio 開發 C51 專案程式

好久沒有發文了,今天來談談關於 8051 MCU 的開發環境,8051 被認為是應用相當廣泛歷久不衰的古老 MCU,在眾多工程人員的努力下,8051仍然持續被重新設計與進化,現代新型的 8051 一般來說都經過架構與製程上的改造,架構上的改造像重新使用RISC架構設計的8051,或是外掛其他周邊例如加入常用的 I2C 與 SPI 或是像有名的 Cypress CY7C68013A 這顆超級 8051 帶有特殊的周邊主要是內建 USB 2.0 控制器 與 GPIF (General Programmable Interface),GPIF 不是 GPIO 不要弄混,這是一種很奇特的介面,它的功能很像 CPLD,可以產生開發者想要的特殊通訊波形,使得 USB 2.0 控制器可以直接與 GPIF 連接的外部裝置直接通訊,8051 核心本身不用介入控制,達到高速傳輸的目的,有點像可程式化的 DMA。製程上的改造使得 8051越做越小顆,像 C8051F320 小小一顆 7x7mm^2 還內建有USB全速控制器,NI 公司的 USB 轉 I2C 與 SPI 產品就是用這顆做的喔。雖然 8051 有許多變種,但是 8051 的核心在怎麼變,軟體開發層面都一樣,因為所有 8051 組合語言指令集都長得一樣,所以用 C 語言開發 8051 程式當然就只需要一種編譯器,最有名的就屬  Keil C Compiler,另外還有開放原始碼專案的 SDCC。雖然 Keil C51 Tool Chain很好用,可是 Keil 的程式環境就令吾人不深感不方便,尤其對我們這些原本搞 Windows 或 Linux 下寫 GUI 應用程式跳過去也搞搞微處理器的人來說,Keil 的程式編輯器實在太陽春,所以就浮現一個簡單的想法,我只要 Keil C51 Tool Chain,程式編輯與編譯環境用 Visual Studio !!

在使用 Visual Studio 來編譯 C51 程式前,要先準備的工作有

1. 你要知道怎麼在 指令列 下面手動用 Keil C 編譯器 編譯 原始檔 (*.c) 為 目的檔 (*.obj)
2. 你要知道怎麼把 C51 的目的檔 用 Keil BL51 連結器 連結為 目的檔模組格式 (*.omf)
3. 你要知道怎麼把 目的檔模組格式 (*.omf) 用 Keil OH51 轉換器 轉成 Hex 檔 (*.hex)
4. 這步驟就跟軟體無關,找燒錄器把 Hex 檔燒入晶片看程式會不會跑~~

首先假設有兩個檔案 main.c 與 subp.c,要怎麼手動編譯出 Hex 檔呢 ?
首先要確認你的 Keil C51 Tool Chain 在系統的環境變數中有沒有設定好
例如安裝路徑是 C:\Keil\C51\BIN,則請在 環境變數 Path 中加入此路徑
在到指令列下測試 c51.exe bl51.exe oh51.exe 是否能正確抓到。

現在來告訴讀者怎麼用手動編譯搞出 Hex 檔,其實步驟非常簡單

先手動編譯出 目的檔 指令如下
  c51.exe main.c DB OE INCDIR(C:\Keil\C51\Inc)
  c51.exe subp.c DB OE INCDIR(C:\Keil\C51\Inc)
程式碼假如沒錯誤的話,就會分別得到 main.obj 與 subp.obj

在來使用 C51 連結器產生 Omf 檔 指令如下
  bl51.exe main.obj,subp.obj TO SL811AU.omf RS(256) PL(68) PW(78)
經過這條指令後,C51 連結器會得到連結後的 Omf 檔
其實 Omf 檔已經是 8051 的可執行檔,有些燒錄器有支援的話
直接把 Omf 檔燒錄進 8051 後就可以執行程式。

這個步驟可以將 Omf 檔轉換成 Hex 檔,使用 OH51 指令如下
  oh51.exe SL811AU.omf
執行完這條指令後,就會產生 SL811AU.hex。

這邊額外補充說明,假如檔案是 組合語言 (*.a51) ,指令如下
  a51.exe filename.a51 XR GEN DB EP NOMOD51 INCDIR(C:\Keil\C51\Inc)
C51 Assembler 將會輸出 filename.obj。

跑這個指令流程實在很不方便,這點古老時代開發 Unix 的祖先們也知道
指令很強大沒有錯,但是很難搞,還要一行一行敲,容易錯,所以今天的主題
出現啦,我們來寫一個 Makefile,把剛剛的流程丟給 make 去產生一連串的命令鏈
Makefile 要玩可以寫到很複雜,可是上面這些簡單的步驟不需要很複雜的 Makefile
所以我只介紹最簡單的語法與規則,它們雖然簡單但是也是最重要的基本特性
其實 Makefile 嚴格來說也算是一種程式語言,只是它不是由上往下跑,其語言特性
是會不斷的輪詢檢查各種規則是否成立,例如 一個 EXE 檔可能由一堆 OBJ 檔連結
而成,可是 make 發現沒有 OBJ 檔,就繼續輪詢檢查有沒有可能產生 OBJ 檔的規則
總之詳細書籍請參考 歐萊禮出版的 make 專案開發工具

1.  定義巨集字串: 例如 CPP=c51.exe,以後就可以用 $(CPP) 直接取用

2.  定義相依關係與要執行的動作: Action 前面一定是 TAB 不是空白
     

  Target : Prerequisite
      Action


     意思是說 要有這個 Target 的前提是要有 Prerequisite,然後做對應的動作

有以上這兩種觀念就即可,下面直接就給已經寫好的 Makefile 程式碼 (C51Make.mak):
# Microsoft Developer Studio Generated NMAKE File For C51
AS=a51.exe
CPP=c51.exe
LINK=bl51.exe
HEXCONV=oh51.exe

C51INC=C:\Keil\C51\INC
BINFILE=SL811AU

#MODULE0=startup
MODULE1=main
MODULE2=subp

ALL : $(BINFILE).hex

CLEAN :
    -@erase "$(MODULE1).OBJ"
    -@erase "$(MODULE1).LST"
    -@erase "$(MODULE2).OBJ"
    -@erase "$(MODULE2).LST"
    -@erase "$(BINFILE).m51"
    -@erase "$(BINFILE).omf"
    -@erase "$(BINFILE).hex"

AS_FLAGS=GEN DB EP NOMOD51 INCDIR($(C51INC))
CPP_FLAGS=DB OE INCDIR($(C51INC))

OBJS=$(MODULE1).obj $(MODULE2).obj
LINK_OBJS=$(MODULE1).obj,$(MODULE2).obj
LINK_FLAGS=TO $(BINFILE).omf RS(256) PL(68) PW(78)

$(BINFILE).hex : $(BINFILE).omf
    $(HEXCONV) $(BINFILE).omf

$(BINFILE).omf : $(OBJS)
    $(LINK) $(LINK_OBJS) $(LINK_FLAGS)

#SOURCE=$(MODULE0)
#$(SOURCE).obj : $(SOURCE).a51
#    $(AS) $(SOURCE).a51 $(AS_FLAGS)

SOURCE=$(MODULE1)
$(SOURCE).obj : $(SOURCE).c
    $(CPP) $(SOURCE).c $(CPP_FLAGS)

SOURCE=$(MODULE2)
$(SOURCE).obj : $(SOURCE).c
    $(CPP) $(SOURCE).c $(CPP_FLAGS)

其中 A51 的部分被我註解掉了,因為吾專案裡面沒有用到組合語言,這個專案原本是設計
一個 USB 裝置且"具 HID 功能的消費者控制裝置",USB 插上電腦後可以用 8051 控制電腦
內的音量,主要有 調高音量 降低音量 靜音 三種功能。總之 有用到組語的讀者們稍微改一下
我寫的 Makefile 就可以應用在自己的專案了。

補充: Makefile 裡面讀者看到 -@ 這是甚麼意思呢 ? 讀者假如有常常開發指令列工具的
經驗,尤其是有 *nix 系統下的編程經驗,就會知道這種系統跟 Windows 不同,它們講
求每件工具做好做精自己的事情,不是 Windows 程式通包的觀念,因此不同工具之間
Makefile 要能知道它們的回傳狀態,所以 main 裡面的 return 0,就是在這個時候使用,
指令列設計者常常會根據不同的情況,return 不同的數值,return 0 在慣例裡面就是工具
執行狀態正常,假如不 return 0 的話 make 執行 Makefile 中途就會停住,以為指令執行
有錯就不會繼續執行,所以 - 就是讓 make 忽略工具的回傳值,至於 @ 就是說不要把命令
的訊息顯示出來。

既然 Makefile 寫好了,要用 Visual Studio 架構開發 8051 的專案就太簡單了
其實就是開一個 Visual Studio 內的 Makefile 專案,設定好剛剛寫的 Makefile
就可以完全的在 Visual Studio 內寫 8051 程式,享受原本 Visual Studio 編輯器
強大的詞法分析功能還有類別檢視視窗自動分析整個程式結構的好處。

因為不是所有讀者可能都開過 Visual Studio 內的 Makefile 專案
下面就給個設定步驟參考,首先新增 Makefile 專案 輸入你喜歡的專案名稱


專案開好後就像平常使用 Visual Studio 一樣請在原始程式檔加入你寫好的
C51 程式,在我的例子中是 main.c 與 subp.c


接著在設定專案的屬性,把剛剛設計好的 Makefile 讓 Visual Studio 去呼叫
微軟的 make 版本稱為 nmake

讀者們可以看到,我把建置命令與重建命令都用

nmake -fC51Make.mak

因為我寫的 Makefile 本身會把已經建立過的 obj 先刪除才重新建構程式
所以這建置與重建對我的Makefile來說沒有差異。

在清除命令列可以看到我輸入的指令是

nmake -fC51Make.mak clean

這邊剛剛好就順便學習另一個 Makefile 的功能,就是直接命令 nmake 跳至特定的
Target,這邊指的就是直接跳至 clean target 執行,有沒有注意到,clean target 沒有
Prerequisite,就是說 clean target 不相依任何檔案,這樣其它的規則就不會被 make 工具
輪詢規則檢查,只有做 Clean 的動作。

 最後給出實際執行 Makefile 命令串執行結果 (產生 SL811AU.hex)



Makefile 是相當複雜的一種程式語言,可以建構非常複雜的程式專案管理系統
在配合呼叫系統的殼層指令像在 Windows 下的 WSH 與 Linux 下的 Shellscript
那大概就幾乎是沒有做不到的事情,本篇主旨透過在 Visual Studio 下開發 C51 程式
同時拿到 VS 環境強大的編輯器又可以編譯 C51 程式來引起讀者對 Makefile 做一個
簡單的認識

(完)

後記 :
回覆的 Paper 版面還挺不好修改,改這無聊的玩意都忘了要發文了
後面幾篇開始,應該就是談談 怎麼從 SL811 學習 USB,這個會拆成
好幾個 Part,因為 Usb Protocol 複雜東西又多,要慢慢一步一步學習才好。

沒有留言:

張貼留言