stamp work v2 - parallax, inc. · 1 stamp work v2.1 中文版 中文版為美國 parallax, inc....

233
1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經 飆機器人_普特企業有限公司授權 不得翻印及販售或提供任何商 業行為與規範。

Upload: others

Post on 30-Dec-2019

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

1

Stamp Work V2.1 中文版

中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經 飆機器人_普特企業有限公司授權 不得翻印及販售或提供任何商業行為與規範。

Page 2: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

1

目錄

事前準備-StampWork 套件…………………………… 1

StampWork 套件……………………………………… 1 建立硬體及軟體……………………………………… 2 在 STAMWORKS 實驗中使用積體電路注意事項… 9

程式要點……………………………………………… 11

工作程式目錄…………………………………………………. 11

分支- 重新定向程式流程…………………………………. 12

迴圈-執行程式碼一遍又一遍…………………………….. 14

子程式-能節約可重複使用的程式碼空間……………. 16

風格的元素………………………………………… 19

實驗開始!...................................................... 25

學習程式概念………………………………………………… 25

建立專案……………………………………………………….. 25

在專案間該做什麼………………….……………………….. 25

實驗#1:點亮一顆 LED 燈………….……………………. 26

實驗#2:亮一顆 LED(進階)…………….……………….. 29

實驗#3:用 LED 燈顯示一個計數器…………………. 33

實驗#4:科幻小說的 LED 燈顯示……………….…….. 36

實驗#5:LED 圖形(點或線)……………………….…….. 40

實驗#6 簡單的遊戲………………………………………... 46

實驗#7:照明控制器……………………………………… 51

建立你自己的電路…………………..…………… 57

使用七段顯示器…………………………………… 59

實驗#8:單一數位計數器………………………………….. 60

實驗#9:數位骰子……………………………………………. 63

Page 3: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

2

實驗#10:數位時鐘………………………………………….. 67

使用 Character LCD 模組……………………….. 73

實驗#11:基本的 LCD 說明………… ………………….. 75

實驗#12:創造特定 LCD 單字….…………………………. 82

實驗#13:讀取 LCD 記憶體……………………………….. 88

向前移動…………………………………..………… 93

實驗#14:掃描並顯示多重輸入………………………….. 94

實驗#15:計數事件………………………………………….. 98

實驗#16:頻率測量………………………………………….. 101

實驗#17:進階的頻率測量………………………………… 106

實驗#18 光線控制特雷門(A Light Controlled Theremin) 109

實驗#19:音效(SFX)…………………………………….. 112

實驗#20:紅外線物件感測 ……………………… 119

實驗#21:用 PULSIN 做類比輸入……………………. 123

實驗#22:用 PWM 於類比輸出……………………….. 126

實驗#23:利用位移暫存器擴大數位輸出 ……. 130

實驗#24:利用位移暫存器擴展數位輸出 …… 137

實驗#25:用數個位移暫存器混合 IO 介面………… 143

實驗#26:模型伺服馬達(HOBBY SERVO)控制… 146

實驗#27:步進馬達(Stepper Motor)控制……….. 150

實驗#28:電壓量測………………………………………… 156

實驗#29:溫度測量………………………………………… 161

實驗#30:高精度溫度測量………………………………. 168

實驗#31:進階七段顯示器多路傳輸…………………. 173

實驗#32:I2C 通訊…………………………………………. 179

實驗#33:使用即時時鐘………………………………….. 188

實驗#34:用電腦做串聯通訊…………………………… 197

實驗#35:(額外)BS2PX ADC………………………... 206

更厲害的 PBASIC………………………………… 211

想出你的點子……………………………………… 219

Page 4: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

1

事前準備-StampWork 套件

StampWork 套件

在開始實驗前,讓我們先來清點套件然後準備接下來實驗所需要的實驗板

(PDB)。做完這些動作後,你將能順利的做實驗。

Page 5: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

2

建立硬體及軟體 要建立 StampWorks 實驗,你需要下列物品:

實驗板(PDB) BSAIC Stamp 2 模組 12 volt 電源供應器(2.1 mm, center-positive plug) 傳輸線(RS-232 或 USB) 紅和黑電線(22-gauge, solid) 撥線鉗(不包含在 StampWorks 套件裡)

安裝 BASIC Stamp 模組 將 BASIC Stamp 2 模組從泡綿中小心的拿出並裝到實驗板上的 40-針腳的腳座上(在左上角靠近 DB-9 連接線接孔)。你會注意到 BASIC Stamp 2 模組應該可以被適當地安裝在腳座上。請確定 BASIC Stamp 2 模組如下圖所示靠近左邊的安裝。

讓程式連接

用傳輸線(用 RS-232 或 USB,但是不是同時使用)來連接實驗板(PDB)和你的電腦。好是能選擇一個沒有用過的 COM Port。如果你不能拔掉其他裝置,如 PDA 等,

請確定和他通訊的軟體沒有在運作,然後在嘗試開啟 BASIC Stamp 的程式。

Page 6: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

3

Note:使用 USB 連接時請確定你擁有的 FDTI VCP(虛擬 Com Port)驅動程式。相關步驟可上 www.parallax.com 上查詢。

Note:已經有第三方軟體可以讓 BASIC Stamp editor 用於其他作業系統,這些編輯器是不被 Parallax 所支持的。這個文件是預設您是在擁有 Windows 的電腦中使

電腦系統需求 須需要一台桌上型或筆記型電腦來執行BASIC Stamp Editor軟體。為了能順利做StampWorks實驗,請確認你的電腦系統中需要下列物品:

Microsoft Windows® 2000/XP或更新版本 可用的RS-232或USB連接孔 上網裝置

安裝 BASIC Stamp Editor 請從 www.parallax.com 下載 BASIC Stamp Editor for Windows 新版本。執行程式安裝。 下載 StampWorks 程式檔案 這本書上會被寫進 BASIC Stamp2 的範例程式可以免費到 www.parallax.com 下載,還有其他版本的 BASIC Stamp 模組的程式碼也在。

Page 7: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

4

準備麵包板 在實驗板的中間是個麵包板,我們將會在上面建立臨時的電路(包含在StampWorks 套件裡的組合包)。重要的是了解麵包版的操作,事前的小準備可以讓我們接下來的實驗更加容易。 在麵包板 裡面的地方是我們將要連接的組件。麵包板這個部份包含了幾列的腳座(延著頂端印有號碼來供參考)。每列有兩行,分別被標記 A 到 E 和 F 到 J。而每列A 到 E 之間電路是相連的,同樣的 F 到 J 也是。 麵包板的上面和下面由兩條水平的插座,這些水平的行(通常稱為軌道或 Buses)將會接上+5 伏特(Vdd)和接地(Vss)。麵包板中預先就連接好這些軌道,讓他的電可以從頭到尾都可通。把上面和下面的軌道連接在一起然後接上實驗板(PDB)電源供應器的 Vdd 和 Vss。下面是麵包板的外觀:

Page 8: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

5

如果透視麵包板,我們可以看到內部的連接狀況。Vdd 和 Vss 軌道需要被連接,這裡是麵包板內部的樣子:

設定您的剝線鉗在直徑 22(0.34m ㎡)。拿一條黑色電線然後從尾端開始算剝掉 1/4英吋(0.6 公分)。然後用針鼻鉗小心的把裸線彎曲 90 度,像下面圖片一樣:

現在把裸線放到 上面或 下面的軌道中,請放在 29 列上(不要放在麵包版中央)。按住線然後延伸到 32 列上用剪刀輕輕的標記,小心不要剪斷電線。 把線從麵包板上拿下來,然後在你標記的地方用剝線鉗剪下 4 英吋的絕緣膠。現在彎曲第二個 90 度,使導線看起來像 U 型,中間是絕緣膠。 刪除線的電路板,剪約 4 英寸(6 毫米)超越了你剛才提出的商標。有了您的剝線機,刪除絕緣的標誌。現在第二個彎 90 度底裸露,使導線形成一個方形的“U”形與絕緣中間。

Page 9: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

6

如果你已經測量好並小心剪下,這個 U 型的線可以適當的跨在 29 到 32 的軌道上。這樣將創造出一條接地的軌道。重複這個程序用一條黑色電線做在 下面的軌道上。然後用同樣的方法在 60 列上連接這兩個軌道(在軌道的 右邊)。 用紅色的電線連接上面和下面的內側軌道。這些軌道將會帶有正 5 伏特,或 Vdd。在 59 列上把 Vdd 軌道連接在一起。 現在拿起 4 公分的黑線和紅線,彎曲它們變成 U 字形。這些電線不是被設計來躺平在實驗版上的,而是讓他們可以很輕易的從 StampWorks 實驗版上移除。 請仔細的將紅線的一端插進 VDD 區塊裡(靠近 Basic Stamp 插座 pin1 的地方),然後將另一端插在 Vdd 軌道上的第五列。接下來將黑線的一端插進 VSS 區塊內,然後將另一端插在接地軌道上的第一列。請小心 後的兩個接觸點,如果 Vdd 和 Vss軌道互相碰觸通電時將會傷害實驗板。完成後,實驗板上的麵包板看起來像這樣:

Page 10: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

7

後檢查

安裝好 BASIC Stamp 模組和準備好麵包板後在實驗前進行 後的檢查。如果你準備好了,使用傳輸線(RS-232 或 USB)連接電腦和實驗板,連接 12 伏特直流電源到實驗板上。將實驗板上的電源開關開到 ON,電源開關旁邊的藍色 LED 應該會亮起。如果沒有,把電源開關扳到 OFF 然後重新檢查所有連接的地方。 打開 BASIC Stamp Editor 然後鍵入下列程式: ' {$STAMP BS2} Main: DEBUG "Ready for StampWorks 2.1!" END

Page 11: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

8

現在執行程式,如果正確的話,程式會被下載到 BASIC Stamp 模組上並在 Debug Terminal 上顯示

如果出現錯誤,請確認下列事項:

BASIC Stamp 模組有正確的放在實驗版(PDB)上嗎? 實驗版上的電源開關是否被開啟?ON 的 LED 燈是藍的嗎? 電腦跟實驗版上的連接線有確實接好嗎? 你是否選錯 PC 端的 com port? Com port 是否被其他程式佔用? 如果是用 USB 連接,是否已經灌了 FTDI VCP 驅動程式?

當 Debug Terminal 試穿出現然後告訴你 StampWorks Lab 已經好了,這樣就可以來談談 BASIC Stamp 的程式了。

Page 12: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

9

在 STAMWORKS 實驗中使用積體電路注意事項 有兩種方法可以畫出積體電路(IC)的電路圖:一種是以”晶片為中心”,I/O 針腳出現在其設備上的物理位置上。StampWorks 使用說明是用”I/O 針腳放置的位置”,讓圖能更清晰易懂。所有晶片上的 I/O 針腳都是用同樣標準在計算,晶片上的圓洞下的針腳當作 1 然後逆時鐘計算其他針腳如下圖:

Page 13: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

10

Page 14: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

11

程式要點 工作程式目錄 在 BASIC Stamp Syntax and Reference Manual (Basic Stamp 語法與參考手冊) 第 1-4 中介紹 BASIC Stamp 的結構、變數與常數。在這章中,我們將會介紹程式中數值的元素:線性碼(linear code)、分支(branching)、迴圈(loops)和子程式。 它的體系結構和概念的變量和常量。在本節中,我們將介紹各種要素的一個程序:線性碼,分支,循環和子程序。 這些介紹的範例中是用虛擬程式碼來示範及說明程式結構。斜體字是用來表示這段虛擬程式碼需要被更換成有效的編碼才能讓程式編譯與執行。在這裡你不用輸入任合範例因為這些概念都會隨著實驗的進行而用到。 註:虛擬程式碼(pseudo code),提供足夠詳細的程式執行流程以描述程式的每一個執行步驟,藉以提供程式設計師在接下來把程式以特定的程式語言完成(如: C 或JAVA)。 人們通常都會認為電腦或晶片是聰明的,他們在未經過設定是不會動作的。這些設定被叫作程式,而這些就是我們要做的事情。寫 BASIC Stamp 的語言叫做 PBASIC 。是由 Parallax 所特製的 BASIC 版本(初學者通用符號指令代碼)程式語言。BASIC是一個很受歡迎的語言因為他很像英文的語法。由 Dartmouth 學院 1960 年代中期發展這個程式語言至今小至 BASIC Stamp 微處理器大至大型電腦系統。 一個可以運作的程式至少需要幾種狀態,像這樣: statement 1 statement 2 statement 3 END

這個非常簡單,還沒有程式結構。你將會發現大部分的程式執行時是不像前面一樣是線性的。程式通常會用分支、迴圈和子程式,在之間只有短短的線性而已。程序流程在運行時是由目標的程序和條件的程序。

Page 15: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

12

分支- 重新定向程式流程 分支(branching)指令是能改變程式流程的線性路徑。換句話說,當程序遇到一個分支指令,它幾乎不會執行下一行的程式碼。程式通常會到其他地方去,通常還會創造一個迴圈。這邊有兩個分支的指令:無條件和有條件的。PBASIC 有兩個指令:GOTO 和 GOSUB 是無條件分支。下面是用 GOTO 無條件分支的例子: Label: statement 1 statement 2 statement 3 GOTO Label 我們會稱作無條件分支是因為他總是會發生。GOTO 把程式重新定位到其他位置上。這個位置是被 GOTO 指令所指定的,我們稱他為位址。請記住位址是在程式碼的開始地方隨後加上一個冒號(:)。你會經常看到 GOTO 內的程式碼執行完後,又會有個程式讓他再次執行。 條件分支將導致程式流程改變到指定的情況去。 簡單的條件分支就是用 IF-THEN

結構。PBASIC 包含兩種版本的 IF-THEN;第一種是被用於讓程式流程在測試條件下重新定位到另一個點。 看一下下面的情況: Start: statement 1 statement 2 statement 3 IF (condition) THEN Start

在這個例子中 statement 1到3 將至少被執行一次,然後只要條件為真就會繼續執行。需要時,可以測試之前的程式碼:

Page 16: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

13

Start: IF (condition) THEN statement 1 statement 2 statement 3 ENDIF

要注意的是在IF-THEN-ENDIF結構下statement的程式碼不需要分支的標籤。如果條件為假時,程式將會繼續直到ENDIF。另外一種使用條件的結構要添加ELSE: Start: IF (condition) THEN statement 1 statement 2 statement 3 ELSE statement 4 statement 5 statement 6 ENDIF

如果條件為真,然後 statement 1 到 3 將會被執行,否則就是 statement 4 到6 被執行。 隨著需求越來越複雜,你會發現你的程式用數值來做控制的方法然後分支到其他地方。一種方法是用多個 IF-THEN 結構。 IF (index = 0) THEN Label_0 IF (index = 1) THEN Label_1 IF (index = 2) THEN Label_2

這種方法是有效的也常被使用。幸運的是,PBASIC有一個特殊的指令叫做BRANCH

可以依照索引的變數允許程式跳到其他的位址上。BRANCH有一點小複雜,但是非常適合代替多個IF-THEN。BRANCH需要一個控制(索引)變數和位址的列表。

上面的程式可以用下面的代碼取代: BRANCH index, [Label_0, Label_1, Label_2]

Page 17: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

14

當 index 為 0 時,程式將會分支到 Label_0,當 index 為 1,程式將會分支到Label_1,依此類推。 有關 BRANCH 的指令是 ON-GOTO,事實上,它可以直接更換: ON index GOTO Label_0, Label_1, Label_2

有電腦背景的程式設計師應該會熟悉 ON-GOTO,它被包含在 PBASIC 2.5 中。

迴圈-執行程式碼一遍又一遍

在上一節中,程式的迴圈可以在有條件和無條件的分支指令下被創造。大部分的PBASIC 包含 PBASIC 2.5,簡單的說迴圈會用 DO-LOOP 結構。隨著 DO-LOOP 分支標籤不再被需要。這裡有如何使用 DO-LOOP 於無條件的迴圈: 這表現在上一節中,程序可以創建循環與有條件和無條件分支指令。現代變體的基本的,包括 PBASIC 2.5,簡化循環與不循環結構。隨著做迴路的分支標籤不再需要。以下是如何迴路是用來強制無條件循環的數目代碼語句: DO statement 1 statement 2 statement 3 LOOP 正如前面的例子,statement 1 到 3 將會不斷執行。

DO-LOOP 結構將會在迴圈之前或之後設定條件 statements: DO WHILE (condition) statement 1 statement 2 statement 3 LOOP

在這範例中迴圈中的 statement 如果 if 和 while 的條件為真才會被執行 DO statement 1 statement 2 statement 3 LOOP WHILE (condition)

Page 18: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

15

在第二個例子中,迴圈中的statement將會被執行至少一次,即使條件為假。如你所見,DO-LOOP可以簡化條件的測試條目。 UNTIL是DO-LOOP中會被加入的指令 DO statement 1 statement 2 statement 3 LOOP UNTIL (condition) DO UNTIL (condition) statement 1 statement 2 statement 3 LOOP

使用 UNTIL,迴圈的狀態將會在將會在條件為假時被執行。 而且,如前所示,在測試結束前迴圏的狀態至少會被執行過一次, 另外一種迴圈的範例是用 FOR-NEXT。 FOR controlVar = startVal TO endVal STEP stepSize statement 1 statement 2 statement 3 NEXT

FOR-NEXT 結構是用來在一定次數下執行部分程式碼。FOR-NEXT 用來控制變數來決定迴圈的次數。變數的大小將決定權圈的 大極限。例如,用 byte 大小的變數則變數的 大值是 255。下面的例子中,controlVar 將被定義成一個 Nib(4-bit)大小的變數,所以他 後的數值將小於 16: FOR controlVar = 1 TO 10 statement 1 statement 2 statement 3 NEXT

Page 19: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

16

在 FOR-NEXT 中 STEP 是用來在當回圈需要計數時。例如,如果回圈需要計數偶數,程式碼看起來會像這樣: FOR counter = 2 TO 20 STEP 2 statement 1 statement 2 statement 3 NEXT

子程式-能節約可重複使用的程式碼空間

後的程式概念,我們將討論的是子程式。子程式是一段可以從程式任何的地方被呼叫的程式碼。GOSUB被用來重新指向程式到子程式中。子程式是用RETURN來停止。RETURN讓程式跳回GOSUB原先的地方。 Start: DO GOSUB My_Sub PAUSE 1000 LOOP My_Sub: statement 1 statement 2 statement 3 RETURN

在這個範例中,My_Sub 子程式被執行然後程式跳回 PAUSE 1000 這一行。 厲害的程式設計師會用更進階的子程式 ON-GOSUB。ON-GOSUB 就像是 ON-GOTO

一樣,但是程式會隨 ON-GOSUB 回到程式流程中。這個技巧在如下面程式結構創造任務時非常實用: Main: DO GOSUB Critical_Task ON task GOSUB Task_1, Task_2, Task_3 task = task + 1 // 3 LOOP

Page 20: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

17

Critical_Task: statement(s) RETURN Task_1: statement(s) RETURN Task_2: statement(s) RETURN Task_3: statement(s) RETURN

在Critical_Task中這類型的程式碼和其他任務是交叉的。把所有任務的程式碼放到離散子程式中,他們可以從程式任何點中被呼叫。他們允許在一個任務去測試情狀然後如果需要的話呼叫其他子程式,或是設定下一個任務。

Page 21: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

18

Page 22: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

19

PBASIC風格的元素 就像大部分的 PBASIC 語言的版本,PBASIC 是個非常寬鬆而且編譯器沒有特殊格式。只要程式碼的語法是正確的,他做完編譯後再下載到 BASIC Stamp 中是不會有問題的。 為什麼要提出一個特定的 PBASIC 風格呢?隨著數百萬計的 BASIC Stamp 微處理機被賣出,在世界上成千上萬的的使用者會像你一樣沒有一起開發 BASIC Stamp的案子但是會分享你的 PBASIC 程式碼給別人。寫一個有組織的程式碼,可以預期將節省你和你的夥伴的時間,不管是在分析、故障排除,尤其是當你經過長時間休息後再返回工作時。 風格準則再這裡要說明的只有一件事:準則。他們已經在其他高階語言的高級程式設計師中開發出風格準則,像是 Java、C/C++、Visual Basic。使用這些準則,或修改他們以適合你的需要。關鍵就是選擇一個風格是適合你並且堅持住。 1.第一次就作對 許多程式設計師,特別是新手,常會掉入”我將會先打入然後稍後再修改”的陷阱。總是在”事後修改”心態下草率的寫程式。如果你沒有在第一時間做正確,你什麼時候有時間再做一次呢? 開始清除錯誤的觀念,你將會減少你錯誤的程式碼出現的機會。如果出現錯誤,要找出來並修復他會變的更為簡單。 2.組織性與一致性 使用空白的程式模組可以幫助你組織你的程式然後建立出一致的編寫風格。BASIC Stamp Editor 允許你在 File/New function 用指定的模板(請參見 Edit/ Preference/ File&Directories…)

Page 23: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

20

3.使用有意義的命名 編寫程式時需要大量的命名常數、變數、程式標籤。編譯器允許命名 長到 32 個字。使用有意義的名字可以減少註解的數量還有使你的程式更容易被閱讀、除錯、維護。 4.為 I/O 針腳命名 在 BASIC Stamp 的 I/O 針腳在 PBASIC 語言中是個很特別的元素,我們需要設定兩個常數,輸出及輸入。輸出及輸入。用大寫字母及混合單字來為 I/O 針腳命名,我們會在每個新單字前用大寫字母。用 BS2 時,PIN 是被定義來使用的。這會導致編譯器可以在針腳上做出正確的動作(常數、輸出位元、輸入位元)。 HeaterCtrl PIN 15

因為連接器在程式運行中不能改變,所以 I/O 針腳的命名像是常數一樣(#5),使用混合單字而且開頭使用大寫字母。 5.常數命名 輸出及輸入。用大寫字母及混合單字來為常數命名,我們會在每個新單字前用大寫字母。 AlarmCode CON 25

6.變數命名 用小寫字母及混合單字來為變數命名,我們會在每個新單字前用小寫字母。為避免在程式中使用到內部設定的變數名稱(例如 B0 或 W1)。用宣告一個變數的型態來讓編譯器自動分配一個記憶體的空間。 waterLevel VAR Word

Page 24: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

21

7.變數型態的定義 為了節省 BASIC Stamp 記憶體的使用,我們必須知道每種變數宣告所代表的大小。 bitValue VAR Bit ' 0 - 1 nibValue VAR Nib ' 0 - 15 byteValue VAR Byte ' 0 - 255 wordValue VAR Word ' 0 - 65535

8.程式標籤 程式標籤在一開始會用大寫的字母,混合單字,並在字跟字中間放一個底線。在使用標籤前至少要有一個空格,並在第一行後放入一個冒號(除了在 GOTO 和 THEN

後以外) Print_ZString: DO READ eeAddr, char eeAddr = eeAddr + 1 IF (char = 0) THEN EXIT DEBUG char LOOP RETURN

9.PBASIC 關鍵字

所有PBASIC語言關鍵字,包括SYMNOL,CON,VAR,PIN和串聯/顯示模組(DEC,HEX,BIN)和控制字元(CR,LF)應該都是大寫。BASIC Stamp編輯器會自動的把PBASIC 關鍵字換成正確的格式,並且允許你設定適合的顏色。 Main: DEBUG "BASIC Stamp", CR END

Page 25: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

22

10.縮排嵌套的程式碼 嵌套的程式碼區塊可以提高可讀性並且有助於降低錯誤。建議讓每個級別都縮進兩個空格,才不會佔用太多空間。 Main: ..DO ....FOR testLoop = 1 TO 10 ......IF (checkLevel < threshold) THEN ........lowLevel = lowLevel + 1 ........LedOkay = IsOff ......ELSE ........LedOkay = IsOn ......ENDIF ......PAUSE 100 ....NEXT ..LOOP WHILE (testMode = Yes) Note:這些半透明的點是用來說明縮排而不是程式碼的一部份。 11. 條件語句 用括號把條件語句框起來讓人更容易看清楚。 Check_Temp: IF (indoorTemp >= setPoint) THEN AcCtrl = IsOn ELSE lowLevel = lowLevel + 1 ENDIF Fill_Water_Tank: DO WHILE (waterLevel = IsLow) TankFill = IsOn PAUSE 250 LOOP Get_Delay: DO DEBUG HOME, "Enter time (5 – 30)... ", CLREOL DEBUGIN DEC2 tmDelay LOOP UNTIL ((tmDelay >= 5) AND (tmDelay =< 30))

Page 26: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

23

12.多使用空格 空白區域(空格或空行)不會影響編譯器或 BASIC Stamp 的表現,所以多多的使用它讓旁人更容易閱讀。在#8 上有個建議,就是在程式標籤前至少要有個空白行(建議在子程式標籤前與兩行空白)。 Main: DO ON task GOSUB Update_Motors, Scan_IR, Close_Gripper LOOP Update_Motors: PULSOUT leftMotor, leftSpeed PULSOUT rightMotor, rightSpeed PAUSE 20 task = (task + 1) // NumTasks RETURN

有一個準則的例外是用SHIFTIN和SHIFTOUT的Bits參數,DEBUG和SEROUT後面使用的REP修改器,還有SERIN後面的byte計數和終止位元值。在這些情況下,就不增加空格。 SHIFTIN A2Ddata, A2Dclock, MSBPOST, [result\9] DEBUG REP "*"\25, CR SERIN IRbSIO, IRbBaud, [buffer\8\255]

13.使用兼容性的編譯條件 一些指令如 SERIN 和 SEROUT 根據不同的 BASIC Stamp 而使用不同的參數。使用條件編譯讓你的程式能達到 大的相容性。 #SELECT $STAMP #CASE BS2, BS2E, BS2PE T1200 CON 813 T2400 CON 396 T9600 CON 84 #CASE BS2SX, BS2P T1200 CON 2063 T2400 CON 1021

Page 27: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

24

T9600 CON 240 #CASE BS2PX T1200 CON 3313 T2400 CON 1646 T9600 CON 396 #ENDSELECT

在StampWork文件中(可在www.parallax.com下載)包含了一個空白的程式樣板(Template.BS2)可以幫助你在一開始編寫程式碼。這取決於你跟隨上面的準則或是開發自己的準則。

Page 28: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

25

實驗開始! 學習程式概念 下面一系列的實驗中你講開始建立並執行你的 StampWorks 實驗室。這些實驗的目的是教導程式的概念和在 BASIC Stamp 上使用外部元件。實驗的重點和設計讓你可以結合自己的概念來完成複雜的任務。 建立專案 這個章節雖然很簡單卻很重要,因為你將會在你的 StampWork 實驗室中學到很重要的程式經驗及建立技巧。當你學完課本後結構的細節可能不多(你會在以後學到,而且讓你自己選擇)而程式的討論也不會繁瑣,我們將專注於 BASIC Stamp 使用特別的技巧或是連接外部裝置。 在專案間該做什麼 一個專案的電路在某些情況下可能不相容於其他的專案或者是舊的程式跑新的電路可能會傷害到 BASIC Stamp。因此當 BASIC Stamp 上建立新的電路前應該下載一個空白的程式到裡面。這樣將會保護 BASIC Stamp I/O 介面的內部電路。這裡有一個範例程式可以清除並重置 BASIC Stamp。 ' {$STAMP BS2} Main: DEBUG "BASIC Stamp clear." END

為了方便起見,儲存程式到CLEAR.BS2。

Page 29: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

26

實驗#1:點亮一顆 LED 燈 LED 幾乎出現在所有的電氣設備上,顯示某些訊息讓客戶知道。 BASIC Stamp 簡單的實驗就是亮一顆 LED,亮一顆 LED 通常用於警示或狀態顯示。 注意:必須知道的 PBASIC 元素

$STAMP(直接編譯)

$PBAISC(直接編譯) PIN CON HIGH LOW PAUSE GOTO

建立電路 所有的 StampWork 實驗會用虛線表示被安裝在實驗板上的零件。LED 在實驗板上的”LEDS”區域,就在 BASIC Stamp 插座的右邊。

實驗板上有 16 個 LED 內建在裡頭,只有連接在一個 BASIC Stamp 模組。 1.開始時用一條 3 英吋(8 公分)的白電線,在兩端各剝開約 1/4 英吋(6 公厘)的絕緣體。 2.將一端插在 BASIC Stamp 的 P0 位置。 3.將另一端插在 LED 0。

Page 30: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

27

程式: SW21-EX01-Flash_LED.BS2: ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Flashes an LED connected to P0. This program will work, unmodified, on ' any BS2-family module. ' -----[ I/O Definitions ]------------------------------------------------- AlarmLed PIN 0 ' LED on P0 ' -----[ Constants ]------------------------------------------------------- FlashTm CON 500 ' delay 500 milliseconds ' -----[ Program Code ]---------------------------------------------------- Main: HIGH AlarmLed ' turn the LED on PAUSE FlashTm LOW AlarmLed ' turn the LED off PAUSE FlashTm GOTO Main

幕後

每個 BASIC Stamp 的 I/O 針腳有 3 個位元(bit)來做控制。在 DIRS 暫存器中有一個位元是在測量該針腳是輸入(位元=0)或是輸出(位元=1)。如果針腳的配置是輸出,該針腳正確的狀態將會被儲存在 OUTS 暫存器中。如果該針腳的狀態是輸入,則該針腳正確的數值將會被儲存在 INS 暫存器中。 HIGH 和 LOW 是在一行指令中執行兩種功能:選擇針腳配置為輸出(在 DIRS 暫存器中為 1)和在 OUTS 暫存器中修改狀態位元(HIGH 為 1,LOW 為 0)。

Page 31: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

28

例如這樣: HIGH 0 … …事實上跟跟下面的表現是一樣的: DIR0 = 1 ' make P0 an output OUT0 = 1 ' set P0 high

但是他只需要一行程式碼。節省程式空間一直是微處理器程式撰寫很重要的地方,當我們可以節省時我們就應該要想到以後我們可能會需要用到這些空間。

就像一位專家編寫程式碼

請注意就算是一非常簡單的程式,我們還是會徹底的執行”PBASIC 風格元素”的風格準則。透過這樣專業的風格,程式會變的像自己的文件,只需要較少的指令,並讓程式的修改更為方便。例如,如果我們想改變 LED 針腳位置或閃爍的頻率,我們只需要更改一小部份而不需要編輯整個。當我們的程式發展到幾百行時,巧妙的為針腳命名和常數可以節省我們很多時間和挫折。

一個初學者常犯的錯誤像這樣: OUTPUT 0 HIGH 0 我們不需要為像這樣為針腳寫上輸出的功能,因為HIGH本身就包含了。這樣做雖然不會傷害硬體,但是它浪費了寶貴的程式碼空間。只有很少的場合是需要程式去操縱INPUT和OUTPUT,大部分的PBASIC指令可以處理針腳的I/O狀態。

Page 32: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

29

實驗#2:亮一顆 LED(進階) 現在我們既然開始了,讓我們加快速度並來探索更進階的碘量 LED 燈。這個方法提供更好的程式可讀性和易於維護。 查一查:必須要知道的 PBASIC 元素

OUTPUT DO-LOOP VAR Nib (宣告型態)

BITO…BIT 15(數值修改器) 建立電路 這個實驗的電路和實驗#1 是一樣的。

程式:SW21-EX02-Flash_LED-Adv.BS2: ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Flashes an LED connected to P0. This program will work, unmodified, on ' any BS2-family module. ' -----[ I/O Definitions ]------------------------------------------------- Strobe PIN 0 ' LED on P0 ' -----[ Constants ]------------------------------------------------------- IsOn CON 1 ' on for active-high LED IsOff CON 0 ' off for active-high LED FlashOn CON 50 ' on for 50 ms FlashOff CON 950 ' off for 950 ms ' -----[ Initialization ]--------------------------------------------------

Page 33: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

30

Reset: Strobe = IsOff OUTPUT Strobe ' enable pin to drive LED ' -----[ Program Code ]---------------------------------------------------- Main: DO Strobe = IsOn PAUSE FlashOn Strobe = IsOff PAUSE FlashOff LOOP

幕後 這個版本的 LED 警示燈用較低等級的方式得到硬體的核心和運作-多一點的設定工作,但是它讓程式有更大的可讀性以及更靈活的修改。這邊有個沒錯的定義:

Strobe = IsOn 在 Reset 標籤上,叫做 Stobe 的 LED 控制針腳會設定關閉狀態 IsOff 為常數,然後針腳將狀態輸出,這樣就可以控制 LED。這裡很罕見的使用 OUTPUT,因為在這之前,LED 控制已經被 OUTS 暫存器所寫入。

這個初始化的部份顯示 PIN 的宣告

事實上這行代碼:

Strobe = IsOff OUTPUT Strobe

…被編譯器翻譯成:

OUT0 = 0 OUTPUT 0

請注意編譯器如何能聰明地代替成第一行的OUT0和第二行的數字0。當然我們可以把程式碼寫成跟編譯器 後翻譯的一樣。不同的是Strobe在程式功能中更具實質意義(對人類而言),而且任合設計改變將會比這個更困難。

Page 34: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

31

主程式的迴圈主要是用DO-LOOP來處理,並且分別提供開和關的時間來讓LED閃爍。如同針腳的配置,我們可以用簡單的編輯宣告的部份來改變閃爍的動作。由於LED有兩種狀態,每種狀態都是獨立的給我們很大的靈活性。

更進一步

另外一種更好的方式讓我們可以直接使用輸出位元的方法如下:

DO Strobe = cntr.BIT0 PAUSE 500 cntr = cntr + 1 LOOP

可以告訴大家上面的程式做了什麼嗎?因為Strobe是一個位元變數(在程式中的OUT0),我們可以寫進任何位元數值到裡面-甚至是其他的變數的位元。上面的例子BIT0( 低有效位元(LSB))的cntr將會透過程式迴圈被寫到控制LED的針腳。利用我們active-high的配置,當cntr為奇數時LED會亮因為cntr讓BIT0也是奇數。

Q:不修改PAUSE 500這一行,我們怎麼樣使LED閃爍的頻率減半? A:寫一個cntr.BIT1到LED。你知道為什麼要這樣做嗎?

註:ACTIVE LOW 是指當受偵測電壓(一般是電源)低於臨界電壓(THRESHOLD VOLTAGE)時,則輸出是接至 GND;ACTIVE HIGH 是指當受偵測電壓(一般是電源)低於臨界電壓(THRESHOLD VOLTAGE),則輸出是接至 VCC

DO-LOOP 和 GOTO 要在什麼時候用比較對呢?雖然兩者在功能上是一樣的,DO-LOOP 比 GOTO 方便在於不用定義程式的標籤。缺點是當 DO-LOOP 在一長串程式碼中很難找,特別是程式設計準則被忽略時。 雖然沒有硬性規定,但是有個準則可以遵循,大約十行已內的程式碼用 DO-LOOP,超過的話儘量使用 GOTO。

Page 35: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

32

就像一位專家編寫程式碼 此版本的 LED 信號燈是讓你了解一個專業的程式編輯者如何達成任務。為什麼?如果你被要求寫一個程式需要亮幾個 LED 燈,你以為他們是 active-high 的,可是經過幾個小時後你發現你手上原理圖的 LED 連接是像這樣:

LED 在原理圖上是 active-low,你必須讓控制針腳電位變為 LOW 才能點亮 LED。現在你將被迫把控制 LED 燈的指令從 HIGH 改為 LOW,然後原始的 LOW 指令改成 HIGH,這將多出很多工作而且可能導致程式錯誤。 一個專業的程式設計師會讓程式有很大的靈活性,他們能讓電路設計變更更為輕鬆。使用一些技巧在實驗上,我們只要改變下列宣告。 IsOn CON 0 ' on for active-low LED IsOff CON 1 ' off for active-low LED

這樣重設程式不用改變結構而且可以直接執行。

Page 36: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

33

實驗#3:用 LED 燈顯示一個計數器 多數的設備都需要至少一顆 LED 燈,從程式的角度來看同時改變所有 LED 燈是很方便的。這個實驗說明如何用多個 LED 燈來顯示一個 4-bit 的計數器。 大多數應用程序將需要一個以上的 LED,從編程的角度來看是很方便的更新所有LED 的同時如果可能的話。這個實驗表明更新由多個 LED 顯示正在運行的 4 位計數器。 查一查:必須要知道的 PBASIC 元素

OUTS, OUTL, OUTH, OUTA – OUTD DIRS, DIRL, DIRH, DIRA – DIRD FOR-NEXT

建立電路

在這個實驗中我們將會在實驗#1 和#2 的電路中添加三個 LED 燈。 1. 一開始用 4 條 3 英吋(8 公分)的白電線。把兩端大約 1/4 英吋(6 公厘)的絕緣體剝

掉。 2. 將電線的一端插到 BASIC Stamp 的 P0 上。 3. 將另一端插在 LED 0 上。 4. 重複步驟 2 和 3 連接 P1 到 P3 及 LED 1 到 3。

Page 37: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

34

程式:SW21-EX03-Counter_LEDs.BS2: ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Displays a 4-bit binary counter on LEDs connected to P0 - P3. This ' program will work, unmodified, on any BS2-family module. ' -----[ I/O Definitions ]------------------------------------------------- LEDs VAR OUTA ' LEDs on P0 - P3 LEDsDirs VAR DIRA ' DIRS control for LEDs ' -----[ Constants ]------------------------------------------------------- MinCount CON 0 ' counter start value MaxCount CON 15 ' counter end value DelayTm CON 100 ' delay time for LEDs ' -----[ Variables ]------------------------------------------------------- cntr VAR Nib ' 4-bit counter variable ' -----[ Initialization ]-------------------------------------------------- Reset: LEDsDirs = %1111 ' make LEDs outputs ' -----[ Program Code ]---------------------------------------------------- Main: DO FOR cntr = MinCount TO MaxCount ' loop through all values LEDs = cntr ' move count to LEDs PAUSE DelayTm ' hold a bit NEXT LOOP ' repeat forever

Page 38: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

35

幕後 正如實驗#1,BASIC Stamp 的輸出位元是被儲存在一個叫做 OUTS 的記憶體暫存器中。變數 OUTA 是 OUTS 中比較低的四個位元,對應到 I/O 針腳中的 P0 到 P3。因為 OUTA 是屬於 BASIC Stamp 一般功能的記憶體的一部份,所以變數可以像其他變數一樣被寫入或讀取。 在程式中我們可以簡單的轉移(複製)4 位元變數 cntr 的內容到 OUTA(別名 LED燈)。由於 P0 到 P3 已經輸出,這將導致變數 cntr 會用二進制的格式來顯示。 挑戰自我:修改程式來讓計數器倒數。

Q:我們可以在不用 cntr 變數的前提下得到同樣的結果嗎? A:可以!我們可以用 FOR-NEXT 來簡單的控制變數。 就像一位專家編寫程式碼

由於我們是用一個群組的概念來處理多的 LED 燈,所以我們不能用 PIN 的宣告類型來處理,我們不得不使用標準變數(在這裡是 OUTA)來讓 LED 同時運作。如果可能的話, 好輸出群組能跟 BASIC Stamp 及記憶體結構能吻合。我們的程式不會永遠像這個實驗一樣整潔,但是當我們 終會用 4 個或 8 個針腳來做組合,這是使用 BASIC Stamp 好的方式。 要注意的是雖然 LEDsDirs 變數不是實際控制 I/O 針腳的狀態,但是它設定了針腳的狀態而且這須要用一條簡單的程式碼來將針腳的狀態輸出。因為這樣,要在 I/O定義區中在 LEDs 宣告附近定義。例如,如果我們需要改變設計將 LEDs 移動到OUTD,只需要在程式中相同的區域做一點改變。

LEDs VAR OUTD ' LEDs on P12 – P15 LEDsDirs VAR DIRD ' DIRS control for LEDs

Page 39: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

36

實驗#4:科幻小說的 LED 燈顯示 我們已經看到如何用 LED 來顯示二進制的數值(實驗#3),現在我們將多做一些步驟和多一些藝術。在這個實驗中我們將會創造出一條就像在電影或電視中看到的科幻小說道具一樣 LED 顯示器。 查一查:必須要知道的 PBASIC 元素

WHILE(關於 DO-LOOP) UNTIL(關於 DO-LOOP) <(小於操作器) <<(向左移運算子) >>(向右移運算子)

建立電路

在這個實驗中將會加入比實驗#3 還要多四條 LED 到電路中。 1.一開始用 4 條 3 英吋(8 公分)的白電線。把兩端大約 1/4 英吋(6 公厘)的絕緣體剝掉。 2.將電線的一端插到 BASIC Stamp 的 P0 上。

Page 40: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

37

3.將另外一端插入 LED 0。 4.重複步驟 2 和 3 將 P1 到 P7 及 LED 1 到 7 完成。 程式: SW21-EX04-SciFi_LEDs.BS2: ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' "Ping-Pongs" a single LED back-and-forth across a bank of eight. This ' program will work, unmodified, on any BS2-family module. ' -----[ I/O Definitions ]------------------------------------------------- LEDs VAR OUTL ' LEDs on P0 - P7 LEDsDirs VAR DIRL ' DIRS control for LEDs ' -----[ Constants ]------------------------------------------------------- DelayTm CON 100 ' delay time for lit LED ' -----[ Initialization ]-------------------------------------------------- Reset: LEDS = %00000001 ' start with right LED on LEDsDirs = %11111111 ' make LEDs outputs ' -----[ Program Code ]---------------------------------------------------- Main: DO WHILE (LEDs < %10000000) ' test for left extreme PAUSE DelayTm ' on-time for lit LED LEDs = LEDs << 1 ' shift LED left LOOP DO PAUSE DelayTm LEDs = LEDs >> 1 ' shift LEDs right LOOP UNTIL (LEDs = %00000001) ' test for right extreme GOTO Main

Page 41: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

38

幕後 這個實驗證明了可以用其他變數來直接操縱 BASIC Stamp 輸出針腳。程式還展示了在前和後添加 DO-LOOP 來測試。 程式一開始先將 LEDs 初始化成%00000001,這樣能證明 LED 有被連接在 P0。當我們將第一個 DO-LOOP 放入 LEDs 後馬上開始測試。如果 LEDs 的數值(目前是%00000001)在 DO-LOOP 迴圈中小於%10000000,程式就會被允許執行,否則程式會跟隨 LOOP 這一行的程式繼續執行。 由於 LEDs 剛開始是小於測試的數值,程式伴隨著一小個暫停指令 PAUSE 在迴圏中往下執行,然後點亮的 LED 隨著<<操作器(向左移動)往左移動。向左移動一個位元就等於乘以 2,顯然更有效率。移動完後程式又回到 DO WHILE 這一行,此時 LEDs

的數值(現在是%00000010)將會再次被測試。 在迴圈中執行七次後,LEDs 的數值變成%10000000 而且條件會變成假(結果為為假);這將讓程式跳到第二個 DO-LOOP 的 上方。

第二個的 DO-LOOP 和第一個幾乎是一樣的,只是 LEDs 的數值是用>>(效果同除以2)向右移動,而在迴圈的 後會做測試。請注意,當測試被放在 DO-LOOP 後面時,迴圈的程式碼將會至少被執行一次。在經過七次測試後條件會變為假而且程式碼會往下執行到 GOTO Main,引領我們回到程式的 上頭。

初學者常常會問:”什麼時候我該用 WHILE UNTIL 來做迴圈?” 其實用 WHILE 或 UNTIL 可以撰寫出同樣的功能。不過,如果你的程式碼很有邏輯,它將會很容易讓其他人遵循。因此建議當條件為真時用 WHILE 來執行回圈;而 UNTIL 是直到條件變為真時才執行回圈。

Page 42: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

39

Page 43: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

40

更進一步 Q:我們如何用程式讓 LED 燈的行為看起來像是飛機跑道的指示燈? A:看看一種解決方法

Reset: LEDsDirs = %11111111 ' make LEDs outputs ' -----[ ProgramCode ]--------------------------------------------- Main: LEDs = %00000001 ' start with right LED on DO PAUSE DelayTm ' on-time for lit LED LEDs = LEDs << 1 ' shift LED left LOOP UNTIL (LEDs = %10000000) ' test for last LED GOTO Main

就像一位專家編寫程式碼 在這個實驗中我們頻繁地使用二進位(%),對我們程式編輯者(像是 BASIC Stamp IDE)而言這是一個很實用的工具,這是一點程式碼,例如:

LOOP UNTIL (LEDs = %10000000) ' test for last LED

這遠比下面的程式碼更容易看的懂: LOOP UNTIL (LEDs = 128) ' test for last LED

當處理完二進位的輸入(例如按鍵或開關)或輸出(例如 LED 燈),使用二進位的標註可以幫助你(或其他人)更”看”得懂程式碼。

Page 44: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

41

實驗#5:LED 圖形(點或線) 在實驗#4 中我們使用一排的 LED 燈來達到藝術的目的,現在我們改變一點來達到更有科技感的目的。這些圖案在音響設備上常會看到,特別是用在 VU(聲音)測量器上。 查一查:必須要知道的 PBASIC 元素

Word(宣告型態)

Byte(宣告型態) GOSUB-RETURN RCTIME IF-THEN-ELSE-ENDIF */(星號-斜線 操作器) DCD

建立電路 在實驗#4 添加下面的 RC 電路到 LED 上。

Note:0.1 μF 電容(標註 104) 1. 用黑線(如果必要時切一段),連接 Vss(接地)軌道到 A15 插座。 2. 將 0.1 μF 電容(標註 104)到 C15 和 C16。

3. 用白電線連接 A16 到 BASIC Stamp 的 P15 上。

Page 45: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

42

4.用白電線,連接 B16 插座到 10K 可變電阻旁。

5.用黑電線,連接 Vss(接地)軌道上和 10K 可變電阻的下方。 程式: SW21-EX05-LED_Graph.BS2: ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Displays a linear (bar) or dot graph using eight LEDs. This program ' will require modifications (to the constants LoScale and HiScale) when ' running on the BS2Sx, BS2p, or BS2px. ' -----[ I/O Definitions ]------------------------------------------------- LEDs VAR OUTL ' LEDs on P0 - P7 LEDsDirs VAR DIRL ' DIRS control for LEDs Pot PIN 15 ' Pot circuit IO ' -----[ Constants ]------------------------------------------------------- DotGraf CON 0 ' define graph types BarGraf CON 1 GraphMode CON BarGraf ' define graph mode IsOn CON 1 IsOff CON 0 LoScale CON 10 ' raw low reading HiScale CON 695 ' raw high reading Span CON HiScale - LoScale ' between lo-to-hi Scale CON $FFFF / Span ' scale factor 0..255 ' -----[ Variables ]------------------------------------------------------- rawVal VAR Word ' raw value from pot grafVal VAR Byte ' graph value hiBit VAR Byte ' highest lighted bit newBar VAR Byte ' workspace for bar graph

Page 46: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

43

' -----[ Initialization ]-------------------------------------------------- Reset: LEDsDirs = %11111111 ' make LEDs outputs ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Read_Pot ' get raw pot value grafVal = (rawVal - LoScale) */ Scale ' z-adjust, then scale GOSUB Show_Graph ' now show it PAUSE 50 LOOP ' -----[ Subroutines ]----------------------------------------------------- Read_Pot: HIGH Pot ' charge cap PAUSE 1 ' for 1 millisecond RCTIME Pot, 1, rawVal ' read the Pot RETURN Show_Graph: hiBit = DCD (grafVal / 32) ' get highest bit IF (GraphMode = BarGraf) THEN newBar = 0 ' clear bar workspace IF (grafVal > 0) THEN DO WHILE (hiBit > 0) ' all bar LEDs lit? newBar = newBar << 1 ' no - shift left newBar.BIT0 = IsOn ' light low end hiBit = hiBit >> 1 ' mark bit lit LOOP ENDIF LEDs = newBar ' output new level ELSE LEDs = hiBit ' show dot value ENDIF RETURN

Page 47: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

44

幕後 現在我們把這個程式,雖然很短,但是他也有他複雜的一面,它使我們能夠讀取可變電阻的原始讀數且可以讓程式休息。 初始化輸出(P0 到 P7)來驅動 LED 燈,程式會用 RCTIME 方程式來讀取 10K 可變電阻的值。利用 DEBUG 來顯示原始數值,RCTIME 讓數值介於 10 到 746 之間。因為graVal 是 byte 大小的變數,所以 rawVal 必須縮小來存放於 8 位元內。

我們希望透過 2.73(695/255)來將原始數值修改到適應 grafVal。問題是PBASIC 只能用整數,所以我們到 後我們會有一些誤差存在。由於乘以該數值的倒數結果是一樣的,我們可以讓 rawVal 乘上 0.366906。在一些例子中我們可以用乘法來接近除法的近似值,但是這是不可能的,因為在 PBASIC 中 16 位元( 終)數值高位元可能會被捨去。 這就是為什麼*/(星號-斜線)運算子會被介紹:這個運算子允許我們乘上解答的1/256 的數值。*/的工作方式是將兩個數值相乘,然後選取 32 位元中間的兩個位元組-這樣的影響是乘上它後可以馬上分成 256 份(因為結果是 1/256)。如果該分數是個常數我們可以用事先乘以 256 及*/參數的分數。在我們案例中可以:

0.366906 x 256 = 93.92 (進位到 94) 事實證明,我們可以很容易的計算出利用電壓跨度(high和low不同的讀值)除以$FFFF來得到的Scale數值( 高為16位元數值)。更好的是我們可以嵌入這個計算結果當作是恆定的定義-這將讓我們可以省下寶貴的變數空間。在 上面一行我們有:

LoScale CON 10 ' raw low reading HiScale CON 695 ' raw high reading Span CON HiScale - LoScale ' between lo-to-hi Scale CON $FFFF / Span ' scale factor 0..255

Page 48: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

45

如果我們決定更換 BS2 的以更快的微控制器,例如一個 BS2p,我們唯一需要做的就是讀電壓,從他鍵入低和高讀值。在我們改變這些後 Scale 常數將會被在下次編譯時被下載,然後程式就像在 BS2 上跑一樣。 你可能想知道為什麼 LoScale 值會大於 0。如果你看著原理圖,有一個 220 歐姆的電阻在可變電阻還有中心連接點之間。這樣的目的是要當可變電阻轉到 Vss 和P15 是輸出 high 時保護 BASIC Stamp,這將會導致電容放電時有一點點小延遲,因此也造成 小值會大於零。 隨著 grafVal 縮放到一個 byte(255)的大小我們可以用 LED 燈創造一行或一個點的圖形。這個程式用 DCD 運算子來計算從 grafVal 高亮起的位元數值。在一個8 個 LED 燈的圖形中,grafVal 除以 32,這將導致 DCD 的輸出數值從%00000001(DCD 0)到%10000000(DCD 7)。 在點模式下,一個亮起的 LED 燈代表可變電阻輸入。在線條模式下,較低的 LED燈必須先填滿。這樣一個簡單的迴圈就完成了。迴圈的控制變數是個變數,hiBit 同時也在用 DCD 計算。在這個迴圈中,hiBit 會從 0 到離開都會測試,所以每次重複經過迴圈時這個值都會減少。 如果 hiBit 大於 0,線條圖案的工作區變數 newBar 會向左移動而他的 bit 0 會被設定。例如,如果 DCD 在 hiBit 中回到%1000,這裡要說 hiBit 和 newBar 是如何影響整個迴圈:

hiBit newBar 1000 0001 0100 0011 0010 0111 0001 1111 0000 (結束 – 離開回圈並顯示數值)

newBar 變數的目的是要防止在每次更新時 LED 燈會閃爍。這樣允許程式在開始時有個”空”的圖形並建立起正確的數值。擁有這樣的技巧後,程式就不用記憶前次圖形的數值了。

Page 49: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

46

就像一位專家編寫程式碼

當你的程式越來越複雜時,同時編寫程式並測試是很重要的。在這個程式中分別有兩個子程式;每個都是獨立的程式碼並且再把它們結合一起前測試。當程式準備好要運作時獨立測試程式模組很重要-沒有比用沒經錯測試的程式碼破壞一個好程式更顯得沮喪了。

Page 50: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

47

實驗#6 簡單的遊戲 隨著提高小型微處理機的發達,手持式的小遊戲已經變成我們文化中的一部份。本實驗的目的就是利用 BASIC Stamp 來創造一台簡單的吃角子老虎機遊戲,並完成燈光及聲音效果。 查一查:必須要知道的 PBASIC 元素

RANDOM &(And 運算子) FREQOUT BUTTON LOOKUP #DEFINE(條件編譯)

#IF-#THEN-#ELSE-#ENDIF(條件編譯) 建立電路

Page 51: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

48

1.用白電線,連接 BASIC Stamp 針腳 P0 到 P5 到 LEDs 0 到 5。 2.用白電線,連接 BASIC Stamp 針腳 P6 到聲音放大器(設定喇叭的選項請到 SPK) 3.用白電線,連接 BASIC Stamp 針腳 P7 到按鈕。 程式: SW21-EX06-Las_Vegas.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program simulates a very simple slot machine game, complete with ' sound FX. The constants TAdj and FAdj may require adjustment when using ' on faster BASIC Stamp modules. ' -----[ I/O Definitions ]------------------------------------------------- LEDs VAR OUTL ' LED outputs LEDsDirs VAR DIRL ' DIRS control for LEDs Speaker PIN 6 ' speaker output PlayBtn PIN 7 ' button input to play ' -----[ Constants ]------------------------------------------------------- TAdj CON $100 ' time adjust factor FAdj CON $100 ' frequency adjust factor ' -----[ Variables ]------------------------------------------------------- rndVal VAR Word ' random number pattern VAR Byte ' light pattern tone VAR Word ' tone output swData VAR Byte ' workspace for BUTTON delay VAR Word ' delay while "spinning" spin1 VAR Byte ' loop counter spin2 VAR Byte ' loop counter ' -----[ Initialization ]-------------------------------------------------- Reset: LEDsDirs = %00111111 ' make LEDs outputs

Page 52: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

49

' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Get_Random ' get random number/tone FREQOUT Speaker, 35 */ TAdj, tone */ FAdj ' sound the tone PAUSE 100 BUTTON PlayBtn, 0, 255, 10, swData, 1, Spin ' check for play LOOP Spin: LEDs = %00111111 ' simulate machine reset PAUSE 750 LEDs = %00000000 PAUSE 500 delay = 75 ' initialize delay FOR spin1 = 1 TO 25 ' spin the wheel GOSUB Get_Random ' get random number FREQOUT Speaker, 25 */ TAdj, 425 */ FAdj ' wheel click PAUSE delay ' pause between clicks delay = delay */ $0119 ' multiply delay by 1.1 NEXT IF (pattern = %00111111) THEN ' if all lit, you win FOR spin1 = 1 TO 5 FOR spin2 = 0 TO 3 LOOKUP spin2, [$00, $0C, $12, $21], LEDs LOOKUP spin2, [665, 795, 995, 1320], tone FREQOUT Speaker, 35 */ TAdj, tone */ FAdj PAUSE 65 NEXT NEXT ELSE FREQOUT Speaker, 1000 */ TAdj, 330 */ FAdj ' otherwise, groan... ENDIF Clear_Game: LEDs = %00000000 ' clear LEDs PAUSE 1000 GOTO Main ' do it again ' -----[ Subroutines ]----------------------------------------------------- Get_Random: RANDOM rndVal ' get pseudo-random number tone = rndVal & $7FF ' keep in reasonable range pattern = rndVal & %00111111 ' mask out unused bits LEDs = pattern ' show the pattern RETURN

Page 53: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

50

幕後 這個程式有個關鍵的問題是如何利用虛擬隨機 RANDOM 來增進更多隨機性。這樣做可以增加更多的”人情味”。 程式在 Main 裡面等待,上面叫做 Get_Random 的迴圈創造了一個虛擬的隨機值,喇叭發出一個音而且在 LED 燈上變成新的部份。當回到迴圈時,當按鍵被按下時會有聲音提示。而程式將會一直在迴圈中直到我們再一次按按鈕。 BUTTON 指令是用來做 debounce 的輸入。在這裡按鍵被按下的時間變化在程式中是隨機的(在此期間 RANDOM 持續呼叫,因為數值一直跳動)。當按鍵被按下時,LED 燈就亮了並且清除模擬遊戲的重置。然後 FOR-NEXT 迴圈被用來模擬吃角子老虎機的動作,對於每一卷,產生”敲”的聲音並修改敲擊間的延遲時間(減少 10%)來模擬自然下降(變慢)的輪子。 註:當按下按鈕時,表面上只按了一下。但是訊號的傳遞並不是很單純的由’1’直接跳到’0’。當我們按下按鈕後,訊號會在高低電位之間彈跳(bounce)。則電路所收到的訊號可能會像 111110110110000000,會和我們所預期的 111111111000000000不同。如此一來,雖然我們只按了一下按鈕,電路可能會解讀成按了好幾下按鈕。debounce 的目的就是為了要除去訊號在高低電位之間彈跳所造成的不正確輸入。 如果所有 LED 燈在 後旋轉時全亮了,程式會發出一些光和音樂來慶祝我們的好運。這部份是在回到程式 上面部份時用 LOOKUP 來發出預先設定好的燈光及音樂。如果任合 LED 燈沒亮,一個長鳴聲會從喇叭發出然後遊戲將會重新開始。 更進一步 你可以修改程式來讓少於 6 顆 LED 燈就能贏嗎? 要如何做到? 就像一位專家編寫程式碼

Page 54: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

51

要代替等待實際的勝利,我們可以透過插入下列程式碼來讓遊戲贏時會響:

pattern = %00111111

在前面測試樣版位元的章節。這是是一個實用的方法來微調慶祝的動作-只要確定在交出這個程式前先刪除這個程式碼。在一些程式中我們可能有一些部份要用來測試,或者我們需要可以把測試馬打開或關閉,插入一個條件編譯區將有利移除和恢復程式碼。

Page 55: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

52

我們可以用#DEFINE來創造一個條件常數。 #DEFINE _TestMode = 1

當_TestMode被定義為1,嵌套到#IF-#THEN內的程式碼將會被執行,否則他將不會被執行甚至是編譯或下載到BASIC Stamp。

#IF _TestMode #THEN pattern = %00111111 #ENDIF

請注意,能像前面所示範的條件編譯區塊會增將程式的大小-如果你要寫一個龐大的程式你應該在一開始就留有他們的空間以免在你需要用它時超過記憶體。

Page 56: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

53

實驗#7:照明控制器 實驗的目的是創造一個小型照明控制器,適合在假日顯示或戶外的裝飾。在此輸出電路只用到 LED 燈(相關可以參考 Matt Gilliland’s Microcontroller Application Cookbook)。 查一查:必須要知道的 PBASIC 元素

DATA // (模數運算子 modulus operator) ON-GOSUB READ

建立電路

Page 57: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

54

1.用白電線連接BASIC Stamp的P0到P5到LED燈0到5。

2.插入一個0.1μF(標記104)電容到插座C15和C16。 3.用白電線連接插座A16到BASIC Stamp P6。 4.用黑電線連接插座A15到Vss(接地)軌道。 5.用白電線連接插座B16到10K可變電阻中間的部分。 6.用黑電線連接Vss(接地)軌道到10K可變電阻底部的地方。

程式: SW21-EX07-Light_Show.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Runs a small, multi-mode light show controller using six outputs (runs ' on LEDs, but with proper interfacing could run incandescent lamps). ' This program will require modifications (to the constants LoSpeed and ' Scale) when running on the BS2Sx, BS2p, or BS2px. ' -----[ I/O Definitions ]------------------------------------------------- Lights VAR OUTL ' light control outputs LightsDirs VAR DIRL ' DIRS for lights outputs Speed PIN 6 ' speed control Pot input LtMode PIN 7 ' mode select input ' -----[ Constants ]------------------------------------------------------- LoSpeed CON 10 ' low end of POT reading Scale CON $0163 ' 1.3868 with */ ' -----[ Variables ]------------------------------------------------------- rawSpd VAR Word ' speed input from POT delay VAR Word ' time between patterns btnVar VAR Byte ' workspace for BUTTON mode VAR Byte ' selected mode offset VAR Byte ' offset into patterns rndVal VAR Word ' workspace for RANDOM

Page 58: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

55

' -----[ EEPROM Data ]----------------------------------------------------- SeqA DATA %000001, %000010, %000100, %001000, %010000 DATA %100000 SeqB DATA %100000, %010000, %001000, %000100, %000010 DATA %000001, %000010, %000100, %001000, %010000 SeqC DATA %000000, %001100, %010010, %100001 SeqD DATA %100100, %010010, %001001 SeqE DATA %0 AMax CON SeqB - SeqA ' calculate length BMax CON SeqC - SeqB CMax CON SeqD - SeqC DMax CON SeqE - SeqD ' -----[ Initialization ]-------------------------------------------------- Reset: LightsDirs = %00111111 ' make outputs ' -----[ Program Code ]---------------------------------------------------- Main: GOSUB Read_Speed ' read speed pot delay = (rawSpd - LoSpeed) */ Scale + 50 ' calc delay (50-1000 ms) PAUSE delay ' wait between patterns Switch_Check: BUTTON LtMode, 0, 255, 0, btnVar, 0, Show ' new mode? mode = mode + 1 // 5 ' yes, update mode var Show: ON mode GOSUB ModeA, ModeB, ModeC, ModeD, ModeE GOTO Main ' -----[ Subroutines ]----------------------------------------------------- Read_Speed: HIGH Speed ' charge cap PAUSE 1 ' for 1 millisecond RCTIME Speed, 1, rawSpd ' read the Pot RETURN ModeA: offset = offset + 1 // AMax ' update offset (0 - 5) READ (SeqA + offset), Lights ' output new light pattern

Page 59: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

56

RETURN ModeB: offset = offset + 1 // BMax READ (SeqB + offset), Lights RETURN ModeC: offset = offset + 1 // CMax READ (SeqC + offset), Lights RETURN ModeD: offset = offset + 1 // DMax READ (SeqD + offset), Lights RETURN ModeE: RANDOM rndVal ' get random number Lights = rndVal & %00111111 ' light random channels

幕後 總體來說,程式比第一次出現時簡單。程式的主體是一個迴圈。跑完主要迴圈的時間控制在可變電阻的位置上。RCTIME 是用來讀取可變電阻的值, 大值是 695 而

小值是 10。我們要做的是將 10 到 695 轉換成 50 到 1000。 這個過程其實很簡單:將需要的輸出範圍(950)除以輸入的範園(685)會得到一個1.3868 的比例係數。這個係數的轉換是用*/乘以 256(355 或$0163)。在應用中可變電阻比較低的值減去原始的輸入值,比例係數就出來了,然後 小的輸出值加上50。這個就是大家所熟悉的 y=mx+b 方程式。 在 Switch_Check 的程式碼中可以看到按鈕是否被按下。如果是,則 mode 變數增加(增加 1)。模數運算子(//)是用來保持 mode 的範圍在 0 到 4。因為模數運算子是往返在整數除法的餘數中。由於任何數字除以自己本身會讓餘數得到 0,用模數運算子將可以讓 mode 的數值往返於 4 到 0。

Page 60: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

57

後要介紹主要迴圈的元素叫做Show。這個程式碼用ON-GOSUB來呼叫將要輸出由mode來決定的亮燈排序動作的程式碼。從Mode A到D是類似的,從BASIC Stamp的EEPROM(儲存在DATA中)。Mode E的輸出是隨機發光的模式。 來看看ModeA裡面的程式碼。第一件發生的事發生在變數;offset被用在”纏繞(wrap-around)”技巧於模組運算子上。變數offset被加在一開始指定亮燈組合上的位置且正確的亮燈位置會被READ從EEPROM讀取。要注意的是每一種組合的DATA會被標記(SeqA、 SeqB…等等)。每一個標籤被轉換成排序一開始位址的常數。每一個排序的長度用這些常數來被計算。使用這個技巧,亮燈的模式不用靠操作程式碼Show就可以被更新(延長或縮短)。ModeE非常簡單,用RANDOM函數在每次經過主要迴圈時輸出新的模式。

更進一步

添加一個亮燈模式。程式的哪個部份是需要修改來達到目的?

就像一位專家編寫程式碼

模數運算子(//)是非常實用的,但是對初學者而言因為它的”神秘”而迴避它。其實他的操作真的非常簡單:他回傳了一個餘數。而他在現實中代表的意義就是在這模式下任何數值的範圍將只會落在0到該數值減一。

初學者通常會這樣寫: idx = idx + 1 IF (idx = 5) THEN idx = 0 ENDIF

Page 61: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

58

專家會把這段程式碼換成:

idx = idx + 1 // 5 但是如果我們希望到其他地方,那就是從 0 到其他數字來包圍?

idx = idx - 1 IF (idx = 0) THEN idx = 4 ENDIF

這當然是可行的。用這個: idx = idx + 4 // 5

你看到發生什麼事了?我們在排序中增加的元素中(5)減去 idx;他的影響是當模數被用來移除所有結果的地方,我們 終減去 idx。 這是一個很方便的竅門-讓數值能保持在你要的範圍。

Page 62: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

59

建立你自己的電路

隨著從前面的實驗獲取的經驗你已經準備好來組合沒有特別指示的佈線。不用緊張,你可以做到的。這些項目是非常簡單的,你會發現這些電路都跟你以前做過的差不多,而我們注重的是使用新的程式碼技巧。

慢慢來並在打開電源前仔細檢查你所連接的每條線路。請記住 好在實驗設定I/O

界面前先清除BASIC Stamp記憶體內的資料,我們可以先下載一段非常簡單的程式: ' {$STAMP BS2} Main: DEBUG "The BASIC Stamp is ready." END

準備好享受更多的樂趣了嗎?你應該知道你將自己開始設計你的BASIC Stamp項目及實驗。

好,那讓我們繼續來看七段顯示器。

Page 63: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

60

Page 64: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

61

使用七段顯示器

當你看看四周圍的設備,你會看到不同形狀、大小和顏色的LED燈。早期LED製造商發現可以把LED包裝成七個線性-樣子像是8的形狀,這樣就可以顯示出任何十進制的數字,甚至是一些字母。我們把這個稱作七段顯示器。

為了簡化佈線,七段顯示器擁有一個共同的內部接點;在實驗版上的LED燈是相連的-共陰極,這代表顯示器上LED燈的陰極是連接在一起的而且接點必須是在low的地方(連接在Vss)才能亮起。下面的圖顯示實驗板上共陰極的LED顯示器接點跟限流電阻。

要注意的是實驗板上總共有五個共陰極的七段顯示器,在七段顯示器中被標註為 A的線段被連接在 A 段 LED 上。

在接下來的實驗中,我們將學習如何善加利用七段顯示器。

Page 65: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

62

實驗#8:單一數位計數器 實驗的目的是要藉由創造一個簡單的單一數位十進位計數器來學習使用七段顯示器。 建立電路

程式: SW21-EX08-7-Seg_Counter.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Displays decimal digits (0 - 9) on a 7-Segment display connected to ' P0-P7. This program will work, unmodified, on any BS2-family module. ' -----[ I/O Definitions ]------------------------------------------------- Segs VAR OUTL ' Segments on P0 - P7 SegsDirs VAR DIRL ' DIRS for segments

Page 66: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

63

' -----[ Variables ]------------------------------------------------------- idx VAR Nib ' counter variable ' -----[ EEPROM Data ]----------------------------------------------------- ' .GFEDCBA ' -------- Digit0 DATA %00111111 Digit1 DATA %00000110 Digit2 DATA %01011011 Digit3 DATA %01001111 Digit4 DATA %01100110 Digit5 DATA %01101101 Digit6 DATA %01111101 Digit7 DATA %00000111 Digit8 DATA %01111111 Digit9 DATA %01100111 ' -----[ Initialization ]-------------------------------------------------- Reset: SegsDirs = %01111111 ' make outputs for LEDs ' -----[ Program Code ]---------------------------------------------------- Main: FOR idx = 0 TO 9 ' loop through digits READ (Digit0 + idx), Segs ' move pattern to display PAUSE 1000 NEXT GOTO Main

幕後 這個實驗和前面的 Light_Show 程式非常相似:從 EEPROM 讀取模式和直接轉移到LED 上。在程式中傳送特定的樣式到七段顯示器以顯示 0 到 9。 為了證明五個模塊有線段連接在一起(且分別經過 DP 連接 A 的末端),移動 Vss 接點從 DIGIT 0 到 DIGIT 4。看看發生什麼事?

Page 67: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

64

更進一步 更新程式來創造一個十六進位的單一數位計數器。使用下面的樣式來顯示十六進位的數字。

就像一位專家編寫程式碼 請注意用來詳列標籤名稱來儲存七段樣式的 DATA 表且樣板被放置在接下來的指令中。透過儲存在 EEPROM 中的線段資訊來代替常數,可以大大簡化顯示轉換來的樣板。 如果我們選擇用常數來儲存樣式,我們就必須用下面的程式碼來做轉換:

LOOKUP idx, [Digit0, Digit1, Digit2, Digit3, Digit4, Digit5, Digit6, Digit7, Digit8, Digit9], Segs

如你所見,用 READ 看起來是整潔的。在大部分的程式中,如果同樣的數值在程式中被用於多於一個地方時,儲存在 DATA 表中的數值將可以簡化程式碼和節省儲存程式的空間。

Page 68: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

65

實驗#9:數位骰子 在實驗#6 時我們創造了一個簡單的遊戲;這次我們將做一個簡單的數位骰子來讓我們能在玩遊戲時能使用。 建立電路 增加這個按鈕到實驗#8 的電路上。

程式: SW21-EX09-Roller.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program combines a 7-segment display and pushbutton input to form ' a digital die that displays numbers 1 - 6. This program will work, ' unmodified, on any BS2-family module. ' -----[ I/O Definitions ]------------------------------------------------- Segs VAR OUTL ' Segments on P0 - P7 SegsDirs VAR DIRL ' DIRS for segments RollBtn PIN 15 ' roll button for die ' -----[ Variables ]-------------------------------------------------------

Page 69: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

66

rndVal VAR Word ' random number swData VAR Byte ' workspace for BUTTON dieVal VAR Nib ' new die value spinPos VAR Nib ' spinner position doSpin VAR Nib ' spinner update control ' -----[ EEPROM Data ]----------------------------------------------------- ' .GFEDCBA ' -------- Digit0 DATA %00111111 ' digit patterns Digit1 DATA %00000110 Digit2 DATA %01011011 Digit3 DATA %01001111 Digit4 DATA %01100110 Digit5 DATA %01101101 Digit6 DATA %01111101 Digit7 DATA %00000111 Digit8 DATA %01111111 Digit9 DATA %01100111 ' .GFEDCBA ' -------- Bug0 DATA %00000001 ' animated "bug" frames Bug1 DATA %00000010 Bug2 DATA %00000100 Bug3 DATA %00001000 Bug4 DATA %00010000 Bug5 DATA %00100000 BugLen CON Bug5 - Bug0 + 1 ' calc animation length ' -----[ Initialization ]-------------------------------------------------- Reset: SegsDirs = %01111111 ' make outputs for LEDs ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Tumble_Die ' shake the die PAUSE 5 ' loop pad ' check for button press BUTTON RollBtn, 0, 255, 5, swData, 1, Show_Die LOOP

Page 70: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

67

Show_Die: READ (Digit0 + dieVal), Segs ' transfer die to segments PAUSE 3000 ' hold for viewing GOTO Main ' start again ' -----[ Subroutines ]----------------------------------------------------- Tumble_Die: RANDOM rndVal ' stir random value dieVal = (rndVal // 6) + 1 ' get die val, 1 - 6 doSpin = (doSpin + 1) // 10 ' update spin timer IF (doSpin = 0) THEN ' time for update spinPos = (spinPos + 1) // BugLen ' yes, point to next pos READ (Bug0 + spinPos), Segs ' output to segments ENDIF RETURN

幕後 這個程式主要的部份是我們已經完成的而且應該很容易去了解。我們要做的是增加一些創意性的程式來使視覺上更加有趣。 要注意的是 Tumble_Die 子函式其實做了很多事情。第一件事是這個函式是啟動隨機數產生器。由於主要的迴圈大概每毫五秒呼叫這個子函式,所以應該可以給我們很好的隨機結果。 從隨機數中骰子的數字就出現了。記得我們學過的模數運算子嗎?它讓數值永遠保持在 0 和除數之間。因為骰子有六面,所以我們隨機數除以 6 並採用模數。結果會出現 0 到 5。。加 1 以後就可以修正成介於 1 到 6 了。

後。同樣的子程式要負責更新動畫中的”蟲”來代表現在正在搖骰子。如果我們透過這個子函式來更新畫面的話,顯示出來的效果就像一隻閃爍的動物-我們需要在每十個畫面後讓他漸漸慢下來(每個圖片間隔超過 50 毫秒)。這個可以用計時器的指令doSpin 來完成。doSpin 的值每次會一直增加然後除以 10(用//);當模數的結果是 0 就會更新動畫的”畫面”。這樣的延遲使我們可以看的更清楚並且創造出更誘人的畫面。

Page 71: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

68

更進一步 更新程式來讓動畫上的蟲跑來跑去像下面圖案一樣。

Page 72: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

69

實驗#10:數位時鐘 實驗的目的是用四個七段顯示器來創造一個簡單的數位時鐘。在實驗中我們將會觀察到多重顯示的過程和發現可以讓我們知道何時輸入已經改變成指定的狀態。

查一查:必須要知道的 PBASIC 元素

• DIG (數值運算子 digit operator)

建立電路

Page 73: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

70

程式: SW21-EX10-Clock.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program takes an external 1 Hz signal from the pulse generator and ' synthesizes a simple clock/timer. This code will run, unmodified, on and ' BS2-family module. ' -----[ I/O Definitions ]------------------------------------------------- Segs VAR OUTL ' Segments on P0 - P7 Digs VAR OUTC ' Digit control pins Tic PIN 15 ' 1 Hz input ' -----[ Constants ]------------------------------------------------------- Blank CON %00000000 ' all segments off DecPnt CON %10000000 ' decimal point on IsHigh CON 1 IsLow CON 0 ' -----[ Variables ]------------------------------------------------------- nTic VAR Bit ' new tic input oTic VAR Bit ' old tic value xTic VAR Bit ' change (1 when 0 -> 1) secs VAR Word ' seconds time VAR Word ' formatted time theDig VAR Nib ' current display digit ' -----[ EEPROM Data ]----------------------------------------------------- ' .GFEDCBA ' -------- Digit0 DATA %00111111 ' digit patterns Digit1 DATA %00000110 Digit2 DATA %01011011 Digit3 DATA %01001111 Digit4 DATA %01100110 Digit5 DATA %01101101 Digit6 DATA %01111101 Digit7 DATA %00000111

Page 74: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

71

Digit8 DATA %01111111 Digit9 DATA %01100111 DigSel DATA %1110 ' digit 0 active DATA %1101 ' digit 1 active DATA %1011 ' digit 2 active DATA %0111 ' digit 3 active ' -----[ Initialization ]-------------------------------------------------- Reset: Digs = %1111 ' all off DIRS = $0FFF ' make segs & digs outputs ' -----[ Program Code ]---------------------------------------------------- Main: DO WHILE (Tic = IsHigh) ' wait during high cycle GOSUB Show_Clock LOOP DO WHILE (Tic = IsLow) ' wait during low cycle GOSUB Show_Clock LOOP secs = secs + 1 // 3600 ' update current time GOTO Main ' -----[ Subroutines ]----------------------------------------------------- Show_Clock: time = (secs / 60) * 100 ' get mins, move to 100s time = time + (secs // 60) ' add seconds in 1s/10s Segs = Blank ' clear display READ (DigSel + theDig), Digs ' select digit READ (Digit0 + (time DIG theDig)), Segs ' move digit pattern to segs IF (theDig = 2) THEN Segs = Segs | DecPnt ' add decimal point ENDIF theDig = theDig + 1 // 4 ' update digit pointer RETURN

幕後 前兩個七段顯示器的實驗用只用到一個數字。這個實驗用到四個。這樣就出現新的問題;由於顯示器的陽極線段都是在一起的,我們一次只能驅動一個。我們把七段顯示器擺放在陽極上然後啟動所需要的數字(讓陰極轉為 Low)。

Page 75: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

72

但是如果我們能一次看到四個這樣是 好的。雖然我不能做到,但是如果我們切換的速度夠快,我們就能欺騙眼睛讓他以為是同時發生的。 人的眼睛有種特性叫做視覺暫留(POV),這種特性會導致眼睛會把影像保持住一小段時間,越明亮的圖像在我們眼睛中停留的時間就越長。視覺暫留讓我們在閃過依張照片後看到一道閃光。我們可以用 POV 的特性來讓四個數字在正確的位置上快速的循環播放。如果這個循環夠快的話,我們眼睛因為視覺暫留的原因讓我們會以為四個數字是同時出現。這個就叫做多工技術(multiplexing)。 多工技術是一個分享傳輸線的程序,在這裡,是代表七段顯示器上的線段。如果我們沒有使用多工技術,我們就會需要 28 條輸出的線來控制四個七段顯示器。這樣比 BASIC Stamp 能用的還多了 12 條。老實說多工技術在 PBASIC 裡不是非常實用,但是它可以讓我們了解一個程序,而當我們在需要多工技術時(請看實驗#31),我們可以得到我們期望的結果。 在程式中主要的迴圈裡分為三個階段:

當產生器輸入為 high 時顯示正確的時間

當產生器輸入為 low 時顯示正確的時間

更新秒數計數器 請再注意一次如何使用模數運算子(//)來讓秒數的範圍在 0 到 3599 之間(這個數字代表一個小時有幾秒)。 而真正在實驗中做工的是在 Show_Clock 子函式中。其目的是要將原本的秒數轉換成時間的格式(MMSS)然後更新成正確的數字。由於這個函式每次只能顯示一個數字,所以他會被呼叫的很頻繁,否則看起來會閃爍。就如我們先前所看到的,在程式中的主要迴圈中並不會,直到信號產生器輸入改變。

Page 76: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

73

時鐘的顯示是靠變數 time 產生的分鐘值(secs/60)放到千位數和百位數的列中。其餘的秒數(secs//60)被添加到 time,把它們放置在個位數和十位數的列中。這邊是他們如何做數學的轉換: 例如:754 秒 754 / 60 = 12 12 x 100 = 1200 (time = 1200) 754 // 60 = 34 1200 + 34 = 1234 (time = 1234; 12 分 and 34 秒) 現在用 time 顯示出數值已經準備好了,線段會在下次更新前清除。清除線段上的數值可以讓顯示的效果更清晰。如果沒有這樣做,舊的線段數值就會在顯示器上造成鬼影的現象。一但顯示器已經清除掉所選擇的數字後線段就會繼續更新。例如: 725 DIG 1 = 2 請記住 右邊的數字是 digit 0。透過更新變數 theDig,我們用它來當作控制陰極列的指標以及從 time 讓數字偏移好讓我們閱讀。 實驗版上的顯示在時鐘中常見的冒號(:),所以我們在 digit 2 後放一個小數點。當theDig 沒有指向這個數字時,小數點就不會發亮。 後一步就是下次呼叫這個子函式時更新 theDig。 更進一步 更新程式來從單一產生器產生 10Hz 輸入和在每個轉換的地方閃爍小數點。(請看SW21-EX10-Clock-DP_Blink.BS2 上的列表)。

Page 77: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

74

Main: DO WHILE (Tic = IsHigh) ' wait during high cycle GOSUB Show_Clock LOOP DO WHILE (Tic = IsLow) ' wait during low cycle GOSUB Show_Clock LOOP tenths = tenths + 1 // 36000 ' update time @ 10 Hz GOTO Main ' -----[ Subroutines ]--------------------------------------------- Show_Clock: time = (tenths / 600) * 100 ' get mins, move to 100s time = time + (tenths // 600 / 10) ' add seconds in 1s/10s Segs = Blank ' clear display READ (DigSel + theDig), Digs ' select digit READ (Digit0 + (time DIG theDig)), Segs ' move digit pattern to segs IF (theDig = 2) THEN Segs.BIT7 = tenths.BIT0 ' blink decimal point ENDIF theDig = theDig + 1 // 4 ' update digit pointer RETURN

Page 78: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

75

使用 Character LCD 模組

雖然 LED 燈和七段顯示器是個不錯的輸出介面,但是對於使用者會需要擁有更多更複雜的訊息給他們。當然, 好的就是電腦所使用的螢幕,但是他太大了、太貴了而且不符合微處理機的狀況。Character LCD 模組也許是個不錯的方案。這個便宜的模組只需利用少許的 I/O 介面及從 BASIC Stamp 得到少許的電力就能讓文字和數字的輸出到螢幕上。由於引進了 BS2p,character LCD 已經內建於 PBASIC 2.0及 2.5 版內。儘管如此,我們仍然可以用 BS2 來驅動這個顯示器並且在接下來的實驗會說明如何使用。 Character LCD 模組提供很多種配置:常見的一線、二線、四線。常見的顯示器有16-或 20-字元的。

The datasheet for the parallel LCD (2 lines x 16 characters) included in the

StampWorks Kit is available for download from www.parallax.com.

LCD 模組利用一個 14-pin 的 IDC 接頭(X1)連接到實驗板上。接頭是有方向性的,以防止插相反。

Graphic LCD 只能用繪圖的方式將資料顯示於 LCD,所以必須先將要顯示文字的圖形依 LCD 所需的格式事先存起來,如一個 16*15 的中文字便需儲存 30byte 的資料,將此 30byte 的資料依序填入 LCD 即可顯示對應文字圖形。 Character LCD 則是已經有內建文字圖形(通常只有英文字母大小寫、阿拉伯數

字、標點符號),只要輸入對應的 ASCII 碼,LCD 便會將該字的圖形顯示於 LCD 一般來說,Character LCD 結構較為簡單,面板較小,功能非常有限。Graphic

LCD 一般而言都能夠同時顯示文字和圖形,功能較 Character LCD 強大許多。

初始化

Page 79: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

76

Character LCD 在顯示出文字前初始化。初始化 LCD 是依照 Hitachi HD44780 控製器的規範來做。這個 Hitachi 控制器是 主流的而且很多控制器都相容於他。如果有疑問,請務必下載並檢查 LCD 的驅動文件。

Page 80: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

77

操作模式 關於操作 character LCD 有兩種基本的模式:把字寫在 LCD 上以及傳送指令到 LCD上(例如清除螢幕)。當傳送一個文字時,RS 傳輸線會變成高電位,而被傳送的資料會被解釋成顯示在正確的游標位置上。發送的程式碼通常是 ASCII 碼來顯示。一些在 LCD ROM 裡的非 ASCII 字元同樣也可以被使用,使用者可以自訂八個自定字元(儲存的地方稱作 CGRAM)。 在傳送資料前,指令透過 RS 傳輸線為低電位會被傳送到 LCD 上。一些標準的指令可以用來管理和操作 LCD 的顯示。 Clear $01 清除 LCD 並移動游標到第一行的第一個位置 Home $02 移動游標到第一行的第一個位置 Cusor Left $10 移動游標到左邊 Cusor Right $14 移動游標到右邊 Display Left $18 整個顯示往左 Display Right $1C 整個顯示往右

連接 LCD 螢幕 標準的平行式 LCD(parallel LCD)在電線後端擁有一個 14-pin 的 IDC 連接頭。這個連接頭是有方向性的這樣才能確保正確的插到實驗板上。只要對齊輕輕的插到 X1的插座上就可以了。

Page 81: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

78

實驗#11:基本的 LCD 說明 這個實驗要說明 character LCD 內部和控制方法。

查一查:必須要知道的 PBASIC 元素

• PULSOUT • HIGHNIB, LOWNIB • ^ (Exclusive Or 互斥運算子) • #ERROR

建立電路

注意:在實驗板上,X2 在下邊的連接頭拆分 LCD 數據匯流排到左右兩邊。

Page 82: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

79

請確定插入到 DB4 到 DB7 的電線是插在連接頭右邊如下所示:

程式: SW21-EX11-LCD_Demo.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates essential character LCD control. ' ' The connections for this program conform to the BS2p-family LCDCMD, ' LCDIN, and LCDOUT instructions. Use this program for the BS2, BS2e, ' or BS2sx. There is a separate program for the BS2p, BS2pe, and BS2px. ' -----[ I/O Definitions ]------------------------------------------------- E PIN 1 ' Enable pin RW PIN 2 ' Read/Write RS CON 3 ' Register Select LcdBus VAR OUTB ' 4-bit LCD data bus ' -----[ Constants ]------------------------------------------------------- LcdCls CON $01 ' clear the LCD LcdHome CON $02 ' move cursor home LcdCrsrL CON $10 ' move cursor left LcdCrsrR CON $14 ' move cursor right LcdDispL CON $18 ' shift chars left LcdDispR CON $1C ' shift chars right LcdDDRam CON $80 ' Display Data RAM control

Page 83: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

80

LcdCGRam CON $40 ' Character Generator RAM LcdLine1 CON $80 ' DDRAM address of line 1 LcdLine2 CON $C0 ' DDRAM address of line 2 #DEFINE LcdReady = ($STAMP >= BS2P) ' -----[ Variables ]------------------------------------------------------- char VAR Byte ' character sent to LCD idx VAR Byte ' loop counter ' -----[ EEPROM Data ]----------------------------------------------------- Msg DATA "The BASIC STAMP!", 0 ' store message ' -----[ Initialization ]-------------------------------------------------- Reset: #IF ($STAMP >= BS2P) #THEN #ERROR "Please use BS2p version: SW21-EX11-LCD_Demo.BSP" #ENDIF DIRL = %11111110 ' setup pins for LCD PAUSE 100 ' let the LCD settle Lcd_Setup: LcdBus = %0011 ' 8-bit mode PULSOUT E, 3 PAUSE 5 PULSOUT E, 3 PULSOUT E, 3 LcdBus = %0010 ' 4-bit mode PULSOUT E, 1 char = %00001100 ' disp on, no crsr or blink GOSUB LCD_Cmd char = %00000110 ' inc crsr, no disp shift GOSUB LCD_Cmd ' -----[ Program Code ]---------------------------------------------------- Main: char = LcdCls ' clear the LCD GOSUB LCD_Cmd PAUSE 500 idx = Msg ' get EE address of message

Page 84: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

81

Write_Message: DO READ idx, char ' get character from EE IF (char = 0) THEN EXIT ' if 0, message is complete GOSUB LCD_Out ' write the character idx = idx + 1 ' point to next character LOOP PAUSE 2000 ' wait 2 seconds Cursor_Demo: char = LcdHome ' move the cursor home GOSUB LCD_Cmd char = %00001110 ' turn the cursor on GOSUB LCD_Cmd PAUSE 500 char = LcdCrsrR FOR idx = 1 TO 15 ' move cursor l-to-r GOSUB LCD_Cmd PAUSE 150 NEXT FOR idx = 14 TO 0 ' move cursor r-to-l by char = LcdDDRam + idx ' moving to a specific GOSUB LCD_Cmd ' column PAUSE 150 NEXT char = %00001101 ' cursor off, blink on GOSUB LCD_Cmd PAUSE 2000 char = %00001100 ' blink off GOSUB LCD_Cmd Flash_Demo: FOR idx = 1 TO 10 ' flash display char = char ^ %00000100 ' toggle display bit GOSUB LCD_Cmd PAUSE 250 NEXT PAUSE 1000 Shift_Demo: FOR idx = 1 TO 16 ' shift display char = LcdDispR GOSUB LCD_Cmd PAUSE 100 NEXT PAUSE 1000

Page 85: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

82

FOR idx = 1 TO 16 ' shift display back char = LcdDispL GOSUB LCD_Cmd PAUSE 100 NEXT PAUSE 1000 GOTO Main ' do it all over ' -----[ Subroutines ]----------------------------------------------------- LCD_Cmd: LOW RS ' enter command mode LCD_Out: LcdBus = char.HIGHNIB ' output high nibble PULSOUT E, 3 ' strobe the Enable line LcdBus = char.LOWNIB ' output low nibble PULSOUT E, 3 HIGH RS ' return to character mode RETURN

幕後

這是一個非常簡單的程式來說明 character LCD 的重要功能。LCD 初始化是依照Hitachi HD44780 控製器的規格來使用 4-bit 模式。這個模式能讓 BASIC Stamp 以

少的 I/O 線路來控制 LCD。雖然可以用八條線路去連接並控制 LCD,但是這並不會出現比較好的表現。對大部分的項目而言是保護 I/O。 這個基本的初始化適用於大部分的裝置:

顯示器是打開的

下線游標是關閉的

閃爍游標是關閉的

游標在每次寫後自動增加

顯示器畫面不會移動

Page 86: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

83

請注意這個程式只初始化 LCD 一行而已,即使 LCD 在實體上有兩行。請看往後的實驗來初始化多行的 LCD。在 LCD 匯流排上使用 4 data bits,兩個負責必須在一個循環中送出位元到 LCD 上。BASIC Stamp 的 HIGHNIB 和 LOWNIB 變數修改器會讓這一個過程變的很容易。每一個半字節(nibble)都被 PULSOUT 用脈波在E(enable)線輸出高電位鎖在 LCD 上。 程式主要的部份是一開始先清除螢幕並且顯示已經儲存在 DATA 的訊息。這個儲存在 EEPROM 訊息的技巧非常實用而且讓程式更容易去更新。在程式中字元匯一直被寫入直到遇到一個 0。這個方法讓我們改變字串的長度而不用擔心迴圈如何設定。隨著訊息被顯示出來,游標的位置回到 home(第一行的第一個位置)和打開(一個下線游標會出現)。 游標在 LCD 上被送回跟去用了兩種不同的方法。第一個是使用 cursor-right 指令。移動游標往右是用手動的方式移動游標到指定的位置。手動游標位置需要許多 LCD的程式來讓資訊整齊的排列在螢幕裡。 當游標回到初始位置(home)時,游標會被關閉而變成閃爍。閃爍是讓游標的位置上由字母及一個黑方塊交替出現。這是個能讓人注意的好方法。另外一種引人注意的方法是閃爍整個螢幕。這個可以用觸發螢幕開關的位元來達成。互斥(Exclusive OR) 運算子(^)可以簡單的做位元觸發,任何位元被 1 做 XOR 運算後都會變成相反的結果:

1 ^ 1 = 0 0 ^ 1 = 1

使用顯示變動指令,整個顯示推移到螢幕外(off-screen)的右邊,再返回。這說明了可見的螢幕其實是一個視窗放到 LCD 的顯示記憶體內(被稱作 DDRAM)。一種添增記憶體的方法是放到螢幕外和推移訊息到可以看到的螢幕上。

Page 87: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

84

就像一位專家編寫程式碼 在可能的情況下,儘量使用 PBASIC 固定內建的指令而不是用手寫編碼。例如在BS2p 家族裡已經有處理 LCD 模組的程式,所以那些用標準 BS2 版傳送的程式碼其實是不需要占用程式空間的。我們可以頻繁的利用條件編譯寫程式,並運行在任何 BS2 型態的微控制器。 從 LCD 程式中使用下列定義:

#DEFINE _LcdReady = ($STAMP >= BS2P)

我們可以在 BS2p 家族中編寫使用在 LCD 指令上的程式碼。現在介紹當 BS2p 家族模組安裝後,LCD_Cmd 和 LCD_Out 子程式如何更新來減少程式對記憶體的需求:

LCD_Cmd: #IF _LcdReady #THEN LCDCMD E, char ' send command to LCD RETURN ' return to program #ELSE LOW RS ' enter command mode #ENDIF LCD_Out: #IF _LcdReady #THEN LCDOUT E, 0, [char] #ELSE LcdBus = char.HIGHNIB ' output high nibble PULSOUT E, 3 ' strobe the Enable line LcdBus = char.LOWNIB ' output low nibble PULSOUT E, 3 HIGH RS ' return to character mode #ENDIF RETURN

請注意 LCD_Cmd 和 LCD_Out 是畫底線—這是為了防止和內建保留字 LCDCMD 及LCDOUT 相衝突。 請見 SW21-EX11-LCD_Demo-All.BS2 完整的列表。

Page 88: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

85

實驗#12:創造特定 LCD 單字

這個程式說明了如何建立訂製 LCD 符號、訂製符號動畫及初始化多行模式的 LCD。 建立電路 和實驗#11 使用同樣的電路。

程式: SW21-EX11-LCD_Demo.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates custom character creation and animation on a ' character LCD. ' ' The connections for this program conform to the BS2p-family LCDCMD, ' LCDIN, and LCDOUT instructions. Use this program for the BS2, BS2e, ' or BS2sx. There is a separate program for the BS2p, BS2pe, and BS2px. ' -----[ I/O Definitions ]------------------------------------------------- E PIN 1 ' Enable pin RW PIN 2 ' Read/Write RS CON 3 ' Register Select LcdBus VAR OUTB ' 4-bit LCD data bus ' -----[ Constants ]------------------------------------------------------- LcdCls CON $01 ' clear the LCD LcdHome CON $02 ' move cursor home LcdCrsrL CON $10 ' move cursor left LcdCrsrR CON $14 ' move cursor right LcdDispL CON $18 ' shift chars left LcdDispR CON $1C ' shift chars right LcdDDRam CON $80 ' Display Data RAM control LcdCGRam CON $40 ' Character Generator RAM LcdLine1 CON $80 ' DDRAM address of line 1 LcdLine2 CON $C0 ' DDRAM address of line 2 #DEFINE _LcdReady = ($STAMP >= BS2P)

Page 89: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

86

' -----[ Variables ]------------------------------------------------------- char VAR Byte ' character sent to LCD newChar VAR Byte idx1 VAR Byte ' loop counters idx2 VAR Nib ' -----[ EEPROM Data ]----------------------------------------------------- Msg1 DATA "THE BASIC STAMP " ' preload EE with messages Msg2 DATA " IS VERY COOL! ", 3 CC0 DATA %01110 ' mouth 0 DATA %11111 DATA %11100 DATA %11000 DATA %11100 DATA %11111 DATA %01110 DATA %00000 CC1 DATA %01110 ' mouth 1 DATA %11111 DATA %11111 DATA %11000 DATA %11111 DATA %11111 DATA %01110 DATA %00000 CC2 DATA %01110 ' mouth 2 DATA %11111 DATA %11111 DATA %11111 DATA %11111 DATA %11111 DATA %01110 DATA %00000 Smiley DATA %00000 ' smiley face DATA %01010 DATA %01010 DATA %00000 DATA %10001 DATA %01110 DATA %00110 DATA %00000

Page 90: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

87

' -----[ Initialization ]-------------------------------------------------- Reset: #IF _LcdReady #THEN #ERROR "Please use BS2p version: SW21-EX12-LCD_Chars.BSP" #ENDIF DIRL = %11111110 ' setup pins for LCD PAUSE 100 ' let the LCD settle Lcd_Setup: LcdBus = %0011 ' 8-bit mode PULSOUT E, 3 PAUSE 5 PULSOUT E, 3 PULSOUT E, 3 LcdBus = %0010 ' 4-bit mode PULSOUT E, 1 char = %00101000 ' multi-line mode GOSUB LCD_Cmd char = %00001100 ' disp on, no crsr or blink GOSUB LCD_Cmd char = %00000110 ' inc crsr, no disp shift GOSUB LCD_Cmd Download_Chars: ' download custom chars char = LcdCGRam ' point to CG RAM GOSUB LCD_Cmd ' prepare to write CG data FOR idx1 = CC0 TO (Smiley + 7) ' build 4 custom chars READ idx1, char ' get byte from EEPROM GOSUB LCD_Out ' put into LCD CG RAM NEXT ' -----[ Program Code ]---------------------------------------------------- Main: char = LcdCls ' clear the LCD GOSUB LCD_Cmd PAUSE 250 FOR idx1 = 0 TO 15 ' get message from EEPROM READ (Msg1 + idx1), char ' read a character GOSUB LCD_Out ' write it NEXT PAUSE 1000 ' wait 2 seconds Animation: FOR idx1 = 0 TO 15 ' cover 16 characters READ (Msg2 + idx1), newChar ' get new char from Msg2

Page 91: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

88

FOR idx2 = 0 TO 4 ' 5 characters in cycle char = LcdLine2 + idx1 ' set new DDRAM address GOSUB LCD_Cmd ' move cursor position LOOKUP idx2, [0, 1, 2, 1, newChar], char ' get animation "frame" GOSUB LCD_Out ' write "frame" PAUSE 100 ' animation delay NEXT NEXT PAUSE 2000 GOTO Main ' do it all over ' -----[ Subroutines ]----------------------------------------------------- LCD_Cmd: LOW RS ' enter command mode LCD_Out: LcdBus = char.HIGHNIB ' output high nibble PULSOUT E, 3 ' strobe the Enable line LcdBus = char.LOWNIB ' output low nibble PULSOUT E, 3 HIGH RS ' return to character mode RETURN

幕後 在這個程式中是要初始化多行模式的 LCD(請注意在進入 4-bit 模式後增添的線)。這樣能使兩列的 LCD 模組都能顯示訊息。隨著顯示器的初始化,定義的訂製符號就可以下載到 LCD 中。 LCD 有八個空間用來放置使用者定義的訂製符號。儲存這些符號資料的地方叫做CGRAM 而且必須在開啟電源及初始化後下載到 LCD 中(CGRAM 是揮發性記憶體,所以訂製符號會在 LCD 沒有電源時消失)。每一個訂製符號需要 8 個位元組(byte),第一個位元組在符號的 上面一條線上, 後的位元組在符號 上面的線上。第八個位元組通常是$00,因為通常游標都在符號的下方。

Page 92: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

89

標準的 LCD 字體是由 5 個位元寬及 7 個位元高所組成。你可以創造一個訂製符號到八個位元高,但是如前面所解釋的通常第八條線是保留給游標的。這裡有個訂製符號定義的範例: 液晶顯示器的標準字體為 5 位寬,高 7 位。您可以創建自定義的字符 8 位身材高大,但解釋第八行前,通常是保留給下劃線光標。下面是一個例子,自定義字符的定義:

符號的形狀是由儲存在資料位元組(data bytes)內的 0 和 1 所組成。在有 1 的位置上那個像素就會亮起,反之 0 則不會亮。 訂製符號的位元部份都被儲存在 BASIC Stamp 裡的 EEPROM 中的 DATA 指令中。為了要移動這些部分到 LCD 上,游標被移動到 CGRAM 然後每個資料位元組都被寫入。因為 LCD 已經被自增(auto-incrementing)給初始化,所以這裡不需要為每個資料位元組作定址。在符號可以被使用之前,顯示器必須靠游標回到 DDRAM 區域來回到”nornal”模式。普遍的方法是清除螢幕或讓游標回到原位。 有趣的是,當刷新顯示內容時,LCD 要從記憶體收回位元部份。在更進階的應用中,CGRAM 記憶體可以在程式要執行到不同畫面時才被更新。 程式 核心的地方就是動畫迴圈。這個程式碼從第二個訊息抓一個符號,然後對於每個在那個訊息中的每個符號,顯示這個動畫順序在想要的符號位置到 LCD 第二行上。LOOKUP 表被用來做動畫排序制定符號的循環。到了排序的 後,新的符號會顯示出來。

Page 93: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

90

就像一位專家編寫程式碼 注意程式中用 DATA 宣告所使用的二進制格式的數字。當初學者可能會認為這個方式過於繁瑣,但是專家會知道透過多辛苦一點的前製工作可以在編輯或重新定義符號時省下後段大量的時間。BASIC Stamp IDE(集成開發環境)支援各種數字格式的目的是協助每個撰寫程式的人-一但下載到 BASIC Stamp,這些數值都會被儲存在二進制格式中。

更進一步 建立你自己的訂制符號排序。更新初始化和動畫的程式碼來適用於你的訂制符號設定。

Page 94: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

91

實驗#13:讀取 LCD 記憶體 這個程式說明如何使用 LCD 的 CGRAM 空間做為外部記憶體。 查一查:必須要知道的 PBASIC 元素

• INS, INL, INH, INA - IND

建立電路 電路和實驗#11 相同

程式: SW21-EX13-LCD_Read.BSP ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates how to read data from the LCD's display RAM ' (DDRAM) or character RAM (CGRAM). ' ' The connections for this program conform to the BS2p-family LCDCMD, ' LCDIN, and LCDOUT instructions. Use this program for the BS2, BS2e, ' or BS2sx. There is a separate program for the BS2p, BS2pe, and BS2px. ' -----[ I/O Definitions ]------------------------------------------------- E PIN 1 ' Enable pin RW PIN 2 ' Read/Write RS CON 3 ' Register Select LcdDirs VAR DIRB ' bus DDR LcdBusOut VAR OUTB ' 4-bit LCD data bus LcdBusIn VAR INB ' -----[ Constants ]------------------------------------------------------- LcdCls CON $01 ' clear the LCD LcdHome CON $02 ' move cursor home LcdCrsrL CON $10 ' move cursor left LcdCrsrR CON $14 ' move cursor right LcdDispL CON $18 ' shift chars left LcdDispR CON $1C ' shift chars right

Page 95: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

92

LcdDDRam CON $80 ' Display Data RAM control LcdCGRam CON $40 ' Character Generator RAM LcdLine1 CON $80 ' DDRAM address of line 1 LcdLine2 CON $C0 ' DDRAM address of line 2 #DEFINE _LcdReady = ($STAMP >= BS2P) ' -----[ Variables ]------------------------------------------------------- char VAR Byte ' character sent to LCD idx VAR Byte ' loop counter rndVal VAR Word ' random value addr VAR Byte ' address to write/read tOut VAR Byte ' test value - out to LCD tIn VAR Byte ' test value - in from LCD temp VAR Word ' use for formatting width VAR Nib ' width of value to display ' -----[ Initialization ]-------------------------------------------------- Reset: #IF _LcdReady #THEN #ERROR "Please use BS2p version: SW21-EX13-LCD_Read.BSP" #ENDIF DIRL = %11111110 ' setup pins for LCD PAUSE 100 ' let the LCD settle Lcd_Setup: LcdBusOut = %0011 ' 8-bit mode PULSOUT E, 3 PAUSE 5 PULSOUT E, 3 PULSOUT E, 3 LcdBusOut = %0010 ' 4-bit mode PULSOUT E, 1 char = %00101000 ' multi-line mode GOSUB LCD_Cmd char = %00001100 ' disp on, no crsr or blink GOSUB LCD_Cmd char = %00000110 ' inc crsr, no disp shift GOSUB LCD_Cmd Display: char = LcdHome GOSUB LCD_Cmd PAUSE 2 FOR idx = 0 TO 15

Page 96: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

93

LOOKUP idx, ["ADDR=?? OUT:???"], char GOSUB LCD_Out NEXT char = LcdLine2 GOSUB LCD_Cmd PAUSE 2 FOR idx = 0 TO 15 LOOKUP idx, [" IN:???"], char GOSUB LCD_Out NEXT ' -----[ Program Code ]---------------------------------------------------- Main: RANDOM rndVal ' generate random number addr = rndVal.LOWBYTE & $3F ' create address (0 to 63) tOut = rndVal.HIGHBYTE ' create test value char = LcdCGRam + addr ' set CGRAM pointer GOSUB LCD_Cmd char = tOut GOSUB LCD_Out ' move the value to CGRAM PAUSE 100 char = LcdCGRam + addr ' reset CGRAM pointer GOSUB LCD_Cmd GOSUB LCD_In ' read value from LCD tIn = char ' display results char = LcdLine1 + 5 ' show address @ L1/C5 GOSUB LCD_Cmd temp = addr width = 2 GOSUB Put_Val char = LcdLine1 + 13 ' show output @ L1/C13 GOSUB LCD_cmd temp = tOut width = 3 GOSUB Put_Val char = LcdLine2 + 13 ' show output @ L2/C13 GOSUB LCD_Cmd temp = tIn width = 3 GOSUB Put_Val PAUSE 1000

Page 97: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

94

GOTO Main ' do it again ' -----[ Subroutines ]----------------------------------------------------- LCD_Cmd: LOW RS ' enter command mode LCD_Out: LcdBusOut = char.HIGHNIB ' output high nibble PULSOUT E, 3 ' strobe the Enable line LcdBusOut = char.LOWNIB ' output low nibble PULSOUT E, 3 HIGH RS ' return to character mode RETURN LCD_In: HIGH RS ' data command HIGH RW ' read LcdDirs = %0000 ' make data lines inputs HIGH E char.HIGHNIB = LcdBusIn ' get high nibble LOW E HIGH E char.LOWNIB = LcdBusIn ' get low nibble LOW E LcdDirs = %1111 ' make buss lines outputs LOW RW ' return to write mode RETURN Put_Val: FOR idx = (width - 1) TO 0 ' display digits l-to-r char = (temp DIG idx) + "0" ' convert digit to ASCII GOSUB LCD_Out ' write to LCD NEXT RETURN

幕後 這個程式說明了多工性的 BASIC Stamp 的 I/O 線路和他們可以在程式中重新配置。將程式寫到 LCD 裡的程式已經在前面兩個實驗中做過。要把資料讀回來,對應在LCD 匯流排的 BASIC Stamp 的 I/O 線路必須重新配置成輸入。這對 BASIC Stamp來說是沒有問題的。

Page 98: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

95

除了 I/O 的配置外,從 LCD 的需要讀取要用到一個額外的控制線(control line):RW。在大部分的程式中這個線可以被保持在低電位(Low)來讓訊息寫進 LCD。為了要讀取從 LCD RAM 中的訊息 RW 線要變成高電位(High)。 這個程式使用 RANDOM 函數產生一個位址以適用於 CGRAM,以及寫入一個資料位元組到 LCD。位址會因 LOWBYTE 高位元遮罩而保持在 0 到 63 的範圍內;HIGHBYTE 則是被用來將資料寫進 LCD 中。 LCD 的 CGRAM 通常是用在訂制符號圖上。對於程式而言如果不需要訂制符號,這些區域( 大到 64 bytes)可以被 BASIC Stamp 當作一個儲存的空間。在程式中如果需要少於八個訂制符號,其他剩餘的 CGRAM 仍然可以被拿來當作板外(off-board)的記憶體(每個訂制符號定義就從 CGRAM 減去 8 bytes)。 從 LCD 讀取資料和寫入是一樣的:位址被設定了且資料已經被接收了。對於這樣事情的發生,LCD 資料線(data line)必須重新配置成輸入。E(enable)線發出脈衝讓資料(一次一個半字節(nibble))可以用於 BASIC Stamp。再一次,HIGHNIB

和 LOWNIB 被用到,這次在返回讀取操作間由兩個半字節建立的單一位元組。 當要被擷取的資料準備好了,位址、輸出資料和輸入資料會被寫進 LCD。一個簡短的子函式 Put_Val 用來處理寫進數直到 LCD。要用這個程式,移動游標到所需的位置,放入要顯示的數值到暫存器,這個數目字是要能放在顯示的寬度內,然後呼叫 Put_Val。這個子程式用到 DIG 運算子來提取在暫存器上的數字並加上 48(ASCII 碼為”0”)來轉換數字的值成為字元,這樣就可以顯示在 LCD 上了。

Page 99: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

96

向前移動 這本書的第一個部份專門介紹輸出設備,因為選擇的輸出設備常常是一個很關鍵的項目。現在你應該對 LED 燈、七段顯示器甚至是 character LCD 模組非常熟悉。從現在起我們將繼續實驗;有些簡單,有些複雜,這些將讓你能成為一個 BASIC Stamp程式設計師並協助你在開發 BASIC Stamp 控制應用時建立信心。 請記住,成功的關鍵在於完成每個實驗並且提出挑戰。然後更進一步的利用 挑戰自己 來測試自己。每次你修改程式你都會學到一點東西。當你第一次做的時候不能照如期運作的話這事沒有關係的,因為你仍然有學習到。耐心並砥礪自己每天學習一點,很快的你會發現你很快就成為 BASIC Stamp 的高手。

Page 100: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

97

實驗#14:掃描並顯示多重輸入 這個實驗將會教你如何去抖動(debounce)多重 BASIC Stamp 輸出。經過修改後,任何數量的輸入,從 2 到 16,都可以用這個方法。

查一查:必須要知道的 PBASIC 元素

• ~ (反向運算子 Invert operator) • DEBUG

• HOME (用於 DEBUG)

• IBIN (用於 DEBUG)

• LOWBIT() (變數修改器 variable modifier)

建立電路

Page 101: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

98

程式: SW21-EX14-Debounce.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates the simultaneous debouncing of multiple inputs. ' The input subroutine is easily adjusted to handle any number of inputs. ' -----[ I/O Definitions ]------------------------------------------------- BtnBus VAR INA ' four inputs, pins 0 - 3 ' -----[ Variables ]------------------------------------------------------- btns VAR Nib ' debounced inputs idx VAR Nib ' loop counter ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Get_Buttons ' get debounced inputs DEBUG HOME, "Inputs = ", IBIN4 btns ' display in binary mode PAUSE 50 LOOP ' -----[ Subroutines ]----------------------------------------------------- Get_Buttons: btns = %1111 ' enable all four inputs FOR idx = 1 TO 5 btns = btns & ~BtnBus ' test inputs PAUSE 5 ' delay between tests NEXT RETURN

幕後 當只需要替一個輸入去抖動(debounce),BASIC Stamp 的 BUTTON 指令就可以完整的做到,甚至增加了兩個實用的功能(例如自動重複)。要去抖動兩個甚至更多的輸入,我們需要建立一些程式碼。實驗的主要部份是子程式 Get_Buttons。就如程式所寫一樣,它可以容納四個常開(normally-open)、低態動作(actitve-low)輸入,但是他也可以輕易地改變輸入量從兩個增加到十六個。

Page 102: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

99

Get_Buttons 的目的是要確保輸入被壓下後至少要有 25 毫秒沒有發生”抖動”。反抖動輸入將會回到變數 btns,其有效輸入由在每個按鍵位置的一個”1”所達成。 Get_Buttons 程式開始有一個假設:所有的按鍵輸入都是有效的,所以所有的btns 變數位元都設為 1。然後用 FOR-NEXT 迴圈,輸入將會被掃瞄並且比對先前的狀態。因為輸入都是低態動作(active-low)(壓下時變成 0),反向運算子(~)翻轉他們。And 運算子(&)被用在更新正確的狀態。對於一個有效的按鍵而言,他必須在整個 FOR-NEXT 迴圈中一直被壓著。 以下是反抖動技巧如何運作:當一個按鍵被按下時,輸入到 BASIC Stamp 的值就會變成 0。反向運算子將會把 0 轉為 1。1 “AND”1 還是 1,所以按鍵仍然是有效的。如果按鍵沒有被按下,原始的輸入到 BASIC Stamp 的值將會變成 1(因為 10k 電阻拉到 Vdd)。1 被反轉成 0。0”AND”任何的數目還是 0,這將導致按鍵在整個反抖動迴圈中都是無效的。 反抖動按鍵的輸入將會利用 IBIN4 修改器顯示在 DEBUG 視窗,使每個按鍵數值(狀態,被按下的等於”1”)可以清楚的被顯示。 就像一位專家編寫程式碼 許多程式需要可以”單發(single shot)”一個按鍵輸入,就是只有在按鍵”改變狀態”

激活了一些事件或程序。透過持續追蹤 後掃描的數值我們可以告訴程式在目前掃描結果和 新掃描結果之間哪個按鍵被改變。

Page 103: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

100

這裡是被修改的子程式:

Get_Buttons: nBtns = %1111 ' enable all four inputs FOR idx = 1 TO 5 nBtns = nBtns & ~BtnBus ' test new inputs PAUSE 5 ' delay between tests NEXT xBtns = nBtns ^ oBtns & nBtns ' look for 0 -> 1 changes oBtns = nBtns ' save this scan RETURN

經由這行程式真正的工作就被做完了

xBtns = nBtns ^ oBtns & nBtns ' look for 0 -> 1 changes 目前按鍵狀態(nBtns)和先前掃瞄的數值(oBtns)用 Exclusive OR(^)運算子做比較。這將導致當先前的數值不同於目前的數值時有個位元變為”1”。這個【比較】值和每個被按下的按鍵持有 1 的 nBtns 做 AND 運算。其結果是 xBtns 將會因在這次掃瞄有個”1”且在 後的掃描有個”0”而有個”1”。 請注意如果按鍵持續被壓著,Get_Buttons 就會被再次呼叫,xBtns 的每個位元將會因沒有改變按鍵狀態而從”1”改變成”0”。 請看 SW21-EX14-Debounce-Adv.BS2 完整說明。 更進一步 修改程式來掃描、反抖動並顯示八個按鍵(提示:用 INL 或 INH)。

Page 104: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

101

實驗#15:計數事件 這個實驗說明延遲事件(events-based)程式。 查一查:必須要知道的 PBASIC 元素

• CLS, CR, CRSRXY (用於 DEBUG)

建立電路

程式: SW21-EX15-Event_Count.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Counts extenal events by wait for a low-to-high transition on the event ' input pin. ' -----[ I/O Definitions ]------------------------------------------------- EventIn PIN 15 ' event input pin ' -----[ Variables ]------------------------------------------------------- nScan VAR Bit ' new scan (changed) oScan VAR Bit ' old scan of input xScan VAR Bit ' scan change eCount VAR Word ' event count target VAR Word ' target count value ' -----[ Initialization ]-------------------------------------------------- Reset:

Page 105: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

102

DEBUG CLS, "Started...", CR ' -----[ Program Code ]---------------------------------------------------- Main: target = 25 ' set target value GOSUB Wait_For_Count ' wait for 25 pulses DEBUG "Count complete." END ' -----[ Subroutines ]----------------------------------------------------- Wait_For_Count: DO nScan = EventIn ' capture input xScan = nScan ^ oScan & nScan ' look for 0 -> 1 change oScan = nScan ' save this scan IF (xScan = 1) THEN eCount = eCount + 1 ' add new event DEBUG CRSRXY, 0, 1, "Count = ", DEC eCount, CR ENDIF LOOP UNTIL (eCount = target) RETURN

幕後 Wait_For_Coun 子程式的目的是讓程式等到一個特定數字的事件。在生產線上,例如有個包裝系統,我們可能需要啟動輸送帶直到 100 箱盒子經過感應器。 如你所見我們在前面章節建立在探討”專業”技術。在迴圈的 上面,輸入狀態被抓取到 nScan,然後和前面的狀態(oScan)做比較來檢測是否改變(儲存在 xScan)。當輸入在掃描時從”0”變為”1”,這個事件就會被計數並顯示出來。在比較前抓取輸入的原因是要防止當在處理比較程序時輸入狀態改變可能的影響。 請注意在子程式 Wait_For_Count 中間顯示正確事件計數確實讓子程式的變動率限定在可以容納的範圍。這是因為 DEBUG 需要幾毫秒的時間來傳送到他的輸出到DEBUG Terminal window。移除 DEBUG 輸出(簡單的使用條件編譯)將增加事件輸入率以被檢測到。

Page 106: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

103

請注意的是子程式希望一個乾淨的輸入,一個含有雜訊的輸入可能導致錯誤的計算,導致提前終止子程式。這裡可以透過 後的實驗轉換 Get_Buttons 子程式來簡單的修復。

Scan_Input: ' use with "noisy" inputs nScan = 1 FOR idx = 1 TO 5 nScan = nScan & EventIn PAUSE 5 NEXT xScan = nScan ^ oScan & nScan ' look for 0 -> 1 change oScan = nScan ' save this scan RETURN

Page 107: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

104

實驗#16:頻率測量 這個實驗說明 BASIC Stamp 如何用 COUNT 函數測量輸入訊號的頻率。

查一查:必須要知道的 PBASIC 元素

• COUNT • #SELECT-#CASE-#ENDSELECT

建立電路

Note: The 1 kΩ resistor is marked: brown-black-red.

Page 108: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

105

程式: SW21-EX16-Freq_Measure.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program counts the number of events in one second and calculates ' frequency from it. Since frequency in Hertz is cycles per second, the ' number of cycles counted is the input frequency. ' -----[ I/O Definitions ]------------------------------------------------- FreqIn PIN 15 ' frequency input pin ' -----[ Constants ]------------------------------------------------------- OneSec CON 1000 ' capture window = 1 sec ' -----[ Variables ]------------------------------------------------------- cycles VAR Word ' counted cycles ' -----[ Program Code ]---------------------------------------------------- Main: DO COUNT FreqIn, OneSec, cycles ' count for 1 second DEBUG HOME, "Frequency: ", DEC cycles, " Hz" ' display LOOP

幕後 在前面的的實驗,某幾行的程式碼被用來在輸入針腳替脈衝計數。這個方法在當計數到特定數字是有用的。其他的程式希望計數脈衝數字直到特定的時間週期。BASIC Stamp 的 COUNT 函數就是被設計來用於此目的。 一個震盪信號的頻率被定義成一秒中多少的循環而且被定義成赫茲(Herz)。BASIC Stamp 的 COUNT 函數在很多的時間監控特定的針腳(Duration 參數)。創造一個簡單的頻率表,在指定的時間視窗設定為 1000 毫秒(1 秒)。

Page 109: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

106

請注意利用下頁的 Parallax USB 示波器(Oscilloscope)比較 BASIC Stamp 的測量輸出與輸入頻率。

Page 110: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

107

當 Duration 設定一秒鐘使用 COUNT 函數,可以很精確的測量 BASIC Stamp 模組特定輸入的頻率(模組對模組輸入頻率不同)。

就像一位專家編寫程式碼 COUNT 是少數幾個在 BASIC Stamp 功能上會因模組的不同而不同。例如在 BS2上,表示 Duration 參數的單位時間是 1 毫秒,而當在 BS2p 表示參數的單位則是0.287 毫秒。

Page 111: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

108

在另外一種情況下條件編譯指令特別有用,為了要 COUNT 適應於任何 BASIC Stamp 2 模組,我們可以加入這些模塊到我們的程式中:

#SELECT $STAMP #CASE BS2, BS2E DurAdj CON $100 ' Duration / 1 #CASE BS2SX DurAdj CON $280 ' Duration / 0.400 #CASE BS2P, BS2PX DurAdj CON $37B ' Duration / 0.287 #CASE BS2PE DurAdj CON $163 ' Duration / 0.720 #ENDSELECT

現在我們有一個 Duration 多重系統,CONT 程式碼可以修改成這樣:

COUNT FreqIn, OneSec */ DurAdj, cycles ' count for for 1 second

這樣程式在任何 BS2-家族模組下的表現都相同。

更進一步 透過改變 COUNT 週期提高程式響應(使訊息更新的更頻繁)。還有哪些需要被調整呢?如何變化是如何會影響到非常低頻率的信號呢?

Page 112: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

109

實驗#17:進階的頻率測量 這個實驗說明 BASIC Stamp 如何用 PULSIN 功能來測量輸入訊號的頻率。

查一查:必須要知道的 PBASIC 元素

• PULSIN

• DEC (用於 DEBUG)

• CLREOL (用於 DEBUG)

建立電路

和實驗#16 使用相同的電路

程式: SW21-EX17-Freq_Measure-Adv.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program monitors and displays the frequency of a signal on 15. The ' period of the input cycle is measured in two halves: low, then high. ' Frequency is calculated using the formula F = 1 / Period. ' -----[ I/O Definitions ]------------------------------------------------- FreqIn PIN 15 ' frequency input pin ' -----[ Constants ]------------------------------------------------------- Scale CON $200 ' 2.0 us per unit ' -----[ Variables ]------------------------------------------------------- pHigh VAR Word ' high pulse timing pLow VAR Word ' low pulse timing period VAR Word ' cycle time (high + low) freq VAR Word ' frequency

Page 113: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

110

' -----[ Initialization ]-------------------------------------------------- Reset: DEBUG CLS, ' setup report output "Period.(uS)... ", CR, "Freq (Hz)..... " ' -----[ Program Code ]---------------------------------------------------- Main: DO PULSIN FreqIn, 0, pLow ' get high side of input PULSIN FreqIn, 1, pHigh ' get low side of input period = (pLow + pHigh) */ Scale ' scale to uSecs freq = 62500 / period * 16 ' calculate frequency DEBUG CRSRXY, 15, 0, DEC period, CLREOL, ' display values CRSRXY, 15, 1, DEC freq, CLREOL LOOP

幕後 在上個實驗我們學到信號的頻率是被定義成每秒多少個循環。我們用計數一秒鐘內脈波(循環)的數量來創造了一個簡單的頻率測量器。這個方法不錯,尤其對於低頻率的信號。然而有時計劃上需要更快的響應時間來做頻率測量。 信號的頻率可以從他的週期來測量,或是一個完整週期的時間如下所示:

透過測量輸入信號的週期,頻率可以透過下列公式來計算(週期是用秒來表示):

Frequency = 1 / Period

Page 114: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

111

BASIC Stamp 的 PULSIN 功能是設計用來測量輸入脈波的寬度。用 PULSIN 測量輸入信號高和低的部份,他的週期和頻率就可以被計算出來。PUSIN 的結果(在BS2 上)會表現在兩個單位毫秒內。第一個 PULSIN 數值會透過下列公式被轉換成μS:

period = (pLow + pHigh) */ Scale 把比率(scale)歸為 PULSIN 指令的單位。因此頻率的計算公式變為:

Frequency = 1,000,000 / period (µs) 不過這樣對於 BASIC Stamp 的計算帶來問題,在 BASIC Stamp 中數字 大為 16位元( 高值為 65,535)。為了修改這個公式,我們可以將 1,000,000 除以 16(62,500)並重新寫公式如下:

Frequency = 62,500 / period (µs) * 16 這個公式可以適用於任何 BS2 模組-從 PUSIN 測量出的原始值已經被轉換成毫秒。在程式中把比率變成定數的目的:他從 PULSIN 轉換了原始的輸入變成毫秒好當做平常的頻率計算。 執行程式和調整 10kΩ的可變電組。注意 Debug Terminal window 沒有延遲更新和當使用 COUNT 來計算頻率時不用等待。這種測量頻率的方法可以在高頻率下運作的更好(超過 100Hz)。

Page 115: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

112

實驗#18 光線控制特雷門(A Light Controlled Theremin) 這個實驗透過建造一個光線控制特雷門來說明 FREQOUT(有史以來第一個電子樂器)。當從 BASIC Stamp-based 特雷門輸出不是常出現在市場上。這是一個有趣的實驗和體驗用非標準的輸入(光線大小)來做程式控制。

查一查:必須要知道的 PBASIC 元素

• FREQOUT

建立電路

Note: The 220 Ω resistor is marked: red-red-brown.

程式: SW21-EX18-Theremin.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program uses RCTIME with a photocell to create a light-controlled ' Theremin. ' -----[ I/O Definitions ]------------------------------------------------- Speaker CON 0 ' speaker output PitchCtrl CON 1 ' pitch control input

Page 116: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

113

' -----[ Constants ]------------------------------------------------------- TAdj CON $100 ' time adjust factor FAdj CON $100 ' frequency adjust factor Threshold CON 200 ' cutoff frequency to play NoteTm CON 40 ' note timing ' -----[ Variables ]------------------------------------------------------- tone VAR Word ' frequency output ' -----[ Program Code ]---------------------------------------------------- Main: DO HIGH PitchCtrl ' discharge cap PAUSE 1 ' for 1 ms RCTIME PitchCtrl, 1, tone ' read the light sensor tone = tone */ FAdj ' scale input IF (tone > Threshold) THEN ' play? FREQOUT Speaker, NoteTm */ TAdj, tone ENDIF LOOP

幕後 特雷門是一個有趣的音樂裝置,在老舊的恐怖電影常用來創造這些怪異、鬼怪的聲音。這個版本用光線照在光敏電阻上來創造輸出聲音。 由於光敏電阻是屬於電阻的一種,RCTIME 可以用來讀取這個值。FREQOUT 播放這個音符。Threshold 常數被用來控制特雷門的切斷點。當光敏電阻讀取的值低於這個數字,就不會發出聲音。這個數值應該一步步的調整直到光敏電阻不會因環境光影響而在播放時停止。

幕後…更進一步 你可能想知道 BASIC Stamp 如何用單純的數位輸出來創造一個音符。事實上,它是藉助外面世界的幫助。在實驗板前面的聲音放大器是一個低通濾波器電路,可以讓從 FREQOUT 的純數位輸出(特別是 PWM 輸出型態)並用平滑他變成一個很好的正弦波來產生一個乾淨的音符。

Page 117: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

114

要看這個動作,建立以下電路:

使用示波器,當執行下面程式時監測電路中標有 A 和 B 的點: Main: FREQOUT Speaker, 1000, 440 GOTO Main

在公板的 BS2 上將會產生一個一秒鐘 440Hz 的音調。請注意”A”點和經過濾波器產生正弦波的點”B”(10kΩ電阻代表聲音放大器的輸入)。

Page 118: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

115

實驗#19:音效(SFX) 本實驗用 DTMFOUT 和 FREQOUT 來模仿電話系統的聲音、創造音效甚至是播放一首簡單的歌。

查一查:必須要知道的 PBASIC 元素

• DTMFOUT • INPUT

建立電路

程式: SW21-EX19-Sound_FX.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Demonstrates sound FX and simple music using FREQOUT and DTMFOUT. ' -----[ I/O Definitions ]------------------------------------------------- Speaker PIN 0 ' speaker on pin 0 ' -----[ Constants ]------------------------------------------------------- R CON 0 ' rest C CON 33 ' ideal is 32.703 Cs CON 35 ' ideal is 34.648 D CON 37 ' ideal is 36.708 Ds CON 39 ' ideal is 38.891 E CON 41 ' ideal is 41.203 F CON 44 ' ideal is 43.654 Fs CON 46 ' ideal is 46.249

Page 119: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

116

G CON 49 ' ideal is 48.999 Gs CON 52 ' ideal is 51.913 A CON 55 ' ideal is 55.000 As CON 58 ' ideal is 58.270 B CON 62 ' ideal is 61.735 N1 CON 500 ' whole note duration N2 CON N1/2 ' half note N3 CON N1/3 ' third note N4 CON N1/4 ' quarter note N8 CON N1/8 ' eighth note TAdj CON $100 ' x 1.0 (time adjust) FAdj CON $100 ' x 1.0 (freq adjust) ' -----[ Variables ]------------------------------------------------------- idx VAR Word ' loop counter note1 VAR Word ' first tone for FREQOUT note2 VAR Word ' second tone for FREQOUT onTime VAR Word ' duration for FREQOUT offTime VAR Word oct1 VAR Nib ' octave for freq1 (1 - 8) oct2 VAR Nib ' octave for freq2 (1 - 8) eePntr VAR Byte ' EEPROM pointer digit VAR Byte ' DTMF digit clickDly VAR Word ' delay betweens "clicks" ' -----[ EEPROM Data ]----------------------------------------------------- Phone1 DATA "123-555-1212", 0 ' stored telephone numbers Phone2 DATA "916-624-8333", 0 ' -----[ Program Code ]---------------------------------------------------- Main: DEBUG CLS, "BASIC Stamp Sound FX Demo", CR, CR Dial_Tone: DEBUG "Dial tone", CR onTime = 35 */ TAdj note1 = 35 */ FAdj FREQOUT Speaker, onTime, note1 ' "click" PAUSE 100 onTime = 2000 */ TAdj note1 = 350 */ FAdj

Page 120: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

117

note2 = 440 */ FAdj FREQOUT Speaker, onTime, note1, note2 ' combine 350 Hz & 440 Hz Dial_Phone1: ' dial phone from EE DEBUG "Dialing number: " eePntr = Phone1 ' initialize eePntr pointer GOSUB Dial_Phone Phone_Busy: PAUSE 1000 DEBUG CR, " - busy...", CR onTime = 400 */ TAdj note1 = 480 */ FAdj note2 = 620 */ FAdj FOR idx = 1 TO 8 FREQOUT Speaker, onTime, note1, note2 ' combine 480 Hz and 620 Hz PAUSE 620 NEXT onTime = 35 */ TAdj note1 = 35 */ FAdj FREQOUT Speaker, onTime, note1 ' "click" Dial_Phone2: DEBUG "Calling Parallax: " eePntr = Phone2 GOSUB Dial_Phone Phone_Rings: PAUSE 1000 DEBUG CR, " - ringing" onTime = 2000 */ TAdj note1 = 440 */ FAdj note2 = 480 */ FAdj FREQOUT Speaker, onTime, note1, note2 ' combine 440 Hz and 480 Hz PAUSE 4000 FREQOUT Speaker, onTime, note1, note2 ' combine 440 Hz and 480 Hz PAUSE 2000 Camptown_Song: DEBUG CR, "Play a Camptown song", CR FOR idx = 0 TO 13 LOOKUP idx, [ G, G, E, G, A, G, E, R, E, D, R, E, D, R], note1 LOOKUP idx, [ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], oct1 LOOKUP idx, [N2, N2, N2, N2, N2, N2, N2, N2, N2, N1, N2, N2, N1, N8], onTime GOSUB Play_1_Note NEXT Howler:

Page 121: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

118

DEBUG "Howler -- watch out!!!", CR FOR idx = 1 TO 4 onTime = 1000 */ TAdj note1 = 1400 */ FAdj note2 = 2060 */ FAdj FREQOUT Speaker, onTime, note1, note2 ' combine 1400 Hz and 2060 Hz onTime = 1000 */ TAdj note1 = 2450 */ FAdj note2 = 2600 */ FAdj FREQOUT Speaker, onTime, note1, note2 ' combine 2450 Hz and 2600 Hz NEXT Roulette_Wheel: DEBUG "Roulette Wheel", CR onTime = 5 */ TAdj ' onTime for "click" note1 = 35 */ FAdj ' frequency for "click" clickDly = 250 ' delay between clicks FOR idx = 1 TO 8 ' spin up wheel FREQOUT Speaker, onTime, note1 ' click PAUSE clickDly clickDly = clickDly */ $00BF ' accelerate (speed * 0.75) NEXT FOR idx = 1 TO 10 ' spin stable FREQOUT Speaker, onTime, note1 PAUSE clickDly NEXT FOR idx = 1 TO 20 ' slow down FREQOUT Speaker, onTime, note1 PAUSE clickDly clickDly = clickDly */ $010C ' decelerate (speed * 1.05) NEXT FOR idx = 1 TO 30 ' slow down and stop FREQOUT Speaker, onTime, note1 PAUSE clickDly clickDly = clickDly */ $0119 ' decelerate (speed * 1.10) NEXT Computer_Beeps: ' looks great with randmom LEDs DEBUG "1950's Sci-Fi Computer", CR FOR idx = 1 TO 50 ' run about 5 seconds onTime = 50 */ TAdj RANDOM note1 ' create random note note1 = (note1 // 2500) */ FAdj ' don't let note go to high FREQOUT Speaker, onTime, note1 ' play it PAUSE 100 ' short pause between notes NEXT Space_Transporter: DEBUG "Space Transporter", CR onTime = 10 */ TAdj

Page 122: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

119

FOR idx = 5 TO 5000 STEP 5 ' frequency sweep up note1 = idx */ FAdj FREQOUT Speaker, onTime, note1, note1 */ 323 NEXT FOR idx = 5000 TO 5 STEP 50 ' frequency sweep down note1 = idx */ FAdj FREQOUT Speaker, onTime, note1, note1 */ 323 NEXT DEBUG CR, "Sound demo complete." INPUT Speaker END ' -----[ Subroutines ]----------------------------------------------------- Dial_Phone: DO READ eePntr, digit ' read a digit IF (digit = 0) THEN EXIT ' when 0, number is done DEBUG digit ' display digit IF (digit >= "0" AND digit <- "9") THEN ' don't digits onTime = 150 */ TAdj offTime = 75 */ TAdj DTMFOUT Speaker, onTime, offTime, [digit - 48] ENDIF eePntr = eePntr + 1 ' update eePntr pointer LOOP RETURN Play_1_Note: note1 = note1 << (oct1 - 1) ' note + octave onTime = onTime */ TAdj note1 = note1 */ FAdj FREQOUT Speaker, onTime, note1 ' play it RETURN Play_2_Notes: note1 = note1 << (oct1 - 1) ' note + octave note2 = note2 << (oct2 - 1) ' note + octave onTime = onTime */ TAdj note1 = note1 */ FAdj note2 = note2 */ FAdj FREQOUT Speaker, onTime, note1, note2 ' play both RETURN

Page 123: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

120

幕後 靠著一些程式上的創意,BASIC Stamp 微控制器可以創造和模仿一些非常有趣的音效,特別是用在電話系統上。因為大部分我們從電話上聽到的聲音(非語音)是由兩個音調所產生的,BASIC Stamp 的 FREQOUT 和 DTMFOUT 功能可以用來產生這些音效。 DTMFOUT 事實上算是 FREQOUT 的特殊版本,可以同時兩個聲音或是疊加在到另外一個上。DTMFOUT 的目的是創造一個雙聲來撥電話。下面的圖顯式原始和被濾波過後的 DTMFOUT 輸出。在被濾波的輸出中交互作用的雙聲清晰可見。

Page 124: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

121

在電話系統中的 DTMF 音調是標準的,所以不是傳遞一個聲音(或多個聲音),數字可以用來作為撥打的參數。在實際的撥號應用中,DTMF 上線或下線可以特別用來處理電話線的品質。 這個程式也提供 BASIC Stamp 播放簡單歌曲的基本音樂功能。固定音符頻率(第一個八度)和注意時間簡化成操作碼。Play_1_Note 子程式調整音符到指定的八度音。在高八度音裡音色提供一個位元因為捨去誤差。使用理想值顯示,固定表可以展開來創造準確的音符。請記住每個八度音是音符頻率的一倍。 Octave 2 = Octave 1 * 2 Octave 3 = Octave 2 * 2 Octave 4 = Octave 3 * 2 依此類推… 挑戰 轉換(一部分)你 愛的歌到 BASIC Stamp 上播放。

Page 125: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

122

實驗#20:紅外線物件感測 這個實驗說明實驗#18 使用 FREQOUT 而無聲音濾波器電路有趣的副作用;這個作用讓我們可以調整一個紅外線(IR)LED 燈來做紅外線感測器。 查一查:必須要知道的 PBASIC 元素

• Bit (變數型態)

建立電路

在 StampWorks 零件套件包含了一個紅外線 LED 燈(clear)和一個 38.5kHz 感測器。為了要防止從 LED 溢出光線,他必須要如上圖所示放到一個保護套內。

Page 126: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

123

程式: SW21-EX20-IR_Detect.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program uses FREQOUT without a filter to modulate an IR LED for ' detection by a demodulating receiver. ' -----[ I/O Definitions ]------------------------------------------------- IrLed PIN 0 ' IR LED output IrDectect PIN 1 ' detector input ' -----[ Constants ]------------------------------------------------------- IrMod CON 38500 ' 38.5 kHz (harmonic) ModTime CON 1 ' 1 ms NoDetect CON 1 ' detector is active-low ' -----[ Variables ]------------------------------------------------------- object VAR Bit ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Scan_IR IF (object = NoDetect) THEN DEBUG HOME, "All clear", CLREOL ELSE DEBUG HOME, "Intruder Alert!", CLREOL ENDIF PAUSE 100 LOOP ' -----[ Subroutines ]----------------------------------------------------- Scan_IR: FREQOUT IrLed, ModTime, IrMod ' module IR LED object = IrDectect ' scan detector RETURN

Page 127: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

124

幕後 如實驗#18 所解釋的,FREQOUT 的原始輸出被設計來在變成一個聲音放大器前被過濾的(產生一個非常乾淨的正弦波)。如果我們移除這個過濾器,原始的輸出會被在特定輸出頻率上填滿許多諧波內容。而諧波內容剛好強到足以調整一個紅外線LED。 註:諧波:在通信系統中,由於傳輸線的非線性特性所產生的一種諧波。當把正弦激勵信號加到輸入端時,其輸出就有諧波頻率出現。 透過FREQOUT指定的38.5kHz-事實上在一個合法的頻率數值上-我們得到一個基本加上諧波的38.5kz;這個諧波被用來調整紅外線LED。為什麼要調整?因為環境充滿了自然和人為的紅外線信號,成且透過調整和解調到特定頻率我們可以檢測我們的來源。下面的圖顯示透過FREQOUT創造的諧波峰;請注意必須接近目標38.5kHz才是有用的。

這個紅外線感測器是特殊的。請注意 FREQOUT 指令必須在我們可以從感測器採樣輸出前結束。在使用中的感測器保持它的輸出長到足以讓針腳掃描。

Page 128: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

125

更進一步 紅外線感測在手持遙控控制上打開了許多的可能性。像是電視和其他遙控器我們已經變的如此習以為常,在我們的案子中變的很好用。但是這問題需要一本書給他自己-並且那本書是可用的。Parallex 工程師,Andy Lindsay,已經撰寫一個參考書名為 IR Remote for the Boe-Bot.。這本書專注於機器人的應用,這些搖控控制程式碼可以用於幾乎任何使用者需要輸入的應用。他的前傳 Robotics with the Boe-Bot(同樣由 Andy 所著)是另外一本查詢紅外線物件感測的好書。

Page 129: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

126

實驗#21:用 PULSIN 做類比輸入 這個實驗說明用 PULSIN 能夠測量一個電阻元件和共同震盪電路。

建立電路

Note: The 0.01 µF capacitor is marked: 103.

程式: SW21-EX21-Analog_In.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program "reads" an analog value by using that component to control ' the output frequency of a 555-based oscillator. PULSIN is used to ' measure the high portion of the signal as it is controlled by the ' variable resistance. ' -----[ I/O Definitions ]-------------------------------------------------

Page 130: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

127

PulseInput PIN 15 ' pulse in from 555 ' -----[ Constants ]------------------------------------------------------- Scale CON $200 ' 2.0 us per unit P90 CON $E666 ' 0.90 P75 CON $C000 ' 0.75 P50 CON $8000 ' 0.50 P25 CON $4000 ' 0.25 P10 CON $1999 ' 0.10 ' -----[ Variables ]------------------------------------------------------- rValue VAR Word ' raw value sValue VAR Word ' smoothed value ' -----[ Initialization ]-------------------------------------------------- Reset: DEBUG CLS, "Analog Input ", CR, "------------ ", CR, "Raw value... ", CR, "Filtered.... " ' -----[ Program Code ]---------------------------------------------------- Main: DO PULSIN PulseInput, 1, rValue ' get high portion of input rValue = rValue */ Scale ' convert to microseconds sValue = (rValue ** P50) + (sValue ** P50) ' apply digital filter DEBUG CRSRXY, 13, 2, DEC rValue, CLREOL, ' print results CRSRXY, 13, 3, DEC sValue, CLREOL PAUSE 50 LOOP

Page 131: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

128

幕後 在這個實驗中,555 被配置成一個穩態(自由運行)的震盪器。分析輸出,比較高的信號較高部份的寬度由光敏電阻的電阻值所控制。利用 PULSIN 測量 555 的高電位部份的輸出,BASIC Stamp 可以測定相對的電阻值-經由光線照射的光敏電阻。 當輸出(pin 3)為高電位,透過光敏電阻和 1K 電阻 555 的電容器會被充電。一但達到閥值(大約 2/3Vdd)和經由 pin 6 檢測 555 輸出而 pin 7 將會變低,導致電容通過 1K 電阻放電。當電容放電到差不多 1/3Vdd 且被 pin 2 偵測到,輸出換回到高電位卻 pin 7 斷開來讓電容再次充電。由於 Cds 只有在充電用途(555 輸出為高電位),我們只要去測量信號這邊來決定相對的電阻。 這項計畫的好處是可以非常快的動作;缺點是在某些程式中快速變化的值變成一種挑戰。我們可以透過一些數位濾波來讓改變變慢。透過加入先前測量的的方法到目前的測量,我們可以控制數值如何快速的到達新的設定。在等式原始到濾波比率的讀數將會決定過濾器的應對。越大的原始部份,輸入響應越快。為了抑制快速改變的輸入,我們可以用一個很小的電路讀取部份和以前大部分的讀取部份。正確的數位濾波器關鍵是確保相對的百分比加到 100%(例如:25/75、50/50、90/10 等等)。

Page 132: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

129

實驗#22:用 PWM 於類比輸出 這個實驗說明用 PWM 和一個現成的運算放大器建造一個穩定的類比輸出。

查一查:必須要知道的 PBASIC 元素

• PWM

建立電路

Note: The 10 kΩ resistor is marked: brown-black-orange.

LM358 需要至少 6.5 伏特在他的 Vcc 針腳(8)上來提供從 PWM 5 伏特的輸出。透過使用實驗板上的 Vin 接腳(接近 RS-232 DCE 端)和一個 12 伏特的電源供應器。這樣就可以了。

Page 133: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

130

程式: SW21-EX22-Analog_Out.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates how the PWM command can be used with an opamp ' buffer to create a variable voltage output. ' -----[ I/O Definitions ]------------------------------------------------- D2Aout PIN 0 ' analog out pin ' -----[ Constants ]------------------------------------------------------- CycAdj CON $100 ' x 1.0, cycle adjust OnTime CON 5 ' 5 ms ' -----[ Variables ]------------------------------------------------------- level VAR Byte ' analog level mVolts VAR Word ' output in millivolts ' -----[ Initialization ]-------------------------------------------------- Reset: DEBUG CLS, "Analog Output ", CR, "--------------- ", CR, "level.... ", CR, "mVolts... " ' -----[ Program Code ]---------------------------------------------------- Main: DO FOR level = 0 TO 255 ' increase voltage to LED PWM D2Aout, level, (OnTime */ CycAdj) GOSUB Show_Level NEXT FOR level = 255 TO 0 ' decrease voltage to LED PWM D2Aout, level, (OnTime */ CycAdj) GOSUB Show_Level NEXT LOOP ' do it again

Page 134: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

131

' -----[ Subroutines ]----------------------------------------------------- Show_Level: mVolts = level */ $139B ' level * 19.6 mV DEBUG CRSRXY, 10, 2, DEC level, CLREOL, CRSRXY, 10, 3, DEC1 (mVolts / 1000), ".", DEC3 mVolts RETURN

幕後 雖然大部分的 BASIC Stamp 應用上是用數位信號來處理,有些需要類比輸出;一個可變的電壓在 0 至一個 大電壓。BASIC Stamp 的 PWM指令是被設計來當和 R/C濾波器結合產生一個類比伏特。PWM 指令產生一連串可編輯放電時間(on-time)和休止時間(off-time)工作週率(duty cycle)的脈波。電路的輸出電壓和 PWM 指令中的 Duty 參數一樣-一個較大的數值給 Duty 將會導致一個較高的輸出電壓。一個255 的 Duty 將會將電容器充電到 5 伏特。 工作週率(Duty Cycle):脈衝訊號經歷高電壓的時間週期與脈衝週期的比例稱

之為工作週率。如圖九,

為了要確保電容器已經完全充電了,Duration 參數應該被設定至至少 5 個 R/C 定值時間。在電路上,一個定值時間是 1 毫秒(10kΩ×0.1μF),所以設定 Duration 到10 毫秒來保證電容器已經充電到 Duty 設定的標準。 在這個實驗中,一半的 LM358 被配置一個電壓追隨器(voltage follower)和提供一個緩衝輸出到 LED 或其他電路。運算放大器緩衝防止沒充電的電容器太快過載。LED 亮和暗是因為改變中的電壓透過他一系列的電阻改變而改變通過 LED 的電

Page 135: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

132

流。請注意 LED 似乎突然開啟和發亮,然後暗到某種程度後突然關閉。這種情況發生在當 LM358 的輸出跨過前面的 LED 電壓閥值(點亮 LED 燈的 小電壓)(實驗板上的藍色 LED 燈大約是 2.3 伏特-其他的 LED 燈則不同)。

Page 136: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

133

雙通道示波器螢幕抓取了如下所示的 PWM2 的未過濾(直接從 BASIC Stamp)和過濾的輸出(LM358 的 pin 1)。

注意來自 PWM 的輸出只有在指令是有效(由 Duration 設定)時保持著,且甚至在輸出針腳上一個迴圈裡會中斷(將會降至 0 伏特)。因此,PWM 指令並不是特別適合用於馬達速度控制應用。

Page 137: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

134

實驗#23:利用位移暫存器擴大數位輸出 這個實驗說明利用簡單的位移暫存器來擴大 BASIC Stamp 的輸出。三個 I/O 針腳會被用來配合一顆 74HC595 位移暫存器控制八個 LED 燈。

註:位移暫存器:可將所儲存的二元資料向一個或兩個方向移位的暫存器。

查一查:必須要知道的 PBASIC 元素

• SHIFTOUT

• MSBFIRST (用於 SHIFTOUT)

建立電路

Page 138: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

135

程式: SW21-EX23-74HC595-1.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates a simple method of turning three BASIC Stamp ' I/O pins into eight digital outputs with a 74HC595 shift register. ' -----[ I/O Definitions ]------------------------------------------------- Clock PIN 0 ' shift clock (74HC595.11) SerData PIN 1 ' serial data (74HC595.14) Latch PIN 2 ' output latch (74HC595.12) ' -----[ Constants ]------------------------------------------------------- DelayTime CON 100 ' -----[ Variables ]------------------------------------------------------- pattern VAR Byte ' zig-zag pattern ' -----[ Initialization ]-------------------------------------------------- Reset: LOW Latch ' make output and low pattern = %00000001 ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Out_595 ' put pattern on 74x595 PAUSE DelayTime ' hold pattern = pattern << 1 ' shift pattern left LOOP UNTIL (pattern = %10000000) DO GOSUB Out_595 PAUSE DelayTime pattern = pattern >> 1 ' shift pattern right LOOP UNTIL (pattern = %00000001) GOTO Main

Page 139: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

136

' -----[ Subroutines ]----------------------------------------------------- Out_595: SHIFTOUT SerData, Clock, MSBFIRST, [pattern] ' send pattern to '595 PULSOUT Latch, 5 ' latch outputs RETURN

幕後 BASIC Stamp 可以重新定義它的 I/O 針腳方向(輸入或輸出)可說是非常靈活,很少應用需要這種靈活性。在大部分情況下,微控制器應用一開始都會定義針腳是輸入還是輸出而定義在整個程式中都不會改變。 我們可以用輸入是輸入和節省寶貴的 BASIC Stamp I/O針腳同時用一個點單的組件來呼叫一個序列進、並聯出的位移暫存器。在這個實驗中,74HC595 位移暫存器會被用到。只需要三個 BASIC Stamp I/O 針腳,這個程式就可以控制 8 個 LED 燈。 74HC595 轉換一個同步序列資料串到八個平行輸出。同步序列資料事實上有兩個部份組成:序列資料(serial data)和序列時脈(serial clock)。BASIC Stamp 的SHIFOUT 指令處理這些資料和時脈傳輸線的細節和寫入資料到同步裝置上,這這裡是 74HC595。下面的圖說明$AF 數值時脈和資料信號的關係。

Page 140: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

137

使用 74HC595,資料必須在位移過程後被鎖定在輸出端。鎖定是靠短暫的脈衝到鎖定控制傳輸線(低電位-高電位-低電位)上來完成的。這功能是防止 74HC595 輸出端因”漣漪”而變成一組已經被位移或通過裝置的新資料。請注意鎖定傳輸線通過電組時被拉低;這是防止當 BASIC Stamp 初始化和 I/O 針腳在高阻抗狀態(浮動)時將意外鎖定的無效資料雜訊傳到 74HC595 輸出端。 更進一步 作為序列裝置,位移暫存器可以被串連,使 BASIC Stamp 可以用同樣第三個 I/O 針腳來控制數十個 74HC595 輸出。

Page 141: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

138

Page 142: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

139

要連接被串聯的 74HC595,時脈和鎖定傳輸線是被綁在一起的而 QH 的序列輸出從一個晶片連接到下一個晶片的序列輸入。

程式: SW21-EX23-74HC595-2.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates a simple method of turning three BASIC Stamp ' I/O pins into sixteen digital outputs with a 74HC595 shift register. ' -----[ I/O Definitions ]------------------------------------------------- Clock PIN 0 ' shift clock (74HC595.11) SerData PIN 1 ' serial data (74HC595.14) Latch PIN 2 ' output latch (74HC595.12) ' -----[ Constants ]------------------------------------------------------- DelayTime CON 100 ' -----[ Variables ]------------------------------------------------------- counter VAR Byte ' binary counter pattern VAR Byte ' zig-zag pattern ' -----[ Initialization ]-------------------------------------------------- Reset: LOW Latch ' make output and low pattern = %00000001 ' -----[ Program Code ]---------------------------------------------------- Main: DO counter = counter + 1 ' update counter GOSUB Out_595x2 ' put pattern on 74x595 PAUSE DelayTime ' hold pattern = pattern << 1 ' shift pattern left LOOP UNTIL (pattern = %10000000) DO counter = counter + 1

Page 143: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

140

GOSUB Out_595x2 PAUSE DelayTime pattern = pattern >> 1 ' shift pattern right LOOP UNTIL (pattern = %00000001) GOTO Main ' -----[ Subroutines ]----------------------------------------------------- Out_595x2: SHIFTOUT SerData, Clock, MSBFIRST, [counter] ' send counter to 595-2 SHIFTOUT SerData, Clock, MSBFIRST, [pattern] ' send pattern to 595-1 PULSOUT Latch, 5 ' latch outputs RETURN

幕後 74HC595 有一個序列輸出 pin(9),可以串聯多個裝置而得到更多的輸出-從一個 595

序列輸出餵給下一個在傳輸線上裝置上的序列輸入。這樣在一個新的時脈脈衝上從QH 移動資料到 QH 的輸出(9)是可行的。當連接串聯的 595 們,時脈和鎖定針腳應該被綁在一起來使所有裝置都保持同步。 程式中我們必須在當串聯裝置作用時關注被位移的數值。隨後 SHIFTOUT序列將會”推動”資料通過每個暫存器直到正確的裝置。在下面的圖示中,被用於 595-2 的數值先輸出並將位移通過 595-2。

資料輸出到所有在鏈上的位移暫存器後,鎖定脈衝被用於轉換新的資料到 74HC595輸出針腳。

Page 144: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

141

實驗#24:利用位移暫存器擴展數位輸出 這個實驗說明利用一個簡單的位移暫存器-74HC165 來擴展 BASIC Stamp 輸出,這和用於實驗#23 的 74HC595 是互補的裝置。

查一查:必須要知道的 PBASIC 元素

• SHIFTIN

• MSBPRE (用於 SHIFTIN)

建立電路

Page 145: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

142

程式: SW21-EX24-74HC165-1.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates a simple method of turning three BASIC Stamp ' I/O pins into eight digital inputs with a 74HC165 shift register. ' -----[ I/O Definitions ]------------------------------------------------- Clock PIN 0 ' shift clock (74HC165.2) SerData PIN 1 ' serial data (74HC165.7) Load PIN 2 ' output latch (74HC165.1) ' -----[ Constants ]------------------------------------------------------- DelayTime CON 100 ' -----[ Variables ]------------------------------------------------------- switches VAR Byte ' switch data ' -----[ Initialization ]-------------------------------------------------- Reset: HIGH Load ' make output and high DEBUG CLS, "Switches 76543210", CR, "-------- --------", CR, "Status ........" ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Get_165 ' get switch inputs DEBUG CRSRXY, 10, 2, BIN8 switches ' display current status PAUSE DelayTime ' pad the loop a bit LOOP ' -----[ Subroutines ]----------------------------------------------------- Get_165: PULSOUT Load, 5 ' load switch inputs SHIFTIN SerData, Clock, MSBPRE, [switches] ' shift them in

Page 146: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

143

幕後 這個實驗說明 SHIFTIN,對於 SHIFTOUT 這是互補功能。在這裡,三個 BASIC Stamp 的 I/O 針腳被用來讀取八個 DIP 開關的狀態。為了要從 74HC165 讀取資料,並聯輸出要透過短暫的脈衝到載入傳輸線(高電位-低電位-高電位)來被鎖定,然後用 SHIFTIN 來移動資料到 BASIC Stamp。 請注意 DIP 開關向上撥到 Vdd,所以設定它們到關閉位置造成在位移暫存器輸入上的一個邏輯上的低電位(0)。透過使用 74HC165 的 Q\(相反於資料輸出)針腳,開關資料透過”1”位元開啟到達 BASIC Stamp 而知道一個開關被關閉。

更進一步 和 74HC595 一樣,我們可以串聯 74HC165 透過三個 I/O 針腳來創造更多的輸入。連接你所選的輸入到下面的電路:

Page 147: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

144

Page 148: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

145

程式: SW21-EX24-74HC165-2.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates a simple method of turning three BASIC Stamp ' I/O pins into sixteen digital inputs with two 74HC165 shift registers ' that have been cascaded. ' -----[ I/O Definitions ]------------------------------------------------- Clock PIN 0 ' shift clock (74HC165.2) SerData PIN 1 ' serial data (74HC165.7) Load PIN 2 ' output latch (74HC165.1) ' -----[ Constants ]------------------------------------------------------- DelayTime CON 100 ' -----[ Variables ]------------------------------------------------------- xInputs VAR Word ' external inputs ' -----[ Initialization ]-------------------------------------------------- Reset: HIGH Load ' make output and high DEBUG CLS, "XInputs FEDCBA9876543210", CR, "------- ----------------", CR, "Status ................" ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Get_165x2 ' get inputs DEBUG CRSRXY, 10, 2, BIN16 xInputs ' display current status PAUSE DelayTime ' pad the loop a bit LOOP ' -----[ Subroutines ]----------------------------------------------------- Get_165x2: PULSOUT Load, 5 ' load inputs SHIFTIN SerData, Clock, MSBPRE, [xInputs\16] ' shift them in RETURN

Page 149: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

146

幕後 這個程式和 74HC595 串連非常相似,從一個被餵的位移暫存器串聯輸出到下一個鏈上的裝置序列輸出。重要的是注意被連接的串聯晶片使用非反相輸出;只有晶片連接到 BASIC Stmap 才會使用反相輸出(所有資料在這通過都會被反相)。 在程式中,Get_165x2 子函式已經被更新到可以用第二個 74HC165。因為一個 Word宣告變數已經被定義在額外的輸入,位元修改器被 SHIFTIN 來使用;這讓所有 16位元可以在同一時間被收集在一起。當位元的數字不同於 8 時位元修改器才會被需要(原始位元計數)。 我們還可以設定單獨位元組變數給每個裝置。下面的程式碼片段顯示了我們如何處理這種狀況:

Get_165x2: PULSOUT Load, 5 ' load inputs SHIFTIN SerData, Clock, MSBPRE, [switches, buttons] RETURN

在這例子中,被稱為 switches 的變數隨著從第一個鏈上的位移暫存器被下載(即使設備被連接到 BASIC Stamp 上)。

Page 150: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

147

實驗#25:用數個位移暫存器混合 IO 介面 這個實驗說明用 74HC595 和 74HC165 和用 少數量的 BASIC Stamp I/O 針腳來做混合。

建立電路

Note: The 4.7 kΩ resistor is marked: yellow-violet-red.

Page 151: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

148

實驗: SW21-EX25-Mixed_IO.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates the ability to use the 74HC595 and 74HC165 ' together with the fewest number of BASIC Stamp IO pins. This is ' accomplished by placing a 4.7K resistor between the data out (pin 7) of ' the 74HC165 and the data in (pin 14) of the 74HC595. The serial data ' pin from the BASIC Stamp connects to the 74HC595. ' -----[ I/O Definitions ]------------------------------------------------- Clock PIN 0 ' shift clock SerData PIN 1 ' serial data (74HC595.14) Latch PIN 2 ' output latch (74HC595.12) Load PIN 3 ' input load (74HC165.1) ' -----[ Constants ]------------------------------------------------------- DelayTime CON 100 ' -----[ Variables ]------------------------------------------------------- xInputs VAR Byte ' external inputs ' -----[ Initialization ]-------------------------------------------------- Reset: LOW Latch HIGH Load DEBUG CLS, "XInputs 76543210", CR, "------- --------", CR, "Status ........" ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Get_165 ' get inputs GOSUB Put_595 ' move to extended outputs DEBUG CRSRXY, 10, 2, BIN8 xInputs ' display current status PAUSE DelayTime ' pad the loop a bit LOOP

Page 152: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

149

' -----[ Subroutines ]----------------------------------------------------- Get_165: PULSOUT Load, 5 ' load inputs SHIFTIN SerData, Clock, MSBPRE, [xInputs] ' shift them in RETURN Put_595: SHIFTOUT SerData, Clock, MSBFIRST, [xInputs] ' send inputs to 595 PULSOUT Latch, 5 ' latch 595 outputs INPUT SerData ' float data I/O line RETURN

幕後 這個程式和前面的實驗作了一個很簡單的結合-和一個關鍵的細節:一個 4.7kΩ的電阻被放在 74HC165 資料輸出針腳和 74HC595 資料輸入針腳間。需要的原因74HC165 資料輸出接腳就是要輸出,而且如果針腳直接和 BASIC Stamp 接觸可能會發生資料衝突(當 BASIC Stamp 把序列資料針腳放進 SHIFTOUT 輸出模式),這樣會造成一個短路。電阻提供了一個負載來讓安全電流通過 BASIC Stamp 和74HC165 之間。 這個電阻還給了 BASIC Stamp 一個負載來驅動它的輸出,所以不管 74HC165 輸出針腳的狀態,74HC595 的資料輸入將會永遠正確。不能讓 4.7kΩ的電阻離開這個電路;否則你的 BASIC Stamp 模組可能會受傷。請注意序列資料傳輸線在 Put_595

子程式 後被製作成一個輸出(浮動)。當針腳在相反狀態時,BASIC Stamp 和74HC165 的電流會停止。

Page 153: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

150

實驗#26:模型伺服馬達(HOBBY SERVO)控制 這個實驗說明標準的模型伺服馬達控制。模型伺服馬達常常在業餘機器人和動畫中和微控制器結合。

查一查:必須要知道的 PBASIC 元素

• MAX ( 大運算子 maximum operator)

• SDEC, SDEC1 – SDEC16 (用於 DEBUG)

建立電路

Page 154: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

151

程式: SW21-EX26-Servo_Control.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program shows how to control a standard servo with the BASIC Stamp. ' Servo position is controlled by reading position of a potentiometer that ' is part of opposing RCTIME networks. ' -----[ I/O Definitions ]------------------------------------------------- PotCW PIN 0 ' clockwise pot input PotCCW PIN 1 ' counter-cw pot input Servo PIN 2 ' servo control pin ' -----[ Constants ]------------------------------------------------------- Scale CON $00C6 ' to scale RCTIME values Center CON 1500 ' servo center position PwAdj CON $0080 ' pulse width adjust (0.5) ' -----[ Variables ]------------------------------------------------------- rcRt VAR Word ' rc reading - right rcLf VAR Word ' rc reading - left diff VAR Word ' difference sPos VAR Word ' servo position pWidth VAR Word ' pulse width for servo ' -----[ Initialization ]-------------------------------------------------- Reset: LOW Servo ' initialize for PULSOUT ' -----[ Program Code ]---------------------------------------------------- Main: HIGH PotCW ' read clockwise position PAUSE 1 RCTIME PotCW, 1, rcRt HIGH PotCCW ' read ccw position PAUSE 1

Page 155: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

152

RCTIME PotCCW, 1, rcLf rcRt = (rcRt */ Scale) MAX 500 ' scale RCTIME to 0-500 rcLf = (rcLf */ Scale) MAX 500 sPos = rcLf - rcRt ' position (-500 to 500) pWidth = (Center + sPos) ' finalize pulse width PULSOUT Servo, (pWidth */ PwAdj) ' move the servo PAUSE 20 ' servo refresh delay GOTO Main

幕後

模型伺服馬達是 常專門用於控制模型飛機表面位置的機電裝置。伺服馬達的位置輸出是靠傳入控制脈衝的寬度來計算。控制脈衝通常是在 1 到 2 毫秒寬。當控制訊號是 1.5 毫秒時,伺服馬達將會在中間。為了要維持它的位置,伺服馬達必須定期更新。典型的更新頻率如下圖所示約為每秒五十次或是每 20 毫秒。

在伺服馬達的 PULSOUT 指令是個控制模型伺服馬達的理想指令。在這實驗中,兩個 RCTIME 電路被建立在一個 10K 可變電阻周圍。這個配置允許程式碼來分開可變電阻(用電刷),測量個別的每一邊。透過這樣做我們可以測量可變電阻的相對位置。每邊的讀值透過*/和 MAX 運算子縮放成介於 0 到 500 的值。透過從另一邊減去一邊,伺服馬達位置數值會在-500 至+500 間往返。

Page 156: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

153

常數 Scale 的數值是憑經驗測量出來的,在建立電路後,插入適當的 DEBUG 狀態來顯示兩邊原始的可變電阻讀值(他們可能不完全吻合,可能有稍許差異)。拿兩數較低的值並除以 500(所需的輸出)。透過乘以 256 來轉換這個分數的值到*/運算域。 範例: 原始 RCTIME v 數值: 645 250 / 645 = 0.775 0.775 x 256 = 198 (這個值稱為 Scale) 兩個被 RCTIME 縮放過的數值不同的地方在於被添加到 1500(毫秒)的中心位置。請記住在 BASIC Stamp 2 模組上,PULSOUT 運作於兩毫秒單位間。這代表脈衝寬度值需要被除以 2 以創造出伺服馬達正確的脈衝輸出。這已經透過使用*/和 PwAdj

不斷地來設定到$0800(0.5)。 這個程式說明 BASIC Stmap 確實可以在負數下運作。你可以看到在計算後透過置入這行 sPos 的值:

DEBUG Home, "Position: ", SDEC sPos, " "

負數被儲存在 2 的補數(two’s complement format)。SDEC(正負數的十進制 signed decimal)修改器透過適當的時候印出標準的十進制。 挑戰 用兩個光敏電阻來替換可變電阻並更新程式碼來讓伺服馬達朝著光源前進。 你能想到一種方法來使用兩個可變電阻和兩個伺服馬達來創造一個太陽追蹤器嗎?

Page 157: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

154

實驗#27:步進馬達(Stepper Motor)控制 這個實驗說明如何控制一個小的 12 伏特步進馬達。步進馬達轉換輸入的樣式和這些輸入的改變率到精確的旋轉動作。旋轉角和每個改變(步)的方向都是透過馬達的結構來計算,和步階輸入一樣。步進馬達被用來在機器人和工業控制應用的精密位置裝置上。 查一查:必須要知道的 PBASIC 元素

• ABS • MIN ( 小運算子 minimum operator)

建立電路

移除實驗#26 的伺服馬達和添加步進馬達如下圖:

Page 158: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

155

程式: SW21-EX27-Stepper_Control.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates simple stepper motor control. A potentiometer ' allows for speed and direction control. Using the L293D driver, this ' program will work with unipolar and bipolar stepper motors. ' -----[ I/O Definitions ]------------------------------------------------- PotCW PIN 0 ' clockwise pot input PotCCW PIN 1 ' counter-cw pot input Coils VAR OUTB ' output to stepper coils ' -----[ Constants ]------------------------------------------------------- Scale CON $100 ' to scale RCTIME Mitsumi CON 48 ' steps/rev by type Howard CON 100 RevSteps CON Mitsumi ' steps per revolution NumSteps CON 4 ' use 4-step sequence LastStep CON NumSteps - 1 ' last step in sequence #DEFINE Testing = 0 ' 1 for POT testing ' -----[ Variables ]------------------------------------------------------- idx VAR Byte ' loop counter stpIdx VAR Nib ' step pointer stpDelay VAR Byte ' delay for speed control rcRt VAR Word ' rc reading - right rcLf VAR Word ' rc reading - left diff VAR Word ' difference in readings ' -----[ EEPROM Data ]----------------------------------------------------- ' __ ' ABAB ' ----- Step1 DATA %1100 Step2 DATA %0110

Page 159: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

156

Step3 DATA %0011 Step4 DATA %1001 ' -----[ Initialization ]-------------------------------------------------- Setup: DIRB = %1111 ' make P4..P7 outputs stpDelay = 5 ' set step delay ' -----[ Program Code ]---------------------------------------------------- Demo: FOR idx = 1 TO RevSteps ' 1 rev forward GOSUB Step_Fwd NEXT PAUSE 200 FOR idx = 1 TO RevSteps ' 1 rev back GOSUB Step_Rev NEXT PAUSE 200 Main: HIGH PotCW ' read clockwise position PAUSE 1 RCTIME PotCW, 1, rcRt HIGH PotCCW ' read ccw position PAUSE 1 RCTIME PotCCW, 1, rcLf rcRt = (rcRt */ Scale) MAX 600 ' set speed limits rcLf = (rcLf */ Scale) MAX 600 diff = ABS (rcRt - rcLf) ' get difference stpDelay = 100 - (diff / 6) MIN 2 ' calculate step delay IF (diff < 25) THEN ' allow for dead band GOTO Main ELSE ' do a step IF (rcLf < rcRt) THEN GOSUB Step_Fwd ELSE GOSUB Step_Rev ENDIF ENDIF GOTO Main ' repeat

Page 160: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

157

' -----[ Subroutines ]----------------------------------------------------- ' Turn stepper clockwise one full step Step_Fwd: stpIdx = stpIdx + 1 // NumSteps ' point to next step GOTO Do_Step ' Turn stepper counter-clockwise one full step Step_Rev: stpIdx = stpIdx + LastStep // NumSteps ' point to previous step GOTO Do_Step ' Read new step data and output to pins Do_Step: READ (Step1 + stpIdx), Coils ' output new coil data PAUSE stpDelay ' pause between steps RETURN

幕後 步進馬達不同於標準的直流馬達在於他們在通電時不能自由的旋轉。對於一顆步進馬達旋轉而言,電源必須持續在特定模式下脈衝。這個步進的順序(模式)計算這步進馬達旋轉的方向。介於序列步進的時間決定了旋轉速度。每一步造成步進馬達旋轉一個固定的角度增量。目前 StampWorks kit 提供的步進馬達每一步旋轉 7.5度。這代表旋轉一整圈(360 度)需要 48 步。使用下面的圖表來得知馬達的資訊。

製造商 Mitsumi Howard Industries

每步度數 7.5 3.6

每圈步數 48 100

Phase 1 咖啡 白 Phase 2 橘 紅 Phase 3 黑 綠 Phase 4 黃 咖啡

接地 紅 黑

Page 161: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

158

馬達的步進序列被儲存在 DATA 宣告中。Step_Fwd 子程式將會從這個表個讀取下一個序列到提供的線圈裡。StepRev 子程式是相似的除了他將會讀取前一步。請注意 StepRev 裡的模數運算子(//)使用方法。透過添加序列 大值到正確的數值然後提供模數運算子,序列會相反。如下所看到的,這裡是模數運算每一步(四步為一個循環): 0 + 3 // 4 = 3 3 + 3 // 4 = 2 2 + 3 // 4 = 1 1 + 3 // 4 = 0 這個實驗同時讀取 10K 可變電阻的兩端來測定它的相對位置。在兩個讀數間不同的值透過 ABS 功能來保持正數。被用來計算旋轉方向的位置和位置力量用來計算旋轉速度。請記住每步間延遲的時間越短,步進馬達轉的越快。當 RCTIME 讀數接近相等時,死區(dead-band)檢查是用來造成馬達停止旋轉。 更進一步 剩餘的步進馬達是很容易得到的,而實驗者常會面臨兩個挑戰:1)如何控制一個雙極(4 線)步進馬達和,2)如何測量未知線圈序列的馬達。 透過使用 L293D 第一個挑戰就解決了;L293D 是一個推挽(push-pull)驅動器(相對於 UKN2x03 只吸收電流)並運作-沒有任何修改到程式碼-用單極和雙極步進馬達。 第二個挑戰可以用一個萬用表來克服。創造一個表來在每一列和行開頭寫下電線顏色,記下電線測量的電阻值。例如:

Page 162: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

159

Yel Blk Org Brn Red

Yel x Blk 225 x

Org 225 225 x

Brn 225 225 225 x

Red 112 112 112 112 x

請注意當紅色電線是是其他電阻讀數的一半時;他就是地線。有些單極馬達有六條電線。在這裡,兩條電線都是地線。 要測量電線的序列,請按照下列步驟: 1. 連接線圈導線到任何排定的順序上。執行程式;如果他轉動的很順就代表你成

功了。

2. 如果第一步沒有成功,交換#1 和#4 的電線接點。重新測試。

3. 如果第二步沒有成功,交換#2 和#3 的電線接點。現在馬達應該可以運轉了。 如果馬達運轉的方向和期望的相反,交換#1 和#4 的順序,還有#2 和#3 的順序。馬達現在應該旋轉的很順暢並且按照既定的方向。 挑戰 重寫程式來讓馬達只跑一半步。請記住還有一半步提供更精確的位置,馬達轉矩減半可能造成無法轉動所連接的裝置。這裡是每步的順序:

Step1 = %1000 Step2 = %1100 Step3 = %0100 Step4 = %0110 Step5 = %0010 Step6 = %0011 Step7 = %0001 Step8 = %1001

Page 163: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

160

實驗#28:電壓量測 這個實驗說明如何用 ADC0831 類比轉數位轉換 IC 來讀取一個輸入電壓的值。

查一查:必須要知道的 PBASIC 元素

• MSBPOST (用於 SHIFTIN)

建立電路

程式: SW21-EX28-ADC0831-Simple.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates reading a variable voltage with an ADC0831 ' analog-to-digital converter chip. This program uses a Vref input of ' 5.000 volts (Vdd) for a bit resolution of 19.6 millivolts. ' -----[ I/O Definitions ]------------------------------------------------- CS PIN 0 ' chip select (ADC0831.1) Clock PIN 1 ' clock (ADC0831.7)

Page 164: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

161

DataIn PIN 2 ' data (ADC0831.6) ' -----[ Constants ]------------------------------------------------------- Cnts2Mv CON $139C ' x 19.6 (to millivolts) ' -----[ Variables ]------------------------------------------------------- result VAR Byte ' result of conversion mVolts VAR Word ' millivolts ' -----[ Initialization ]-------------------------------------------------- Reset: DEBUG CLS, ' create report screen "ADC.... ", CR, "volts... " ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Read_0831 ' read the ADC mVolts = result */ Cnts2Mv ' convert to millivolts DEBUG HOME, ' report CRSRXY, 9, 0, DEC result, CLREOL, CRSRXY, 9, 1, DEC mVolts DIG 3, ".", DEC3 mVolts PAUSE 100 LOOP ' -----[ Subroutines ]----------------------------------------------------- Read_0831: LOW CS ' enable ADC SHIFTIN DataIn, Clock, MSBPOST, [result\9] ' read ADC HIGH CS ' disable ADC RETURN

Page 165: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

162

幕後 前面的專案已經用 RCTIME 來讀取電阻元件。這是一種類比輸入的格式,但是不是一種電壓的量測。為此,BASIC Stamp 需要其他裝置來幫忙。 簡單的量測電壓數值的方法就是用一個類比轉數位的轉換器。 在實驗中,National Semiconductor 的 ADC0831 被用來轉換電壓(0 到 5)到一個同步序列信號來讓 BASIC Stamp 用 SHIFTIN 來讀取。要注意的是 Read_0831 子程式裡我們指定 9 個位元到 SHIFTIN,即使結果只有 8 個位元?為什麼? ADC0831 在激活做電壓轉換後需要一個在時脈傳輸線上的脈衝。在下一個 8 個時脈脈衝移動資料輸出到外部如下圖所示:

第一個時脈脈衝(灰色)後,CS 傳輸線變成低位元造成 ADC0831 去做電壓轉換。被用於 SHIFTIN 的 MSBPOST 模式用來讓資料位元先送出 MSB,然後時序傳輸線下降。POST 模式在每個時序脈衝後採樣數據傳輸線上的資料。 電壓量測-其實就是 Vin+(針腳 2)和 Vin-(針腳 3)電壓的差異-這個值會介於0 到 255 之間(Vref)。在我們第一使用時我們已經連接 Vin-到地和 Vref 到 Vdd;這樣給我們一個範圍在 5.00 的電壓。5 伏特除以 255,我們可以發現每個位元等於19.6 毫伏特。為了要顯示出結果要乘以 19.6(結果*/$139C)來顯示出毫伏特。

Page 166: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

163

用於清理顯示的 DEBUG 技巧,mVolt。DIG 3 運算顯示出所有電壓而 DEC3 修改器顯示分數的電壓( 右邊的 3 個數字)。 重新連接電路如下面所示並重新執行程式。

現在用一個萬用表來量測介於針腳 2 和針腳 3 的電壓。請注意當針腳 3 的電壓高於針腳 2 時,輸出為 0。 更進一步 就像前面所講的,對於 ADC 輸出的每位元伏特都是透過電壓供應到 Vref 來計算。重新連接電路如下所示,並設定 Vref 針腳上的電壓到 2.55 伏特(確認萬用表)。

Page 167: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

164

透過減少 Vref 電壓,每個輸出位元結果會增加。一個 2.55 伏特的 Vref,每位元電壓為 0.01 伏特,將近當 Vref 為 5 伏特時的兩倍,而且轉換成毫伏特很簡單。這裝置對於像是 GP2D12 距離感測器等擁有輸出電壓介於 0 到 2.4 伏特的感測器來說是很有用的。 在執行程式前修改 Cnts2Mv 來不斷地反映 Vref 的改變。每個位元等於 0.01 伏特(1/100),我們可以乘以 10 來轉換成毫伏特(1/1000)。

Cnts2Mv CON $0A00 ' x 10 (to millivolts)

請注意 ADC0831 不能測量低於 0 伏特的電壓( 低值為 0),他不能測量高於 Vref的電壓。如果介於針腳 2 和針腳 3 間的電壓差大於 Vref,輸出將會被限制在 255。當電壓可能會超過 Vref 時記住這些設計的限制。

Page 168: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

165

實驗#29:溫度測量 這個實驗說明使用數位溫度感測器 IC:DS1620。精確的溫度測量是一個必要的環境控制應用(用於空調上)。

查一查:必須要知道的 PBASIC 元素

• LSBFIRST (用於 SHIFTOUT)

• LSBPRE (用於 SHIFTIN)

• BYTE0, BYTE1 (變數修改器 variable modifier)

建立電路

程式: SW21-EX29-DS1620-Simple.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program measures temperature using the Dallas Semiconductor DS1620 ' temperature sensor. Resolution is 0.5 degrees Celsius. ' -----[ I/O Definitions ]-------------------------------------------------

Page 169: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

166

DQ CON 0 ' DS1620.1 (data I/O) Clock CON 1 ' DS1620.2 Reset CON 2 ' DS1620.3 ' -----[ Constants ]------------------------------------------------------- RdTmp CON $AA ' read temperature WrHi CON $01 ' write TH (high temp) WrLo CON $02 ' write TL (low temp) RdHi CON $A1 ' read TH RdLo CON $A2 ' read TL RdCntr CON $A0 ' read counter RdSlope CON $A9 ' read slope StartC CON $EE ' start conversion StopC CON $22 ' stop conversion WrCfg CON $0C ' write config register RdCfg CON $AC ' read config register DegSym CON 186 ' degrees symbol ' -----[ Variables ]------------------------------------------------------- tempIn VAR Word ' raw temperature sign VAR tempIn.BIT8 ' 1 = negative temperature tC VAR Word ' Celsius tF VAR Word ' Fahrenheit ' -----[ Initialization ]-------------------------------------------------- Setup: HIGH Reset ' alert the DS1620 SHIFTOUT DQ, Clock, LSBFIRST, [WrCfg, %10] ' use with CPU; free-run LOW Reset PAUSE 10 HIGH Reset SHIFTOUT DQ, Clock, LSBFIRST, [StartC] ' start conversions LOW Reset DEBUG CLS, "DS1620 ", CR, "---------" ' -----[ Program Code ]---------------------------------------------------- Main: DO

Page 170: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

167

GOSUB Read_DS1620 ' get the temperature Display_C: DEBUG CRSRXY, 0, 2, (tC.BIT15 * 13 + " "), DEC (ABS tC / 10), ".", DEC1 (ABS tC), DegSym, " C", CLREOL Display_F: DEBUG CRSRXY, 0, 3, (tF.BIT15 * 13 + " "), DEC (ABS tF / 10), ".", DEC1 (ABS tF), DegSym, " F", CLREOL PAUSE 1000 ' delay between readings LOOP ' -----[ Subroutines ]----------------------------------------------------- Read_DS1620: HIGH Reset ' alert the DS1620 SHIFTOUT DQ, Clock, LSBFIRST, [RdTmp] ' give command to read temp SHIFTIN DQ, Clock, LSBPRE, [tempIn\9] ' read it in LOW Reset ' release the DS1620 tempIn.BYTE1 = -sign ' extend sign bit tC = tempIn * 5 ' convert to tenths IF (tC.BIT15 = 0) THEN ' temp C is positive tF = tC */ $01CC + 320 ' convert to F ELSE ' temp C is negative tF = 320 - ((ABS tC) */ $01CC) ' convert to F ENDIF RETURN

幕後 人體上 大的器官是皮膚,也是 容易被溫度所影響。難怪那麼多人投入環境控制系統(用於空調上)。 這項實驗用 Dallas Semiconductor 的 DS1620 數位溫度/恆溫晶片。這個晶片測量溫度並且透過一個同步序列介面傳送數值到 BASIC Stamp。DS1620 是一個智能裝置,可程式化,可以用 THi、TLo 和 TCom 單獨操作來控制輸出。

Page 171: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

168

連接 DS1620 和其他同步序列裝置是一樣的,唯一的例外是在 DQ 傳輸線上的 1K電阻。不要讓他離開;DS1620 的 DQ 針腳是雙向的,所以他可以-在適當的條件下-成為一個輸出和在 BASIC Stamp 針腳相反狀態連接在一起。這種狀況可能造成傷害到一個裝置或其他設備。1K 電阻限制了 BASIC Stamp 和 DS1620 間的電流到安全到程度能避免程式出錯的傷害。 DS1620 需要在使用前初始化。像這樣的活動應用中,DS1620 被裝配和 CPU 一起自由運行。裝配完後資料被送到 DS1620,需要一個 10 毫秒的延遲來讓裝配可以被寫入到 DS1620 內部的 EEPROM(這個延遲在每次寫進 EEPROM 時都需要)。延遲後,DS1620 被指示開始持續的轉換。這樣當 BASIC Stamp 呼叫他時能確保正確的溫度讀數。DS1620 需要大約一秒鐘來完成溫度轉換,所以要獲得新的溫度頻率間格不能小於一秒。 要檢索出目前的溫度,讀取溫度($AA)指令位元被送到 DS1620。然後 新的轉換數值會被讀回。回去的資料有 9 個位元寬,而保持溫度在半個攝氏單位中。Bit8

負責標示溫度。如果是負數(標示位元為 1),其他八個位元保持 2 的補數的單位數值。 標示位元擴展到 tempIn 上面的位元祖來允許正數或負數值在接下來的公式裡。這是需要的因為 BAISC Stamp 儲存負數值在 16 位元 2 的補數格式內,但是只有 9 個位元從 DS1620 回來。你看到標示利用下面測試程式如何得到額外的擴展:

DEBUG BIN8 -0, CR, ' %00000000 (positive) BIN8 -1 ' %11111111 (negative)

有了在 tempIn 中完整的(符號)的 16 位元數值,攝氏溫度靠 tempIn 乘以 5。如果目前的溫度是 22.5 度 C,tC 得保持在 255。

Page 172: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

169

為了要轉換攝氏(十分之一)到華氏(同樣是十分之一)一個標準的溫度轉換會被用到: Ftenths = (Ctenths * 1.8) + 320 請注意從標準的式子中轉換 32 度同樣要乘以 1/10。 對於轉換負數溫度,方程式裡元素中的順序就不能用了,原因在於負數不能在PBASIC 中被除。ABS 運算子被用來轉換中間的結果成為正數值。當減去 320 其結果當會對齊(並且被符號化 signed);一些在攝氏範圍內的負數值在華氏仍是正數。 顯示動作用一個小技巧:來看數值中的 Bit15;如果 Bit15 是 1 然後溫度就是負數而且一個”-”將放在溫度讀數前,另外一個空格也會被印出來。

Page 173: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

170

更進一步 DS1620 有恆溫輸出,這樣可以被用來控制其他裝置。這些輸出通常被用來在單機模式下,但是當 DS1620 和 BASIC Stamp 或其他裝置連接時同樣可以自主動作。連接兩個 LED 燈到 DS1620 THi 和 TLo 輸出如圖所示:

ˊ

和 LED 燈連接,增加下面的程式碼在 DS1620 初始化後面: Set_Alarms: HIGH Reset tC = (THi - 32 */ $008E) * 2 ' convert to 0.5 C SHIFTOUT DQ, Clock, LSBFIRST, [WrHi, tC\9] ' write high temp LOW Reset PAUSE 10 HIGH Reset tC = (TLo - 32 * 5 / 9) * 2 SHIFTOUT DQ, Clock, LSBFIRST, [WrLo, tC\9] ' write low temp LOW Reset PAUSE 10

幕後 當目前溫度等於或高於儲存在高-溫度暫存器中的數值,THi 輸出將會變成高位元。當目前溫度等於或低於低-溫度暫存器時,TLo 輸出將會變成高位元。

Page 174: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

171

在程式中定值 THi 和 TLo 被用來設定高或低溫度的閥值。在被寫入到適當的暫存器前,這些數值表示整個華氏的度數和被轉換成攝氏的半度。 Chalf = (F - 32) x 5 / 9 x 2

後,請注意在設定適當暫存器中,一個 10 毫秒的 PAUSE 在每次 EEPROM 寫入時是被需要的。當閥值被寫入到恆溫暫存器,THi 和 TLo 將會獨立運作且不用透過程式介面。BASIC Stamp 可以讀取適當暫存器來取得 DS1620THi 和 TLo 的狀態。請看實驗#30。

Page 175: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

172

實驗#30:高精度溫度測量 這個實驗說明如何進階的使用 DS1620 溫度感測器,允許高精度(0.05℃)的測量。

建立電路 使用實驗#29 的電路。

程式: SW21-EX30-DS1620-HiRes.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program measures temperature using the Dallas Semiconductor DS1620 ' temperature sensor. Resolution is <0.05 degrees Celsius. ' ' NOTE: After downloading program, power must be cycled for proper ' operation. ' -----[ I/O Definitions ]------------------------------------------------- DQ CON 0 ' DS1620.1 (data I/O) Clock CON 1 ' DS1620.2 Reset CON 2 ' DS1620.3 ' -----[ Constants ]------------------------------------------------------- RdTmp CON $AA ' read temperature WrHi CON $01 ' write TH (high temp) WrLo CON $02 ' write TL (low temp) RdHi CON $A1 ' read TH RdLo CON $A2 ' read TL RdCntr CON $A0 ' read counter RdSlope CON $A9 ' read slope StartC CON $EE ' start conversion StopC CON $22 ' stop conversion WrCfg CON $0C ' write config register RdCfg CON $AC ' read config register DegSym CON 186 ' degrees symbol

Page 176: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

173

' -----[ Variables ]------------------------------------------------------- tempIn VAR Word ' raw temperature config VAR Byte ' configuration register done VAR config.BIT7 ' 1 when conversion done tHiFlag VAR config.BIT6 ' 1 when temp >= THi tLoFlag VAR config.BIT5 ' 1 when temp <= TLo busy VAR config.BIT4 ' 1 when EE update writing cRem VAR Word ' count remaining slope VAR Word ' slope (counts per degree) tC VAR Word ' Celsius tF VAR Word ' Fahrenheit ' -----[ Initialization ]-------------------------------------------------- Setup: HIGH Reset ' alert DS1620 SHIFTOUT DQ, Clock, LSBFIRST, [WrCfg, %11] ' with CPU, one-shot mode LOW Reset ' release DS1620 PAUSE 10 DEBUG CLS, "DS1620-HR ", CR, "----------" ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Read_DS1620_HR ' get hi-res temperature Display_C: DEBUG CRSRXY, 0, 2, (tC.BIT15 * 13 + " "), DEC (ABS tC / 100), ".", DEC2 (ABS tC), DegSym, " C", CLREOL Display_F: DEBUG CRSRXY, 0, 3, (tF.BIT15 * 13 + " "), DEC (ABS tF / 100), ".", DEC2 (ABS tF), DegSym, " F", CLREOL LOOP

Page 177: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

174

' -----[ Subroutines ]----------------------------------------------------- Read_DS1620_HR: ' get hi-resolution temp HIGH Reset ' alert the DS1620 SHIFTOUT DQ, Clock, LSBFIRST, [StartC] ' start conversion LOW Reset ' release the DS1620 DO HIGH Reset SHIFTOUT DQ, Clock, LSBFIRST, [RdCfg] ' read config register SHIFTIN DQ, Clock, LSBPRE, [config\8] LOW Reset LOOP UNTIL (done = 1) ' wait for conversion HIGH Reset SHIFTOUT DQ, Clock, LSBFIRST, [RdTmp] ' read raw temperature SHIFTIN DQ, Clock, LSBPRE, [tempIn\9] LOW Reset HIGH Reset SHIFTOUT DQ, Clock, LSBFIRST, [RdCntr] ' read counter SHIFTIN DQ, Clock, LSBPRE, [cRem\9] LOW Reset HIGH Reset SHIFTOUT DQ, Clock, LSBFIRST, [RdSlope] ' read slope SHIFTIN DQ, Clock, LSBPRE, [slope\9] LOW Reset tempIn = tempIn >> 1 ' remove half degree bit tempIn.BYTE1 = -tempIn.BIT7 ' extend sign bit tC = tempIn * 100 ' convert to 100ths tC = tC - 25 + (slope - cRem * 100 / slope) ' fix fractional temp IF (tC.BIT15 = 0) THEN tF = tC */ $01CC + 3200 ' convert pos C to Fahr ELSE tF = 3200 - ((ABS tC) */ $01CC) ' convert neg C to Fahr ENDIF RETURN

幕後

深入探索 DS1620 的運作我們發現溫度是被兩個溫度-控制的振盪器所得到的。當一個振盪器轉動-超過另一個被決定的週期路徑,溫度計數器-已經被預先載入-55℃-得到增加。分數溫度可以被看轉換週期 後計數剩下的和比較另外一個暫存器所決定,這樣被叫做斜率累加器。斜率累加器的目的在於校準振盪器的非線性動作所影響的溫度。

Page 178: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

175

對於高精度溫度測量我們可以讀取溫度,移除半-度位元(被 DS1620 電路預測),然後從斜率和計數保持暫存器中計算小數部份用的數值。下面的公式是用來計算DS1620 的高精度溫度: tC = (tempIn / 2) – 0.25 + ((slope – remaining) / slope) 要在這模式使用 DS1620 需要一個稍微不同的初始化程序:為了要讀取斜率和計數保持暫存器,DS1620 必需為一次模式(one-shot mode)被程式化。請注意如果DS1620 已經透過連續的轉換預先被程式化了(如在實驗#29 中),在 DS1620 將作出適當反應前電源必須在為一次模式重新運作後重新開啟。 在一次模式中溫度透過傳送 StartC 指令被讀取($EE)然後連續讀取配置的暫存器直到 Bit7 被成高位元-這代表結束轉換循環。當循環完成溫度時,仍然繼續計數,而斜率暫存器可以從 DS1620 被讀取。請注意配置暫存器被用來送出結束轉換的訊息也對於 DS1620 的 THi 和 TLo 輸出保持住旗標(flag)。 高精度轉換透過移除半-度位元開始-這是透過位移 tempIn 往右一格來達成(當除或乘以 2 的次方(2,4,8,16…)用位移運算子來代替*或/會更有效率)。下一步是展開符號位元使 tempIn 保持在正確的 16 位元數值。位移操作只被用於已經被移動過的符號位元;現在他的位置是在 Bit7。溫度是當時轉換到第 100 次來保持從這個程序下的可用的結果,而且上面提供的公式導出 tC。請注意高精度的參數也已經被轉換了 100 次了。如果當下的溫度是 23.75℃,tC 現在應該保持在 2375。

Page 179: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

176

Page 180: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

177

實驗#31:進階七段顯示器多路傳輸 這個實驗說明利用一個額外的多路傳輸控制器來使用七段顯示器。多位數的七段顯示器常用來在投幣機來顯示大量的輸入金額。

建立電路

連接 4 個按鈕至 P4 到 P7(請看實驗#14)並添加下面的多路傳輸電路。

Page 181: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

178

程式: SW21-EX31-MC14489.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program is a coin counter -- it will count nickels, dimes, quarters, ' and dollars using pushbutton inputs. The "bank" is displayed on four ' 7-segment LED displays that are controlled with a MC14489. ' -----[ I/O Definitions ]------------------------------------------------- Clock PIN 0 ' shift clock (MC14489.11) SerData PIN 1 ' serial data (MC14489.12) Enable PIN 2 ' enable (MC14489.10) Coins VAR INB ' coin inputs (P4 - P7) ' -----[ Constants ]------------------------------------------------------- FullValue CON 500 ' bank full = $5.00 ' Hex values for Letters Ltr_F CON $F ' display in Hex mode ' Special Decode characters Blank CON $0 ' display in Special mode Ltr_U CON $A Ltr_L CON $5 ' -----[ Variables ]------------------------------------------------------- money VAR Word ' current money count idx VAR Nib ' loop counter deposit VAR Nib ' coins deposited nickel VAR deposit.BIT0 ' bit values of deposit dime VAR deposit.BIT1 quarter VAR deposit.BIT2 dollar VAR deposit.BIT3 config VAR Byte ' decode configuration dpCtrl VAR Nib ' decimal point control segs5 VAR Nib ' segs - digit 5 segs4 VAR Nib segs3 VAR Nib segs2 VAR Nib segs1 VAR Nib ' segs - digit 1

Page 182: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

179

' -----[ Initialization ]-------------------------------------------------- Reset: HIGH Enable ' disable MC14489 GOSUB Show_The_Money ' initialize display segs config = %00110001 ' use 3 digits, hex mode GOSUB Update_Cfg ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Get_Coins ' wait for coins LOOP UNTIL (deposit > 0) money = money + (nickel * 5) ' add coins money = money + (dime * 10) money = money + (quarter * 25) money = money + (dollar * 100) GOSUB Show_The_Money ' update the display PAUSE 250 IF (money < FullValue) THEN Main ' scan until full DO PAUSE 500 config.BIT0 = ~config.BIT0 ' toggle display GOSUB Update_Cfg LOOP ' -----[ Subroutines ]----------------------------------------------------- Get_Coins: deposit = %1111 ' enable all coin inputs FOR idx = 1 TO 10 deposit = deposit & ~Coins ' test inputs PAUSE 5 ' delay between tests NEXT RETURN ' Display money value until that value meets or ' exceeds the bank limit. Show_The_Money: IF (money < FullValue) THEN ' show money count dpCtrl = %1011 ' display bright, show DP segs5 = Blank segs4 = Blank

Page 183: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

180

segs3 = money DIG 2 ' dollar digit segs2 = money DIG 1 ' tens digit segs1 = money DIG 0 ' ones digit GOSUB Update_Segs ELSE ' show "FULL" config = Blank GOSUB Update_Cfg config = %11101111 ' setup for "FULL" dpCtrl = %1000 ' display bright, no DPs segs5 = Blank segs4 = Ltr_F ' F segs3 = Ltr_U ' U (Special Decode) segs2 = Ltr_L ' L (Special Decode) segs1 = Ltr_L ' L (Special Decode) GOSUB Update_Segs ' show message GOSUB Update_Cfg ' display on ENDIF RETURN ' Update MC14489 configuration register Update_Cfg: LOW Enable ' enable MC14489 SHIFTOUT SerData, Clock, MSBFIRST, [config] ' send config register HIGH Enable ' disable MC14489 RETURN ' Update MC14489 decimal point control and segments registers Update_Segs: LOW Enable SHIFTOUT SerData, Clock, MSBFIRST, [dpCtrl\4, segs5\4, segs4\4, segs3\4, segs2\4, segs1\4] HIGH Enable RETURN

幕後 對於已經說明過的實驗#10,多個七段顯示器需要很多努力,這樣消耗大量的 BASIC Stamp 的資料運算。放入 Motorola MC14489 顯示多工器。只透過三個 BASIC Stamp I/O 針腳就能有效的控制多達五個七段顯示器。介面是簡單的,允許顯示數字(所有十六進制值)、一些文字(可以被顯示在一個七段顯示器內的)和一些特別的符號(例如破折號、度等)。MC14489 同樣可以控制到 多 25 個單獨的 LED 燈(使用無解碼模式(No Decode Mode))。

Page 184: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

181

MC14489 連接到 LED 顯示器簡單的方法:針腳 A 到 H 連接到 A 段到 H 段和小數點的所有共陰極顯示器。針腳 BANK 1 到 BANK5 連接到顯示器上每個陰極上(Digit0到 Digit4)。如果你用少於 5 個 Digit,省略 高的 digit 數。例如,這個實驗用 4 個digit,數字從 0 到 3,所以 Digit4 就不必連接。 當 MC14449 被用在七段顯示器上,它可以被配置成自動轉換二進位編碼到十進位(BCD)值到適當的線段(segments)上-這被稱作十六進位解碼模式。這樣讓顯示十進位和十六進位數字非常簡單。 後無解碼模式下被用在數字暫存器的位元直接輸出(但是只有在線段 A 到 D;線段 E 到 G 在無解碼模式下是被關閉的)。 透過 MC14489 控制來獲得訊息到顯示器上的關鍵是理解配置暫存器和位元們交互作用來控制顯示器解碼。下面的表是瀏覽配置暫存器位元們和如何影響顯示器:

Bit0 0 = display blank; 1 = display on Bit1 0 = Hex Decode for Bank 1; 1 = Depends on Bit6 Bit2 0 = Hex Decode for Bank 2; 1 = Depends on Bit6 Bit3 0 = Hex Decode for Bank 3; 1 = Depends on Bit6 Bit4 0 = Hex Decode for Bank 4; 1 = Depends on Bit7 Bit5 0 = Hex Decode for Bank 5; 1 = Depends on Bit7 Bit6 0 = No Decode; 1 = Special Decode for Bank1 – Bank 3 Bit7 0 = No Decode; 1 = Special Decode for Bank4 – Bank 5

傳送資料到 MC14489 有兩種方法:1)八位元配置暫存器被送出,或 2)24 位元(6 個半字節)保持顯示訊息的傳播。這裡沒有資料的位址用於其他同步串聯裝置;MC14489 正確的路線資訊傳送到他基於同樣大小的封包。

Page 185: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

182

為了計數程式我們 初希望用十六進制(數字)來解 digit0 到 2 的碼、空白 digit 3

和 4,並且設定小數點在 digit 2 上。正確的配置暫存器數值為%00110001(回顧上面配置位元表)。Update_Cfg 子程式處理傳送配製暫存器到 MC14489。 小數點被一個被傳送到 MC1448 來顯示的 6 半字節大小的暫存器所控制。小數點的位置-如果使用的話-就會被轉換來讓 Update_Segs 子程式使用,與位每個顯示的數字控制變數在一起。 大部分的工作發生在被稱為 Show_The_Money 的子程式中。當 Money 計數小於500,這個值將會被顯示在七段顯示器上。這個程式掃瞄經過每個 money 的數字並且傳送數字的位置和數值(從 DIG 運算子)到 MC14489。由於顯示器顯示元和角,在第三個數字上的小數點會被啟用。 當 money 的數值到達或超過 500,顯示會改變成”FULL”。這是透過設定 Bank 1 到3(digit 0 到 2)成特定解碼以便字母”U”和”L”可以被顯示來完成。字母”F”是十六進制的數字設定所以 Bank 4(digit 3)被留在十六進制解碼模式。 程式的主要迴圈是簡單的:他掃瞄 Get_Coins 開關輸入和更新每個被按下的開關所產生的 money 計數。當”銀行”已經滿了,程式進入一個無限回圏來切換配置暫存器的顯示位元;這是一個簡單的方法來顯示而不用先改顯示內容。 挑戰 修改在實驗#28 的程式碼來顯示在七段顯示器上的輸入電壓。

Page 186: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

183

實驗#32:I2C 通訊 這個實驗說明 BASIC Stamp 透過使用 Philips I2C 協議來和其他裝置通訊的能力。這個實驗用這個協議來寫入和讀出資料到一個串聯的 EEPROM 用高-和低等級 I2C程式,這樣可以被用於和任何 I2C 裝置通訊。 建立電路

程式: SW21-EX32-24LC32.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates essential I2C interfacing by connecting to ' a 24LC32 EEPROM. The connections in the program conform to the BS2p ' I2CIN and I2COUT instructions. ' -----[ I/O Definitions ]------------------------------------------------- SDA PIN 8 ' I2C serial data line SCL PIN 9 ' I2C serial clock line ' -----[ Constants ]------------------------------------------------------- Ack CON 0 ' acknowledge bit

Page 187: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

184

Nak CON 1 ' no ack bit EE24LC32 CON %1010 << 4 ' device ID ' -----[ Variables ]------------------------------------------------------- slvAddr VAR Byte ' I2C slave address devNum VAR Nib ' device number (0 - 7) addrLen VAR Nib ' bytes in word addr (0 - 2) wrdAddr VAR Word ' word address i2cData VAR Byte ' data to/from device i2cWork VAR Byte ' work byte for TX routine i2cAck VAR Bit ' Ack bit from device test VAR Nib outVal VAR Byte inVal VAR Byte fails VAR Word ' -----[ Initialization ]-------------------------------------------------- Reset: #IF ($STAMP >= BS2P) #THEN #ERROR "Please use BS2p version: SW21-EX32-24LC32.BSP" #ENDIF Setup: devNum = %000 ' chip select (%000 - %111) slvAddr = EE24LC32 | (devNum << 1) ' setup slave ID addrLen = 2 ' 2 bytes in word address DEBUG CLS, "24LC32 Demo ", CR, "---------------", CR, "Address... ", CR, "Output.... ", CR, "Input..... ", CR, "Status.... ", CR, "Errors.... " ' -----[ Program Code ]---------------------------------------------------- Main: fails = 0 FOR wrdAddr = 0 TO 4095 ' test all locations DEBUG CRSRXY, 11, 2, DEC4 wrdAddr FOR test = 0 TO 3 ' use four patterns

Page 188: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

185

LOOKUP test, [$FF, $AA, $55, $00], outVal DEBUG CRSRXY, 11, 3, IHEX2 outVal i2cData = outVal GOSUB Write_Byte PAUSE 10 GOSUB Read_Byte inVal = i2cData DEBUG CRSRXY, 11, 4, IHEX2 inVal, CRSRXY, 11, 5 IF (inVal = outVal) THEN DEBUG "Pass " ELSE fails = fails + 1 DEBUG "Fail ", CRSRXY, 11, 6, DEC fails EXIT ' terminate location ENDIF PAUSE 10 NEXT NEXT IF (fails = 0) THEN DEBUG CRSRXY, 11, 6, "None. All locations test good." ENDIF END ' =====[ High Level I2C Subroutines]======================================= ' Random location write ' -- pass device slave address in "slvAddr" ' -- pass bytes in word address (0, 1 or 2) in "addrLen" ' -- word address to write passed in "wrdAddr" ' -- data byte to be written is passed in "i2cData" Write_Byte: GOSUB I2C_Start ' send Start i2cWork = slvAddr & %11111110 ' send slave ID (write) GOSUB I2C_TX_Byte IF (i2cAck = Nak) THEN Write_Byte ' wait until not busy IF (addrLen > 0) THEN IF (addrLen = 2) THEN i2cWork = wrdAddr.BYTE1 ' send word address (1) GOSUB I2C_TX_Byte ENDIF i2cWork = wrdAddr.BYTE0 ' send word address (0) GOSUB I2C_TX_Byte ENDIF i2cWork = i2cData ' send data GOSUB I2C_TX_Byte GOSUB I2C_Stop RETURN

Page 189: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

186

' Random location read ' -- pass device slave address in "slvAddr" ' -- pass bytes in word address (0, 1 or 2) in "addrLen" ' -- word address to write passed in "wrdAddr" ' -- data byte read is returned in "i2cData" Read_Byte: GOSUB I2C_Start ' send Start IF (addrLen > 0) THEN i2cWork = slvAddr & %11111110 ' send slave ID (write) GOSUB I2C_TX_Byte IF (i2cAck = Nak) THEN Read_Byte ' wait until not busy IF (addrLen = 2) THEN i2cWork = wrdAddr.BYTE1 ' send word address (1) GOSUB I2C_TX_Byte ENDIF i2cWork = wrdAddr.BYTE0 ' send word address (0) GOSUB I2C_TX_Byte GOSUB I2C_Start ENDIF i2cWork = slvAddr | %00000001 ' send slave ID (read) GOSUB I2C_TX_Byte GOSUB I2C_RX_Byte_Nak GOSUB I2C_Stop i2cData = i2cWork RETURN ' -----[ Low Level I2C Subroutines ]--------------------------------------- ' *** Start Sequence *** I2C_Start: ' I2C start bit sequence INPUT SDA INPUT SCL LOW SDA Clock_Hold: DO : LOOP UNTIL (SCL = 1) ' wait for clock release RETURN ' *** Transmit Byte *** I2C_TX_Byte: SHIFTOUT SDA, SCL, MSBFIRST, [i2cWork\8] ' send byte to device SHIFTIN SDA, SCL, MSBPRE, [i2cAck\1] ' get acknowledge bit RETURN ' *** Receive Byte ***

Page 190: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

187

I2C_RX_Byte_Nak: i2cAck = Nak ' no Ack = high GOTO I2C_RX I2C_RX_Byte: i2cAck = Ack ' Ack = low I2C_RX: SHIFTIN SDA, SCL, MSBPRE, [i2cWork\8] ' get byte from device SHIFTOUT SDA, SCL, LSBFIRST, [i2cAck\1] ' send ack or nak RETURN ' *** Stop Sequence *** I2C_Stop: ' I2C stop bit sequence LOW SDA INPUT SCL INPUT SDA RETURN

幕後

I2C 匯流排是一個用在零件間主-從(Maser-Slave)關係的雙線、同步匯流排。Master開始和 Slave 通訊而且負責產生時脈訊號。如果要求這樣作,Slave 可以傳送資料回 Master。這代表資料針腳(SDA)是雙向的,而且時脈針腳(SCL)(經常)被Master 所完全控制。 Mastet 和 Slave 間的轉換資料像這樣: Master 傳送資料

Master 開始轉換 Mastet 定址 Slave Master 傳送資料到 Slave Master 停止轉換

Master 接收資料

Master 開始傳送 Maser 定址 Slave Master 從 Slave 接收資料 Master 結束轉換

Page 191: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

188

I2C規範事實上是允許多個Master存在在一個共同的匯流排上而且提供一個方法來仲裁他們。這樣有點超過我們需要讓事情簡單化的範圍。在我們的設定裡,BS2(或BS2e 或 BS2sx)將會當 Master 而其任何連接他的將會變成 Slave。 你將會注意到在 I2C 規範中,SDA(串連資料)和 SCL(串聯時脈)傳輸線被拉到Vdd(經常透過 4.7kΩ)。這樣的規格需要裝置匯流排針腳打開流乾。要讓其他傳輸線變成高電位,相關的匯流排針腳被做成一個輸入(浮動)和拉傳輸線到 Vdd。要讓傳輸線變成低電位,匯流排針腳拉它到 Vss(ground)。 這個計畫是被設計成保護在匯流排上的裝置防止短路到地面。因為沒有其他傳輸線是高電位,所以沒有危險。現在我們將要消除一個位元。不是寫程式碼來讓傳輸線變成低電位或釋放他(當然有可能-我做過),我們將要用 SHIFTOUT 和 SHIFTIN

來移動資料的往來。如果你擔心一個短路的匯流排在 SHIFTOUT 和 SHIFTIN 之間傷害到 BASIC Stamp 的 SDA 或 SCL 針腳,你可以在他們上面各加上一個 220 歐姆的電阻來保護他們。如果你小心的佈線和寫程式,這樣就沒有很必要了。 初階 I2C 程式碼 關於初階的通訊,I2C Master 需要做下面四件事情:

產生一個開始條件 轉換 8 位元資料到 Slave 接收從 Slave 來的八位元資料-有或沒有收到 產生一個停止條件

一個開始條件是被一個在 SDA 傳輸線上的高電位到低電位轉換且 SCL 傳輸線為高電位時所定義。所有的傳輸都從在 S 一個開始條件開始。一個停止條件是被一個DA 傳輸線上的高電位到低電位轉換且時脈傳輸線為高電位時所定義。結束條件結束轉換且可以用來終止他。

Page 192: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

189

當 Slave 裝置可以控制 SCL 傳輸線,這邊會有一個短暫的週期。如果一個 Slave還沒準備好傳輸或接收資料,它可以在開始條件後保持 SCL 傳輸線在低位元。Master 可以監控這些來等待 Slave 準備好。BS2 的速度上,監控時脈傳輸線經常是不必要的但是監控”時脈保持”的能力是被建立在 I2C_Start 子程式來讓它是安全的。 對於我們的實驗我們將會用到 7 位元定址(見下圖),slave 位址位元組中的較高的七個位元包含設備型態和位址,而位元 0 保持住資料的方向:”0”表示設備寫入;”1”代表裝置讀取。下面的 slave 位址將會不同,取決於裝置上和要求的型態。大部分的 I2C 裝置擁有一或兩個位址位元組,可以透過資料位元組跟隨著從裝置中被寫進或讀入。

被轉換的資料每次是 8 個位元,先傳送 MSB。在每個位元組後,I2C 規範呼叫接收裝置透過匯流排第九個時脈變成低位元來收到傳輸。唯一的例外是當 Master 是接收者而且是從 Slave 接收 後的位元組。在這裡,沒有接收位元從 Master 送到Slave。 從一個特定的 slave 傳送和接收資料都是需要一個開始條件,傳送 Slave 位址以及在 後的停止條件。Slave 位址和停止間發生的事是看裝置和應用的程序。

Page 193: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

190

你將需要作的事是得到一個你想要連接到的 I2C 裝置資料表。你將會發現大部分的I2C 資料表-大部分有一個非常清楚的通訊定義-通常在符號格式-這使得執行初階I2C 程式變的簡單。 適用初階 I2C 程式的實驗來執行 Write_Byte 和 Read_Byte 程式。這些程式被產生用來運作於任何 I2C 裝置,允許 slave 位址,位址位元數和用來讀取或寫入的位址(如果需要的話)。請注意每個程式開始都有 I2C 開始條件而且還有停止的終止條件。傳送裝置指令/型態程式碼間的程式碼和位址去處理,然後確實處理(寫入或讀取)這些資料。雖然這需要幾行的程式碼,但是它實際上是非常簡單明瞭的。 是範例程式迴圏的核心通過 24LC32 EEPROM 有效的位址,寫入和讀取回 4 個不同的位元部份。如果數值讀回沒有吻合被寫入的數值,fails 的變數就會增加。Debug Terminal window 給予程式正確的狀態如下所示。注意每個位址用了 4096 個位址和4 個寫入和讀取,這個程式需要多點時間來完成。

Page 194: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

191

Page 195: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

192

實驗#33:使用即時時鐘 這實驗用 I2C 框架來發展實驗#32 裡的和一個 DS1307 即時時鐘晶片做通訊。RTC時間功能和管理對於以時間為主的應用很重要,而這應用需要測量時間間隔。

查一查:必須要知道的 PBASIC 元素

• HEX, HEX1 – HEX4 (用於 DEBUG)

建立電路 連接四個按鈕到 p4 到 p7(請看實驗#14)和連接 DS1307 如下圖所示:

Page 196: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

193

程式: SW21-EX33-DS1307.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates the access and control of an external real- ' time-clock chip, the DS1307. ' -----[ I/O Definitions ]------------------------------------------------- SDA PIN 0 ' I2C serial data line SCL PIN 1 ' I2C serial clock line BtnBus VAR INB ' four inputs, pins 4 - 7 ' -----[ Constants ]------------------------------------------------------- Ack CON 0 ' acknowledge bit Nak CON 1 ' no ack bit DS1307 CON %1101 << 4 ' -----[ Variables ]------------------------------------------------------- slvAddr VAR Byte ' I2C slave address devNum VAR Nib ' device number (0 - 7) addrLen VAR Nib ' bytes in word addr (0 - 2) wrdAddr VAR Word ' word address i2cData VAR Byte ' data to/from device i2cWork VAR Byte ' work byte for TX routine i2cAck VAR Bit ' Ack bit from device secs VAR Byte ' DS1307 time registers mins VAR Byte hrs VAR Byte day VAR Byte ' weekday date VAR Byte ' day in month, 1 - 31 month VAR Byte year VAR Byte control VAR Byte ' SQW I/O control btns VAR Nib ' debounced button inputs btnBack VAR btns.BIT3 ' roll back btnDay VAR btns.BIT2 ' +/- day btnHr VAR btns.BIT1 ' +/- hours btnMn VAR btns.BIT0 ' +/- minutes idx VAR Nib ' loop control

Page 197: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

194

pntr VAR Byte ' ee pointer char VAR Byte ' character for display ' -----[ EEPROM Data ]----------------------------------------------------- DayNames DATA "SunMonTueWedThuFriSat" ' -----[ Initialization ]-------------------------------------------------- Reset: #IF ($STAMP >= BS2P) #THEN #ERROR "Please use BS2p version: SW21-EX33-DS1307.BSP" #ENDIF Setup: slvAddr = DS1307 ' 1 byte in word address addrLen = 1 DEBUG CLS, "DS1307 Demo", CR, "-----------" Reset_Clock: GOSUB Get_Buttons ' scan buttons idx = btns & %0011 ' isolate hrs & mins IF (idx = %11) THEN ' if both pressed, reset secs = $00 mins = $00 hrs = $06 ' 6:00 AM day = $07 ' Saturday date = $01 ' 1st month = $01 ' January year = $05 ' 2005 control = 0 ' disable SQW output GOSUB Set_Clock ' block write clock regs ENDIF ' -----[ Program Code ]---------------------------------------------------- Main: GOSUB Get_Clock ' read DS1307 hrs = hrs & $3F DEBUG CRSRXY, 0, 2, HEX2 hrs, ":", HEX2 mins, ":", HEX2 secs, CR GOSUB Print_Day PAUSE 100 GOSUB Get_Buttons IF (btns > %0000) THEN ' button pressed? IF (btns <> %1000) THEN ' ignore back only hrs = hrs.NIB1 * 10 + hrs.NIB0 ' BCD to decimal

Page 198: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

195

mins = mins.NIB1 * 10 + mins.NIB0 IF (btnBack = 0) THEN ' increment values day = ((day - 1) + btnDay // 7) + 1 ' keep 1 - 7 hrs = hrs + btnHr // 24 ' keep 0 - 23 mins = mins + btnMn // 60 ' keep 0 - 59 ELSE day = ((day - 1) + (btnDay * 6) // 7) + 1 hrs = hrs + (btnHr * 23) // 24 mins = mins + (btnMn * 59) // 60 ENDIF hrs = (hrs / 10 << 4) + (hrs // 10) ' decimal to BCD mins = (mins / 10 << 4) + (mins // 10) secs = $00 GOSUB Set_Clock ' update DS1307 ENDIF ENDIF GOTO Main ' -----[ Subroutines ]----------------------------------------------------- Get_Buttons: btns = %1111 ' enable all four inputs FOR idx = 1 TO 5 btns = btns & ~BtnBus ' test inputs PAUSE 5 ' delay between tests NEXT RETURN Print_Day: pntr = DayNames + ((day - 1) * 3) ' point to 1st char FOR idx = 0 TO 2 ' print 3 letters READ (pntr + idx), char ' read letter DEBUG char ' print it NEXT RETURN ' Do a block write to clock registers Set_Clock: GOSUB I2C_Start ' send Start i2cWork = slvAddr & %11111110 ' send slave ID (write) GOSUB I2C_TX_Byte IF (i2cAck = Nak) THEN Set_Clock ' wait until not busy i2cWork = 0 ' point at secs register GOSUB I2C_TX_Byte FOR idx = 0 TO 7 ' write secs to control

Page 199: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

196

i2cWork = secs(idx) GOSUB I2C_TX_Byte NEXT GOSUB I2C_Stop RETURN ' Do a block read from clock registers Get_Clock: GOSUB I2C_Start ' send Start i2cWork = slvAddr & %11111110 ' send slave ID (write) GOSUB I2C_TX_Byte IF (i2cAck = Nak) THEN Get_Clock ' wait until not busy i2cWork = 0 ' point at secs register GOSUB I2C_TX_Byte GOSUB I2C_Start i2cWork = slvAddr | %00000001 ' send slave ID (read) GOSUB I2C_TX_Byte FOR idx = 0 TO 6 ' read secs to year GOSUB I2C_RX_Byte secs(idx) = i2cWork NEXT GOSUB I2C_RX_Byte_Nak ' read control control = i2cWork GOSUB I2C_Stop RETURN ' =====[ High Level I2C Subroutines]======================================= ' Random location write ' -- pass device slave address in "slvAddr" ' -- pass bytes in word address (0, 1 or 2) in "addrLen" ' -- word address to write passed in "wrdAddr" ' -- data byte to be written is passed in "i2cData" Write_Byte: GOSUB I2C_Start ' send Start i2cWork = slvAddr & %11111110 ' send slave ID (write) GOSUB I2C_TX_Byte IF (i2cAck = Nak) THEN Write_Byte ' wait until not busy IF (addrLen > 0) THEN IF (addrLen = 2) THEN i2cWork = wrdAddr.BYTE1 ' send word address (1) GOSUB I2C_TX_Byte ENDIF i2cWork = wrdAddr.BYTE0 ' send word address (0) GOSUB I2C_TX_Byte ENDIF i2cWork = i2cData ' send data GOSUB I2C_TX_Byte

Page 200: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

197

GOSUB I2C_Stop RETURN ' Random location read ' -- pass device slave address in "slvAddr" ' -- pass bytes in word address (0, 1 or 2) in "addrLen" ' -- word address to write passed in "wrdAddr" ' -- data byte read is returned in "i2cData" Read_Byte: GOSUB I2C_Start ' send Start IF (addrLen > 0) THEN i2cWork = slvAddr & %11111110 ' send slave ID (write) GOSUB I2C_TX_Byte IF (i2cAck = Nak) THEN Read_Byte ' wait until not busy IF (addrLen = 2) THEN i2cWork = wrdAddr.BYTE1 ' send word address (1) GOSUB I2C_TX_Byte ENDIF i2cWork = wrdAddr.BYTE0 ' send word address (0) GOSUB I2C_TX_Byte GOSUB I2C_Start ENDIF i2cWork = slvAddr | %00000001 ' send slave ID (read) GOSUB I2C_TX_Byte GOSUB I2C_RX_Byte_Nak GOSUB I2C_Stop i2cData = i2cWork RETURN ' -----[ Low Level I2C Subroutines]---------------------------------------- ' *** Start Sequence *** I2C_Start: ' I2C start bit sequence INPUT SDA INPUT SCL LOW SDA Clock_Hold: DO : LOOP UNTIL (SCL = 1) ' wait for clock release RETURN ' *** Transmit Byte *** I2C_TX_Byte: SHIFTOUT SDA, SCL, MSBFIRST, [i2cWork\8] ' send byte to device SHIFTIN SDA, SCL, MSBPRE, [i2cAck\1] ' get acknowledge bit RETURN

Page 201: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

198

' *** Receive Byte *** I2C_RX_Byte_Nak: i2cAck = Nak ' no Ack = high GOTO I2C_RX I2C_RX_Byte: i2cAck = Ack ' Ack = low I2C_RX: SHIFTIN SDA, SCL, MSBPRE, [i2cWork\8] ' get byte from device SHIFTOUT SDA, SCL, LSBFIRST, [i2cAck\1] ' send ack or nak RETURN ' *** Stop Sequence *** I2C_Stop: ' I2C stop bit sequence LOW SDA INPUT SCL INPUT SDA RETURN

幕後

雖然用 PAUSE 在程式碼中執行基本的計時功能是有可能的,但是當 BASIC Stamp需要處理其他事情時就會出問題。特別是當一個裝置需要處理時間、星期、日期時。

直接的方法就是增加一個額外的即時時鐘。在實驗裡,我們將會用到Maxim-Dallas DS1307。就像 24LC32 一樣,DS1307 透過一條 I2C 匯流排連接到令一邊。不像是 24LC32,他不能定址,所以只有一個 DS1307 可以存在在所給的I2C 匯流排上。 一但程式透過自己運行了 DS1307 他就會準確的持續追蹤秒、分、小時、星期、日期、月、年(閏年補償到 2100 年)和一個用於 SQW 輸出的控制暫存器。當作一種獎勵,DS1307 含有 56 位元組的記憶體(記憶體$08 到$3E)這可以用來生產-目的的記憶體。而且為了計畫,DS1307 主要的電源是靠簡單的 3v 鋰電池(可用長達 10 年以上)。 就像大部分的 I2C 裝置,DS1307 是根基於暫存器的,每個時間和日期的元素被儲存在他們自己的暫存器中(記憶體位址)。為了方便起見,讀取和寫入的兩種模式是可作用的:暫存器(register)和區塊(block)。在暫存器存取(register access)中,個別元素可以被寫入或讀取。在區塊存取(block access)中,我們趁機自動

Page 202: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

199

遞增 DS1307 的內部位址指標;這樣位元組團允許從 DS1307 被寫入或讀取透過指定的區塊開始位址。

Page 203: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

200

值得注意的是 Set_Clock 和 Get_Clock 子程式用區塊模式來讀取和寫入從/到DS1307 的八個位元組團。同樣要注意的是這些子程式利用 PBASIC 允許記憶體空間被處理成像是一個陣列-甚至當一個陣列沒有被明確宣告。你將會看在兩個程式裡的 secs 被用在基於陣列上。這代表分鐘暫存器(minutes register)和 secs(1)相符,小時和 secs(2)相符等等。下面的清單顯示時鐘暫存器如何繪製內含的的secs()陣列。

secs VAR Byte ' secs(0) mins VAR Byte ' secs(1) hrs VAR Byte ' secs(2) day VAR Byte ' secs(3) date VAR Byte ' secs(4) month VAR Byte ' secs(5) year VAR Byte ' secs(6) control VAR Byte ' secs(7)

就如你清單上看到的,陣列元素都是根據同樣變數型態的宣告順序;改變宣告的順序將會改變陣列的位置。這是個非常強大的技術因為 PBASIC 不允許宣告其他的陣列元素。使用上面這個技術給你 大的程式修改空間。 在 Set_Clock 和 Get_Clock 子程式間有一個小差異必須和 I2C 協議規範一起做。在 Set_Clock 裡,在迴圈中所有的時間暫存器被寫到 DS1307。在 Get_Clock

裡,雖然,在迴圈中只有第一個七位元組被讀;而 後一個位元組在後來被讀取。原因是 I2C 規範要求在 後讀取動作後要有一個否定字元。 這個程式說明 BCD 轉換成十進制數值,並返回。DS1307 儲存時間暫存器中用BCD,這樣可以直接用 DEBUG 上的 HEX2 修改器來顯示,但是不能修改算數。半字節(NIB)修改器可以讓 Byte 和 Word 變數瞬間變成 BCD 轉十進制:

Page 204: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

201

decVal = (bcdVal.NIB1 * 10) + bcdVal.NIB0 一但數值已經被調整了,轉換回 BCD 也是同樣簡單:

bcdVal = (decVal / 10 << 4) + bcdVal // 10 對於四個連接的按鈕,三個是用來推進分、小時、天(當任何一個元素改變次等的都會被重設)。為了要推元素回來,第四個按鈕被保持著。注意模數運算子如何被使用來保持每個元素更新到程式碼的信號線上。 更進一步 關於在應用中基於時間上的數學運算是值得被擔心的,一個簡單的方法-如果用分鐘的結果是可以滿足的話-轉換時間到單一的數值到分鐘裡: rawTime = (hours * 60) + minutes 這會變成為一個從 0(午夜)到 1439(23:59 或 11:59PM)。有了這個單一數值,運算操作上更簡化。要換回小時和分鐘也同樣簡單: hours = rawTime / 60 hours = rawTime // 60 結果變成 24 小時制的時間。要轉成 12 小時制,計算小時如下所示: hours = 12 – (24 – (rawTime / 60) // 12) 要記算 AM/PM 的狀態,看 rawTimevalue;AM 時間介於 0 到 719,PM 時間介於720 到 1439。 挑戰 重新連接 MC22489 多工器和顯示在跑的時間到七段顯示器上。

Page 205: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

202

實驗#34:用電腦做串聯通訊 這個實驗說明了 BASIC Stamp 可以透過其他他的 IO 針腳來和其他電腦通訊。同樣要說明儲存非揮發性訊息在 BASIC Stamp 的 EEPROM 空間中的能力。 查一查:必須要知道的 PBASIC 元素

• SERIN • SEROUT

• WAIT (SERIN 修改器) • SELECT-CASE • WRITE

建立電路

Page 206: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

203

程式: SW21-EX34-Serial_IO.BS2 ' {$STAMP BS2} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' This program demonstrates serial communications with a PC, using flow ' control to ensure the BASIC Stamp is ready before the PC attempts to ' send new information. ' -----[ I/O Definitions ]------------------------------------------------- TX PIN 15 ' transmit to PC RTS PIN 14 ' Request To Send RX PIN 13 ' receive from PC CTS PIN 12 ' Clear To Send DQ CON 4 ' DS1620.1 (data I/O) Clock CON 5 ' DS1620.2 Reset CON 6 ' DS1620.3 LEDs VAR OUTA ' LED outputs ' -----[ Constants ]------------------------------------------------------- T2400 CON 396 ' True for inverter T9600 CON 84 T38K4 CON 6 SevenBit CON $2000 Inverted CON $4000 Open CON $8000 Baud CON T9600 CMenu CON $FF ' show command menu CGetId CON $F0 ' get string ID CSetId CON $F1 ' set string ID CTemp CON $A0 ' get DS1620,display raw count CTmpC CON $A1 ' get DS1620 - display in C CTmpF CON $A2 ' get DS1620 - display in F CGetLeds CON $B0 ' get digital output status CSetLeds CON $B1 ' set LED outputs RdTmp CON $AA ' read temperature WrHi CON $01 ' write TH (high temp) WrLo CON $02 ' write TL (low temp) RdHi CON $A1 ' read TH RdLo CON $A2 ' read TL

Page 207: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

204

RdCntr CON $A0 ' read counter RdSlope CON $A9 ' read slope StartC CON $EE ' start conversion StopC CON $22 ' stop conversion WrCfg CON $0C ' write config register RdCfg CON $AC ' read config register ' -----[ Variables ]------------------------------------------------------- cmd VAR Byte ' command from PC/terminal eeAddr VAR Byte ' EE address pointer param VAR Byte ' parameter to/from tempIn VAR Word ' raw data from DS1620 sign VAR tempIn.BIT8 ' 1 = negative temperature tC VAR Word ' degrees C in tenths tF VAR Word ' degrees F in tenths ' -----[ EEPROM Data ]----------------------------------------------------- ID DATA "StampWorks 2.1", CR ' CR-terminated string ' -----[ Initialization ]-------------------------------------------------- Setup: DIRA = %1111 ' LED pins are outputs HIGH Reset ' alert the DS1620 SHIFTOUT DQ, Clock, LSBFIRST, [WrCfg, %10] ' use with CPU; free-run LOW Reset PAUSE 10 HIGH Reset SHIFTOUT DQ, Clock, LSBFIRST, [StartC] ' start conversions LOW Reset GOSUB Show_Menu ' -----[ Program Code ]---------------------------------------------------- Main: cmd = 0 SERIN RX\CTS, Baud, [WAIT ("?"), HEX cmd] ' wait for ? and command SELECT cmd ' process command entry CASE CMenu GOSUB Show_Menu ' refresh menu CASE CGetId

Page 208: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

205

GOSUB Show_ID ' show ID string CASE CSetId GOSUB Set_ID ' set new ID GOSUB Show_ID ' confirm new ID CASE CTemp GOSUB Show_Temp ' show raw counts CASE CTmpC GOSUB Show_Temp_C ' show tC (tenths) CASE CTmpF GOSUB Show_Temp_F ' show tF (tenths) CASE CGetLeds GOSUB Show_Leds ' show LED status CASE CSetLeds GOSUB Set_Leds ' set LED status GOSUB Show_Leds ' confirm new status CASE ELSE SEROUT TX\RTS, Baud, ["Invalid command.", CR] ENDSELECT GOTO Main ' -----[ Subroutines ]----------------------------------------------------- Show_Menu: SEROUT TX\RTS, Baud, [CLS, "========================", CR, " StampWorks Monitor ", CR, "========================", CR, "?FF - Show Menu", CR, "?F0 - Display ID", CR, "?F1 - Set ID", CR, "?A0 - DS1620 (Raw count)", CR, "?A1 - Temperature (C)", CR, "?A2 - Temperature (F)", CR, "?B0 - Display LED Status", CR, "?B1 - Set LEDs", CR, CR, "Please enter a command.", CR, CR] RETURN Show_ID: SEROUT TX\RTS, Baud, ["ID = "] ' label output

Page 209: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

206

eeAddr = ID ' point to first character DO READ eeAddr, param ' read a character SEROUT TX\RTS, Baud, [param] ' print it eeAddr = eeAddr + 1 ' point to next LOOP UNTIL (param = CR) RETURN Set_ID: eeAddr = ID ' point to ID location DO SERIN RX\CTS, Baud, [param] ' get character from PC WRITE eeAddr, param ' write to EE eeAddr = eeAddr + 1 ' point to next location LOOP UNTIL (param = CR) ' CR = end of new ID RETURN Show_Temp: ' display raw counts GOSUB Read_DS1620 ' read temperature tempIn = tempIn & $1FF ' return to 9 bits SEROUT TX\RTS, Baud, ["DS1620 = ", DEC tempIn, CR] RETURN Show_Temp_C: GOSUB Read_DS1620 param = tC.BIT15 * 2 + "+" ' create sign char SEROUT TX\RTS, Baud, ["TempC = ", ' label param, ' display sign DEC (ABS tC / 10), ".", ' whole degrees DEC1 (ABS tC), CR] ' fractional degrees RETURN Show_Temp_F: GOSUB Read_DS1620 param = tF.BIT15 * 2 + "+" ' create sign char SEROUT TX\RTS, Baud, ["TempF = ", ' label param, ' display sign DEC (ABS tF / 10), ".", ' whole degrees DEC1 (ABS tF), CR] ' fractional degrees RETURN Read_DS1620: HIGH Reset ' alert the DS1620 SHIFTOUT DQ, Clock, LSBFIRST, [RdTmp] ' give command to read temp SHIFTIN DQ, Clock, LSBPRE, [tempIn\9] ' read it in LOW Reset ' release the DS1620

Page 210: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

207

tempIn.BYTE1 = -sign ' extend sign bit tC = tempIn * 5 ' convert to tenths IF (tC.BIT15 = 0) THEN ' temp C is positive tF = tC */ $01CC + 320 ' convert to F ELSE ' temp C is negative tF = 320 - ((ABS tC) */ $01CC) ' convert to F ENDIF RETURN Show_Leds: SEROUT TX\RTS, Baud, ["Status = ", BIN4 LEDs, CR] RETURN Set_Leds: SERIN RX\CTS, Baud, [BIN param] ' use binary input LEDs = param.LOWNIB ' set the outputs RETURN

幕後

沒有非同步串聯通訊,這個世界就不會是今天這個模樣。企業推動或交換訊息给彼此將會非常的困難。現在將不會有自動提款機來確認我們銀行帳戶和領取現金。這完全沒有互聯。 前面的實驗已經用同步串聯通訊。在那些計劃裡,需要兩條傳輸線:時脈和資料。其好處就是傳送者和接收者是自動同步。缺點則是它需要至少兩條電線在同一個方向來傳送訊息。 非同步串聯通訊只需要一條電線來傳送訊息。這計畫中必須去作的是兩端傳送者和接收者必須在開始通訊前同意通訊的速度可以被接受。一些”聰明”的系統可以檢測通訊的速度(胞率),但是 BASIC Stamp 不行。 在這實驗中我們將會用 SEROUT 來傳送訊息到傳送程式而 SERIN 來提取資料。輸入通常是一個指令而有時候這個指令將會被伴隨著一組新資料。請注意 SERIN 連接事實上由兩個針腳所定義:

SERIN RX\CTS, Baud, [WAIT ("?"), HEX cmd]

Page 211: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

208

CTS 連接告訴電腦 BASIC Stamp 準備好接收資料。記得 BASIC Stamp 沒有緩衝串連資料,且如果當 BASIC Stamp 忙著處理其他指令而造成該位元組被遺失,PC傳送一個位元組。 初始化 LED 輸出和 DS1620 後,程式進入主要迴圈並等待從傳送程式輸出。首先,SERIN 等待”?”字元的到來,忽略其他的一切直到這事情發生。問號,然後,意思是開始一個詢問。一但問號到達後 HEX 修改器造成 BASIC Stamp 尋找有效的十六進制字元(0 到 9,A 到 F)。任何不是十六進制字元到達(當使用終端機時通常是歸位【ENTER】)告訴 BASIC Stamp 停止處理輸入(到 cmd 的變數)且繼續。 BASIC Stamp 已經用 SERIN 指令來做文字轉換數字。現在指令可以用,程式用SELECT-CASE 來處理有效的指令,且如果進入的指令沒有被使用到,傳送一個訊息到終端機。 對於有效的指令 BAISC Stamp 透過用SEROUT傳送一串文字來回應請求。和SERIN

一樣,SEROUT 也是用來控制流量。RTS(請求發送 Request To Send)連接允許電腦讓 BASIC Stamp 知道他已經準備好接收資料。 每個回應字串包含一個標籤(label)、等號、特定數值的參數和歸位。當用到終端程式,輸出是容易讀的。就像這樣:

ID = StampWorks 2.1 當使用終端機程式時,在輸出 後的歸位給我們一條新線和當我們用我們自己的程式處理輸入提供一個”end of input”(和 StampPlot Lite 一樣)。當其他電腦和 BASIC Stamp 反應通訊時,等號可以被用來當一個定義符號。我們將會用它來區分標籤上的數值。 大部分的請求需要訊息。其中兩個卻可以修改修改訊息來儲存在 BASIC Stamp。

Page 212: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

209

第一個指令是”?F1”,允許我們寫入一串數值到 BASIC Stamp 的 EEPROM(落在ID 的位置上)。當$F1 被當作是指令數值接收時,程式跳到子程式 Set_ID。在進入 Set_ID 上,被叫作 eeAddr 的 EE 指標被初始化,然後 BASIC Stamp 等待一個字元的到來。注意沒有修改器在這裡被用到。因為終端機程式和 BASIC Stamp 代表字元是用 ASCII 碼,所以我們不必特別做什麼事。當一個字元到達,WRITE 被用來把字元放進 EEPROM 而位址指標被增加。如果 後的字元是歸位(13),程式顯示 新的字串(使用 Show_ID 的程式碼),否則它會循環回去並等待其他的字元。 第二個要修改的指令是”?B1”,允許我們去設定 4 個 LED 燈的狀態。看看 Set_Leds

子程式。現在,SERIN 的 BIN 修改器被使用,所以我們可以輕易的定義我們希望控制的每個位元。透過使用 BIN 修改器,我們的輸出將會變成一串 0 和 1(任何字元都會被轉換成二進制輸入)。在這個程式裡,”1”將會使 LED 燈打開;”0”會導致LED 燈關閉。這裡有個用於 B1 指令的範例:

?B1 0011<CR> 下面的圖顯示一個實際用 BASIC Stamp 的 Debug Terminal window 所看到的情況。

Page 213: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

210

要執行這個實驗,下列幾個步驟: 1. 移除前面實驗的零件 2. 輸入並下載程式 3. 移除實驗板上的電源並且建立電路 4. 移動傳輸線到 RS-232 接口上(如果需要的話) 5. 透過按下 Debug 按鈕來打開 Debug Terminal window,選擇 com port 連接到

RS-232 接頭,然後檢查 RTS 6. 打開實驗板的電源 挑戰(對於 PC 程式設計師) 寫一個程式來連接這個實驗。

Page 214: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

211

實驗#35:(額外)BS2PX ADC 這個實驗利用 BS2px 控制器中的比較器功能。透過通過一個已知的電壓(用 PWM)到比較器的一邊,它可以用來測量另外一邊輸入的未知電壓。 查一查:必須要知道的 PBASIC 元素

• COMPARE (只用在 BS2px )

建立電路

程式: SW21-EX35-BS2px-ADC.BPX ' {$STAMP BS2px} ' {$PBASIC 2.5} ' -----[ Program Description ]--------------------------------------------- ' ' Creates a simple 8-bit ADC with the BS2px using the internal comparator.

Page 215: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

212

' -----[ I/O Definitions ]------------------------------------------------- Vin PIN 1 ' unknown voltage input DacIn PIN 2 ' input from R/C DAC DacOut PIN 3 ' DAC via PWM + R/C ' -----[ Variables ]------------------------------------------------------- adcVal VAR Byte ' adc value (0 - 255) bias VAR Byte ' bias for ADC conversion result VAR Bit ' comparator result bit mVolts VAR Word ' input in millivolts ' -----[ Initialization ]-------------------------------------------------- Check_Stamp: #IF ($STAMP <> BS2PX) #THEN #ERROR "This program requires the BS2px" #ENDIF Setup: DEBUG CLS, "BS2px ADC Demo", CR, "==============", CR, "Raw..... ", CR, "Volts... " ' -----[ Program Code ]---------------------------------------------------- Main: DO GOSUB Get_ADC ' read comparator ADC mVolts = adcVal */ $139B ' convert to millivolts DEBUG CRSRXY, 9, 2, ' show results DEC adcVal, " ", CRSRXY, 9, 3, DEC1 (mVolts / 1000), ".", DEC3 mVolts PAUSE 250 LOOP ' -----[ Subroutines ]----------------------------------------------------- ' Simple ADC conversion ' -- outputs voltage on P3 until it crosses voltage on P2

Page 216: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

213

Get_ADC: adcVal = 0 ' clear ADC bias = 128 ' start in middle DO adcVal = adcVal + bias ' add bias to adc result PWM DacOut, adcVal, 15 ' output new test value COMPARE 2, result ' check comparator IF (result = 1) THEN ' if unknown lower than test adcVal = adcVal - bias ' -- reduce adcVal ENDIF bias = bias / 2 ' check next half LOOP UNTIL (bias = 0) RETURN

幕後

比較器是一個比較兩個電壓的電路;當電壓在+(非反相)比較器的輸入大於在-(反相)輸入的電壓時,輸出將會變成高電位,否則就是低電位。用這一的現象未知的電壓就可以透過輸入已知的電壓到比較器的另外一邊並檢查輸出來被量測到。 這個過程其他的 BASIC Stamp 和額外的比較器當然也可以做到。對於這個實驗利用 BS2px 內建的比較器功能。透過這些我們只要用三個 I/O 針腳和一些標準的零件。 測量未知電壓有個簡單的方法就是做一個迴圈偷偷的接上未知電壓:

Get_ADC_Simple: ' slow version adcVal = 0 DO PWM DacOut, adcVal, 15 ' output new value COMPARE 2, result ' check comparator IF (result = 1) THEN EXIT ' voltage found adcVal = adcVal + 1 ' increment result LOOP UNTIL (adcVal = 255) RETURN

這個策略的問題是當未知電壓偏向比例中比較高的部份長度的轉換。解決這問題的技巧叫做二進制搜尋(binary search)。簡單的說二進制搜尋可以消除單次測試中一半的可能。用這個方法可以在幾次測試中消除大量的可能性。

Page 217: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

214

在 Get_ADC 子程式中的 bias 變數被用來除以有效的可能,因為他在進入回圏前是從 128 開始。在測試回圏運作的部份裡,bias 被加到 adcVal-這個電壓是經由PWM 輸出到比較器的一邊。 如果未知電壓低於目前的測試電壓(在 adcVal),bias 目前的值就會在 bias 為了下次測試被除前被移除。bias 新的值被加到 adcVal 而比較器會再次檢查。這過程會一直重複直到 bias 被分開到 0-這讓 8 個重複的測試迴圏為”找到”未知電壓,不管電壓是多少。這樣可以比前面提供的方法快上許多。 下面的表說明用 3.3 伏特的輸入電壓用於測試迴圈(總數 168)。

Step bias adcVal (counts) adcVal (volts) Remove bias? 1 128 128 2.50 No 2 64 192 3.76 Yes 3 32 160 3.14 No 4 16 176 3.45 Yes 5 8 168 3.29 No 6 4 172 3.37 Yes 7 2 170 3.33 Yes 8 1 169 3.31 Yes

End 0 168 3.29 注意輸入事實上是透過 Step5 算出來的,但是運算性質需要它來執行所以的方法直到 bias 被除到 0。

Page 218: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

215

Page 219: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

216

更厲害的 PBASIC 在結束前,我要分享一些我認為從剩下領域可以區分出厲害的 PBASIC 程式設計師。這真的很簡單,沒有很難,可惜的是經常未被充分利用。掌握或採用這些建議取決於你,但是我認為如果你做了你將會為你的努力得到回報。 採用”PBASIC 風格元素” 我知道我一直在嘮叨這個,我會這樣做事有很好的理由:在我為 BASIC Stamp 微處理器寫程式的十二年來,我發現大部分的程式設計師因為馬虎的程式習慣而造成錯誤。透過 neatness counts 的主張,你的程式將會減少好多錯誤-我從經驗中得知的。 謹慎的使用變數宣告 許多程式設計師,特別是出身於個人電腦被發明後的,已經在其他資源遠超過BASIC Stamp 微處理器的平台上學過程式設計,這樣讓他們從未真正為管理變數空間煩惱過。這些程式設計師經常不會花很多時間來發現他們在個人電腦上用的技巧不能完全用在 BASIC Stamp(或其他小型微處理器)上。 分析你的程式和程式碼需要的宣告變數型態。如果變數有 10 個以上,請用 Nib,而不是用 Byte、Word 等這些會輕易浪費變數空間的宣告。 陣列是隱藏的-進階 常會有這樣的問題:我如何為陣列的一個元素命名?答案是:你不能-至少在你像這樣宣告時:

Page 220: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

217

colors VAR Byte(3)

Page 221: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

218

只要多點努力我們可以同時擁有同樣的陣列並且為裡面的元素命名。這裡是如何做到的:

colors VAR Byte red VAR colors green VAR Byte blue VAR Byte

被稱作 colors 的變數仍然像陣列一般處理: colors(0) = 50 colors(1) = 10 colors(2) = 35

程式碼的部分當然是同樣的: red = 50 green = 10 blue = 35

這是能用的,因為 BASIC Stamp 變數空間可以被當作一個隱形的陣列。元素的大小將取決於在選擇的變數基礎上。其它這技巧的關鍵是編譯器宣告同樣型態的變數在你的列表中他們出現的指令裡。在這例子中 colors 變數和 red 占據在同樣的記憶體空間,green 和 blue 在下面的順序中。 覆蓋變數來節省程式碼 你有兩個 byte 大小的旗標變數。你可以定義他們像這樣:

flags0 VAR Byte flags1 VAR Byte

這樣做是沒問題,但是你可以節省一個程式的位元和透過命名位元組到單一 Word

變數來提升速度,像這樣: flags VAR Word flags0 VAR flags.BYTE0 flags1 VAR flags.BYTE1

Page 222: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

219

第二個宣告不會比第一個多消耗變數空間,但是能用一行程式碼存取到所有旗標: flags = 0

這樣節省程式空間並增進速度因為 PBASIC 翻譯器必須從程式的 EEPROM 讀取一個指令,而前面的宣告會分成好幾行程式碼來設定所有變數;每行需要存取到程式的 EEPROM 進而影響程式速度。是的,看起來是件小事,但是請記住:很多的小事累加起來會得到更好的效能。 學習使用變數修改器 另一個常見的問題是:我如何轉換 BCD 到小數,然後回去?當這些轉換可以用標準程式編寫技巧,用 PBASIC 變數修改器可以變的很簡單。第一,轉換一個變數從BCD 變成小數:

decVal = bcdVal.NIB1 * 10 + bcdVal.NIB0

多麼簡單啊?因為 BCD 用半字節來做數字儲存,這似乎是 明顯的方法可是很多程式設計師會因沒掌握變數修改器的方法而會用更複雜的方法。小數轉換成 BCD也是同樣簡單:

bcdVal = ((decVal DIG 1) << 4) + (decVal DIG 0)

另一個有用的變數修改器是 LOWBIT()陣列。這個修改器可以讓我們讀取變數索引內變數任何的內部位元。舉例來說,如果你需要計數 Word 內所設定的位元,你可以像這樣做:

Count_Bits: bitCount = 0 FOR idx = 0 TO 15 bitCount = bitCount + wordVar.LOWBIT(idx) NEXT

Page 223: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

220

I/O 針腳也可以是變數 請記住 I/O 針腳也是變數(INS 和 OUTS)且當做些簡單的掃描時不需要用額外的變數。取而代之:

Main: DO startStatus = IN3 LOOP WHILE (startStatus = 1)

你可以用 PIN 型態宣告來宣告一個輸出和直接這樣做: StartBtn PIN 3 Main: DO : LOOP WHILE (StartBtn = 1)

我不主張用多個狀態於一條傳輸線上,但是對於於一些例子(無義的 DO-LOOP)來說這是一種簡單的方法。 我們可以用 combinatorial logic 來擴展。例如你要計數兩個不同的輸出在執行一個迴圈都是高電位的次數。厲害的 PBSIC 風格就會這樣做:

Count_Buttons: btnCount = 0 FOR idx = 1 TO 250 btnCount = btnCount + (Btn1 & Btn2) PAUSE 40 NEXT

這是可以用的因為當兩個按鈕被按下時,我們想要加一個到計數變數裡。透過一個邏輯上的 AND 來結合 Btn1 和 Btn2,我們減少括號到 0 或 1,當兩個按鈕都被按下時,唯一一次將會被返回(假設激活高電位輸入)。 你可以用*/和**來寫分數 */和**運算子允許 BASIC Stamp 乘以分數。這結果當然是一個整數,但是這些運算子將會簡化這個過程,而且常常增進結果的精度(超過標準乘或除的方法)。

Page 224: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

221

Page 225: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

222

什麼時候你要用*/還是相對的**?當你的分數結果大於 1,*/經常是運算子的選擇。當分數結果小於 1,**將會給予 好的答案。 要用*/,分數乘 256 並用這個對於*/的運算域。

Pi CON $0324

然後… area = radius * radius */ Pi

當你需要乘上一個小於 1 的數時,特別是很小的數,**運算子是 適合的。當使用**時你的分數乘上 65536 並用**操作的作為結果。

scale = rawInput ** 25 ' x 0.00038146

熟練模數(//)運算子

模數是很容易使用的,但是我仍看到很多程式設計師這樣做:

count = count + 1 IF (count = 10) THEN count = 0 ENDIF

為什麼?這樣不是更簡單? count = (count + 1) // 10

翻新很簡單,向下推(從 0 回到某個 大值)也是很簡單: count = (count + 9) // 10

看起來不太一樣,但是動作就像是這樣: IF (count < 0) THEN count = count – 1 ELSE count = 0

Page 226: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

223

ENDIF

Page 227: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

224

-1 是怎麼回事?他適用於除數和被加到中間結果的數值。 熟練模數的關鍵在於記住它是個往返於 0 到使用的除數間的數。如果你想要當按鍵按下時產生一個介於 20 到 50 間的虛擬亂數(pseudo-random)。這樣做:

Main: DO RANDOM randVal LOOP UNTIL (StartBtn = Pressed) selection = randVal // 31 + 20

你知道如何運作了?20 到 50 的距離是 30,所以我們用 31 來當做模數的除數。 使用條件編譯

BASIC Stamp 微控制器已經出現好幾年了,而且可以預期的,新的模組會更快且比舊的更多功能。BASIC Stamp IDE(集成開發環境 Integrated Development Environment)允許條件編譯,所以你可以建立一個程式碼用來執行任何一種的 BS2模組。 常看到的 BASIC Stamp 問題就是要移動一種模組到另外一種模組 SERIN

和 SEROUT 的問題。透過使用編譯來定義 baudmode,這問題就解決了。下面的程式碼片段從我提供的標準程式模板(Template.BS2)縮寫。

#SELECT $STAMP #CASE BS2, BS2E, BS2PE T2400 CON 396 T9600 CON 84 T19K2 CON 32 T38K4 CON 6 #CASE BS2SX, BS2P T2400 CON 1021 T9600 CON 240 T19K2 CON 110 T38K4 CON 45 #CASE BS2PX T2400 CON 1646 T9600 CON 396 T19K2 CON 188 T38K4 CON 84 #ENDSELECT

Page 228: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

225

SevenBit CON $2000 Inverted CON $4000 Open CON $8000 Baud CON T9600

條件編譯同樣簡化了 debug 程式碼的移動-程式碼你通常需要在完成程式前刪除或”註解”掉。

#DEFINE _DebugMode = 1 #IF (_DebugMode = 1) #THEN DEBUG HOME, DEC status #ENDIF

透過改變_DebugMode 的數值到 0,DEBUG 指令(被圈在#IF-#THEN-#ENDIF 區塊裡)被移除和簡單的被儲存。 在任務中中斷你的程式 因為 BASIC Stamp 執行編譯程式,所以要中斷它是不可能的。程式是怎麼可以回應短期的事件?答案是利用 ON-GOSUB 和設定你的程式碼如下:

Main: DO GOSUB Critical_Task ON task GOSUB Task0, Task1, Task2 task = task + 1 // NumTasks LOOP Critical_Task: ' task code RETURN Task0: ' task 0 code RETURN Task1: ' task 1 code RETURN Task2: ' task 1 code IF (Emergency) THEN GOSUB Special_Task

Page 229: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

226

ENDIF

Page 230: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

227

RETURN Special_Task: ' special task code RETURN

這很簡單,不需要強大的架構就可以適用於任何應用上。在主要迴圈中,被叫做Critical_Task 的子程式透過迴圈中的每個重複的事來執行,跟隨著當下所選擇的任務。在”正常”情況下執行的指令是: Critical_Task Task0 Critical_Task Task1 Critical_Task Task2 請注意所有的任務(Task)程式碼被嵌入到子程式裡。這樣的設計允許一個任務從其他在程式中的一點中被呼叫-甚至是從其他任務中。請注意 Task2 有能力在緊急的情況停止且如果那個情況存在可以呼叫 Special_Task。 使用這個框架的關鍵在於把你的程式打散成幾個小的任務。這樣你的程式就能擁有

好的反應能力和 大的靈活性。

Page 231: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

228

想出你的點子 恭喜你變成一位 BASIC Stamp 程式設計師!所以下一步呢?由你自己來決定。很多程式設計師新手當他們開始開發他們的專案時會卡住。但是別擔心,這是很自然的-這邊有很多方法來排解困難。下面的工作流程提示和資源將會幫助你成功實現你的好點子功能。 計畫你的工作,做你的計畫 你已經聽過無數次:計畫、計畫再計畫。沒有任何事比程式設計師沒有充分規劃還要麻煩。尤其是在 BASIC Stamp 的資源如此稀少的狀況下。大部分的問題都出在不良的規劃和安排而造成錯誤。 討論它 和自己討論程式。不要只是想它,講出來。如果你要解釋成是的操作給你的同伴把它大聲的講出來。通常只聽我們自己的聲音看看哪裡不同。 好是講給不是程式設計師的人聽。這會讓你解釋更多的細節。許多時候我們假設我們是講給自己或能力差不多的人。 寫出來 在你要坐在你電腦前,把你設計的程式細節寫在白板上。並用許多顏色來寫。你將會發現透過視覺上的設計可以提供新的見解,而且用這種媒介讓你靠流程圖來寫程式碼。 用“便利貼註解”來設計 拿出一些便利貼。寫下模組的名字或簡潔的程式碼片段在你個人的便利貼上,然後

Page 232: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

229

把他們貼在牆上。現在向後站並且觀察一下。然後移動他們一圈。增加便利貼,拿掉一些,只要做你認為對的。這樣的練習特別適用於團體。你怎麼知道你什麼時候完成?當便利貼停止移動!這是在開始編輯前記錄 後結果的 佳辦法。其他的提醒:當透過寫出來結合,這個方法相當好。如果不是完全正確,只要刪除那一行或移動其他便利貼。試試看這個方法,他真的很有用。

Page 233: Stamp Work V2 - Parallax, Inc. · 1 Stamp Work V2.1 中文版 中文版為美國 Parallax, Inc. 授權 飆機器人_普特企業有限公司(PlayRobot, Inc.) 編譯。任何未經

230

現在你對 BASIC Stamp 專案的欲望可能遠超過你所想的。所以接下來呢?別擔心,這裡有很多 BASIC Stamp 的相關資源可以用,這裡有個列表給你參考:

Books & Magazines

Microcontroller Application Cookbooks by Matt Gilliland Microcontroller Projects with BASIC Stamps by Al Williams Getting Started In Electronics by Forrest Mims Engineer’s Notebook by Forrest Mims Nuts & Volts Magazine “Stamp Applications” column Internet Sites

• www.parallax.com (Parallax main site) • www.emesystems.com/BS2index.htm (Tracy Allen’s BASIC Stamp resources – very

technical) • www.al-williams.com (Al Williams web site) • www.seetron.com (Scott Edwards Electronics web site) • www.hth.com/losa (List of Stamp Applications – great idea source)