在上一篇中我們自製了一個 USBKeyboard,這次來自製一個 USB 數字鍵盤 (Numeric USB Keypad)。
▲ USBKeypad: 照片來源
準備材料
除了 Arduino 板子和 USB Shield 外,你還需要一個 Keypad:
關於 Keypad 的介紹與使用方法,請參考我寫的「Arduino 筆記 – Lab18 讀取 3x4 Keypad 的輸入」這篇筆記。
一家烤肉萬家香,開放分享才會快樂
在上一篇中我們自製了一個 USBKeyboard,這次來自製一個 USB 數字鍵盤 (Numeric USB Keypad)。
▲ USBKeypad: 照片來源
除了 Arduino 板子和 USB Shield 外,你還需要一個 Keypad:
關於 Keypad 的介紹與使用方法,請參考我寫的「Arduino 筆記 – Lab18 讀取 3x4 Keypad 的輸入」這篇筆記。
USBKeyboard 是 V-USB for arduino 這個計畫所提供的一個範例,它實作了一個很簡單的 USB 鍵盤裝置。
這個範例名字其實取得不好,因為它並沒有真正做出一個 USB 鍵盤,事實上這個範例只用到一個按鈕,程式會在按鈕被按下時,送出 "hello world" 跟一個 Enter 的鍵盤訊息給電腦,所以也許應該把它稱作 USB Helloworld Button 比較恰當。先不管這個問題,我們還是繼續沿用 USBKeyboard 這個名字。
接下來,我們就來自製這個 USBKeyboard 吧。
首先,你必須為 Arduino 做個 USB Shield,底下是一個參考電路,由於 USB D+ 和 D- 用 3.3V 的電壓,因此在 D+ 和 D- 上使用稽納二極體 (Zener diodes)。你必須確保 D- 準位在 2.5V 與 3.6V 之間。
我把 V-USB 提供的 4 支範例程式 (custom-class, hid-mouse, hid-custom-rq, hid-data) 移植到 Arduino 上了,現在你只要用 Arduino IDE 就可以上傳這 4 支範例程式:
在你開始之前,我希望你已經看過「V-USB 簡介」一文,知道 V-USB 是什麼,而且也希望你看過底下這幾篇,因為這 4 支範例程式的使用方法都寫在這幾篇裏,在這我就不再重述了:
要在 Arduino 上跑 V-USB 這 4 支範例程式,首先你必須準備一張 USB Shield。底下是一個參考電路,由於 USB D+ 和 D- 用 3.3V 的電壓,因此在 D+ 和 D- 上使用稽納二極體 (Zener diodes)。你必須確保 D- 準位在 2.5V 與 3.6V 之間。
實物照片:
▲ 圖片來源: galileo 的 USB Shield
Arduino 版的 V-USB 範例程式可以在底下的鏈結中取得:
下載後把檔案解壓縮到 Arduino-00xx\libraries 資料夾下,或是放到 Arduino 速寫簿(Sketchbook)資料夾的 Libraries 資料夾底下也行。
接著韌體要做兩個調整:
完成之後,你就可以用 Arduino IDE 打開範例程式並且上傳到 Arduino 板子上執行。
就這樣!
希望你可以順利使用這四支範例程式。如果你遇到什麼困難,歡迎留言或寫信來詢問。
承上篇,這篇將摘要說明 V-USB hid-data 範例程式。
hid-data 分成韌體和指令列工具 (commandline) 兩個部份。
底下是 hid-data 對 usbconfig.h 所做的調整:
這些設定 USB bus D+ 和 D- 所用的接腳。預設是:
#define USB_CFG_IOPORTNAME D
#define USB_CFG_DMINUS_BIT 4
#define USB_CFG_DPLUS_BIT 2
這個設定 interrupt-in endpoint 1,這是 HID device 的必要選項。
這個設定 interrupt-in endpoint 1 的 poll interval,單位為 miliseconds,不能小於 10 ms。
這些設定 VID 和 PID。預設是:
#define USB_CFG_VENDOR_ID 0xc0, 0x16
#define USB_CFG_DEVICE_ID 0xdf, 0x05資料表示方式是 low byte first,VID 0x16c0 和 PID 0x05df 是 obdev 提供的共享 VID/PID。
這些設定 Device Name 和資料長度,hid-data 把 Device Name 設成 "DataStore",資料長度是 9:
#define USB_CFG_DEVICE_NAME 'D', 'a', 't', 'a', 'S', 't', 'o', 'r', 'e'
#define USB_CFG_DEVICE_NAME_LEN 9
這些設定 Device Class 和 Interface Class。hid-mouse 的設定為:
#define USB_CFG_DEVICE_CLASS 0
#define USB_CFG_INTERFACE_CLASS 3USB 有定義一些常用的 device class,可在 USB Class Codes 這個頁面中找到,0 代表由 interface 指定。而 interface class 定義 3 代表這個是 HID Class。
這個設定 HID report descriptor 的資料長度。你必須在程式裏定義一個叫 usbHidReportDescriptor 的陣列,用來存放 report descriptor,而且陣列 size 要跟這個設定一致為 22 bytes 才行。
這會設定呼叫 usbFunctionWrite() 來處理 control-out transfer,而用 usbFunctionRead() 來處理 control-in transfer:
#define USB_CFG_IMPLEMENT_FN_WRITE 1
#define USB_CFG_IMPLEMENT_FN_READ 1
主程式分成 main() 和 usbFunctionSetup() 兩個函式。關於 main() 和 usbFunctionSetup() 兩個函式的說明,請參考「V-USB custom-class 範例解說」一文。
在這個範例程式中,main loop 的工作很單純,只是不斷呼叫 usbPoll() 讓 driver 處理工作。根據 V-USB 的說明,usbPoll() 至少每 50 ms 要跑一次。
底下是 hid-data的 usbFunctionSetup():
程式的邏輯是透過 bRequestRequest 判斷是不是 class request,假如是,再依 bRequest 判斷是哪一種 class request (Get Report, Set Report, Get Idle, Set Idle, Get Protocol 或 Set Protocol)。hid-data 只處 Get Report 和 Set Report 兩個 requests。在這個範例中,Get Report 是傳回 feature report 給 Host,而 Set Report 則是接收來自 host 端的 feature report。因為只有一個 feature report,所以 Get/Set Reports 沒有進一步判斷 ReportType (wValue high byte) 和 Report ID (wValue low byte)。
當收到 Get Report 或 Set Report 的 request 時,usbFunctionSet() 並沒有馬上把資料傳給 Host,而是回傳 USB_NO_MSG 讓 V-USB Driver 呼叫 usbFunctionRead() 和 usbFunctionWrite() 來處理。
usbFunctionRead() 的實作如下:
只是單純從 eeprom 讀取一塊資料 (data chunk) 並放到 buffer 給 Driver 處理。
而 usbFunctionWrite() 的實作如下:
也只是單純把從 host 收到的一塊資料 (data chunk) 寫到 eeprom。
底下是 hid-data 所定義的 HID Report Descriptor:
上列定義一個 Feature Report,資料長度為 128 bytes。
指令列工具包含 hiddata.c 和 hidtool.c。hid-data 把開啟 USB device 以及 Get Report 和 Set Report 的功能集中到 hiddata.c。
主程式 hidtool.c 只是間接呼叫 hiddata.c 中的 usbhidGetReport() 和 usbhidSetReport(),假如是 usbhidGetReport() 會將收到的資料以 hex format 印出,除此之外,沒有值得一提的地方。
hid-data 利用 usb_control_msg() 發送 control message,usb_control_msg() 的原型為:
int usb_control_msg(usb_dev_handle *dev, int requesttype, int request, int value, int index, char *bytes, int size, int timeout);
以 Get Feature Report 為例,呼叫方法為:
其中 USB_TYPE_CLASS 指定 Class request,USB_RECIP_DEVICE 指定接收者為 Device,而 USB_ENDPOINT_IN 則是指定 Control-IN transfer。USBRQ_HID_GET_REPORT 表示 Get Report 的 request,而 wValue 高位元組為 USB_HID_REPORT_TYPE_FEATURE 表示要取 Feature Report,而低元組是 report number,在此為 0。
而 Set Feature Report 的呼叫方法則為:
其中 USB_ENDPOINT_OUT 指定 Control-OUT transfer。
承上篇,這篇將摘要說明 V-USB hid-custom-rq 範例程式。
hid-customer-rq 分成兩個部份:韌體和 PC 端的指令列工具 (commandline)。
hid-custom-rq 的功能跟 custom-class 範例一樣,因此底下的內容大部份都跟 custom-class 雷同。hid-custom-rq 跟 custom-class 不一樣的地方,在於 hid-custom-rq 是宣告成 HID device。
底下是 hid-custom-rq 對 usbconfig.h 所做的調整:
這些設定 USB bus D+ 和 D- 所用的接腳。預設是:
#define USB_CFG_IOPORTNAME D
#define USB_CFG_DMINUS_BIT 4
#define USB_CFG_DPLUS_BIT 2
這個設定 interrupt-in endpoint 1,這是 HID device 的必要選項。
這個設定 interrupt-in endpoint 1 的 poll interval,單位為 miliseconds,不能小於 10 ms。
這些設定 VID 和 PID。預設是:
#define USB_CFG_VENDOR_ID 0xc0, 0x16
#define USB_CFG_DEVICE_ID 0xdf, 0x05資料表示方式是 low byte first,VID 0x16c0 和 PID 0x05df 是 obdev 提供的共享 VID/PID。
這些設定 Device Name 和資料長度,hid-custom-rq 把 Device Name 設成 "LEDCtlHID",資料長度是 9:
#define USB_CFG_DEVICE_NAME 'L', 'E', 'D', 'C', 't', 'l', 'H', 'I', 'D'
#define USB_CFG_DEVICE_NAME_LEN 9
這些設定 Device Class 和 Interface Class。hid-custom-rq 的設定為:
#define USB_CFG_DEVICE_CLASS 0
#define USB_CFG_INTERFACE_CLASS 3USB 有定義一些常用的 device class,可在 USB Class Codes 這個頁面中找到,0 代表由 interface 指定。而 interface class 定義 3 代表這個是 HID Class。
這個設定 HID report descriptor 的資料長度。你必須在程式裏定義一個叫 usbHidReportDescriptor 的陣列,用來存放 report descriptor,而且陣列 size 要跟這個設定一致為 22 bytes 才行。
承上篇,這篇將摘說明 V-USB hid-mouse 範例程式。
底下是 hid-mouse 對 usbconfig.h 所做的調整:
這些設定 USB bus D+ 和 D- 所用的接腳。預設是:
#define USB_CFG_IOPORTNAME D
#define USB_CFG_DMINUS_BIT 4
#define USB_CFG_DPLUS_BIT 2
這個設定 interrupt-in endpoint 1,這是 HID device 的必要選項。
這個設定 interrupt-in endpoint 1 的 poll interval,單位為 miliseconds,不能小於 10 ms。
這些設定 VID 和 PID。預設是:
#define USB_CFG_VENDOR_ID 0xc0, 0x16
#define USB_CFG_DEVICE_ID 0xe8, 0x03資料表示方式是 low byte first,VID 0x16c0 和 PID 0x03e8 是 obdev 提供的共享 VID/PID。
這些設定 Device Name 和資料長度,hid-mouse 把 Device Name 設成 "Mouse",資料長度是 5:
#define USB_CFG_DEVICE_NAME 'M', 'o', 'u', 's', 'e'
#define USB_CFG_DEVICE_NAME_LEN 5
這些設定 Device Class 和 Interface Class。hid-mouse 的設定為:
#define USB_CFG_DEVICE_CLASS 0
#define USB_CFG_INTERFACE_CLASS 3USB 有定義一些常用的 device class,你可以在 USB Class Codes 這個頁面中找到,0 代表由 interface 指定。而 interface class 定義成 3 代表這個是 HID Class。
這個設定 HID report descriptor 的資料長度。你必須在程式裏定義一個叫 usbHidReportDescriptor 的陣列,用來存放 report descriptor,而且陣列 size 要跟這個設定一致為 52 bytes 才行。
主程式分成 main() 和 usbFunctionSetup() 兩個函式。關於 main() 和 usbFunctionSetup() 兩個函式的說明,請參考「V-USB custom-class 範例解說」一文。
在這個範例程式中,main loop 利用 usbInterruptIsReady() 檢查 Interrupt-In endpoint 1 的 buffer 是否可用,假如可以,便呼叫 advanceCircleByFixedAngle() 計算新的滑鼠座標,接著再呼叫 usbSetInterrupt() 把 reportBuffer 傳給 Host:
底下是 hid-mouse 的 usbFunctionSetup():
程式的邏輯是透過 bRequestType 判斷是不是 class request,假如是就依 bRequest 判斷是哪一種 class request (Get Report, Set Report, Get Idle, Set Idle, Get Protocol 或 Set Protocol)。hid-mouse 只處理 Get Report, Get Idle 和 Set Idle 這三個 requests。除了 Get Report 是必要的外,其它兩個 requests 可以省略不寫。事實上因為 Host 端的 HID Driver 已經知道 report 的格式,所以其實 host 也不會發出這些 requests。
底下是 hid-mouse 所定義的 HID Report Descriptor:
上列定義一個標準滑鼠,有三個按鈕,X 和 Y 軸的相對座標,以及一個滾輪 (wheel)。而 report 的資料結構如下:
底下簡單說明這個 Report Descriptor 的結構:
首先,必須先定義 Buttons,總共有 3 個 Button:
每個 Button 狀態不是 0 就是 1:
3 個 Button 總共是 3 個位元:
這 3 個位元是 INPUT report:
其它 5 個位元是填充位元 (padding bits):
最後定義 X, Y 和滾輪:
把它們全當成 1 byte 的 signed integer,值域為 -127 到 +127:
每個 8 位元,總共 3 個:
把它們宣告成 INPUT report:
最後告訴電腦這是一個滑鼠:
就這樣。關於 HID Report Descriptor,你也可以參考「HID Report Descriptor 教學」這幾篇文章。
這篇將摘要說明 V-USB custom-class 範例的程式碼。要讀這篇,讀者必須對 USB 有足夠的認識。
customer-class 分成兩個部份:韌體和 PC 端的指令列工具 (commandline)
usbconfig.h 是 V-USB 的設定檔,每個 V-USB 的程式都會從 V-USB 的 usbconfig-prototype.h 複製過來並改名為 usbconfig.h 然後根據自己的硬體調整設定。
底下是 custom-class 對 usbconfig.h 所做的調整:
這些設定 USB bus D+ 和 D- 所用的接腳。預設是:
#define USB_CFG_IOPORTNAME D
#define USB_CFG_DMINUS_BIT 4
#define USB_CFG_DPLUS_BIT 2
這些設定 VID 和 PID。預設是:
#define USB_CFG_VENDOR_ID 0xc0, 0x16
#define USB_CFG_DEVICE_ID 0xdc, 0x05資料表示方式是 low byte first,VID 0x16c0 和 PID 0x05dc 是 obdev 提供的共享 VID/PID。
這些設定 Device Name 和資料長度,custom-class 把 Device Name 設成 "LEDControl",資料長度是 10:
#define USB_CFG_DEVICE_NAME 'L', 'E', 'D', 'C', 'o', 'n', 't', 'r', 'o', 'l'
#define USB_CFG_DEVICE_NAME_LEN 10
這個設定 Device Class。USB 定義了一些常用的 device class,你可以在 USB Class Codes 這個頁面中找到。0xff 代表的是 "Vendor Specific",也就是廠商自行定義的 function。
hid-data 是 V-USB 所附的一個範例,它示範如何透過 HID feature report 傳送固定大小的資料區塊 (blocks of data) 以讀取或寫入 eeprom 裏的內容。由於 Windows 內建 HID driver,因此 Windows 不會要求安裝驅動程式。這個範例同時也示範如何用 usbFunctionWrite() 和 usbFunctionRead() 傳送資料。
hid-data 包在 V-USB 套件裏:
hid-data 需要調整的地方跟 hid-custom-rq 一樣:
● usbconfig.h:
定義所用的 D+ 和 D- data lines 腳位。必須根據你的硬體調整 USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 和 USB_CFG_DPLUS_BIT。
● Makefile:
定義所用的 MCU 以及時脈頻率,必須根據你的硬體調整 DEVICE 和 F_CPU。
下指令編譯韌體,你會需要 WinAVR:
cd hid-data/firmware
make hex
接著把韌體燒錄到板子上,讓裝置重新上電,然後,「裝置管理員」視窗裏就會出現剛剛安裝的裝置,不用安裝驅動程式:
▲ Windows 會將新裝置當成「HID-compliant device」
下指令編譯 PC 端指令列工具,你會需要 MingGW 和 MSYS:
cd hid-custom-rq/commandline
make -f Makefile.windows
這會產生 hid-tool.exe。
底下示範 hid-tool 的用法:
讀取 eeprom:
寫資料到 eeprom:
hid-data 所用的資料區塊大小為 128 bytes。
hid-custom-rq 是 V-USB 所附的一個範例,它示範如何定義 HID class device。hid-custom-rq 功能跟 custom-class 範例一樣,不過它宣告成 HID device,由於 Windows 內建 HID driver,因此 Windows 不會要求安裝驅動程式。
hid-custom-rq 一樣可以用 custom-data 所附的 commandline 工具,透過 libusb-win32 來控制裝置。libusb-win32 dll 必須跟 commandline 工具放在同一個資料夾。
hid-custom-rq 包在 V-USB 套件裏:
hid-custom-rq 需要調整的地方跟 custom-data 一樣:
● usbconfig.h:
定義所用的 D+ 和 D- data lines 腳位。必須根據你的硬體調整 USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 和 USB_CFG_DPLUS_BIT。
● Makefile:
定義所用的 MCU 跟時脈頻率,必須根據你的硬體調整 DEVICE 和 F_CPU。
定義所用的 LED 接腳,必須根據你的硬體調整 LED_PORT_DDR, LED_PORT_OUTPUT 和 LED_BIT。
下指令編譯韌體,你會需要 WinAVR:
cd hid-custom-rq/firmware
make hex
接著把韌體燒錄到板子上,讓裝置重新上電,然後,「裝置管理員」視窗裏就會出現剛剛安裝的裝置,不用安裝驅動程式:
▲ Windows 會將新裝置當成「HID-compliant device」
下指令編譯 PC 端指令列工具,你會需要 MingGW, MSYS 和 libusb-win32 函式庫:
cd hid-custom-rq/commandline
make -f Makefile.windows
這會產生 set-led.exe。
註:libusb-win32 函式庫的安裝方法為,把 include\usb.h 複製到 C:\MingW\include\,而把 lib\gcc\libusb.a 複製到 C:\MingW\lib。
hid-custom-rq 的用法跟 custom-class 一樣:
打開 LED:
set-led on
關閉 LED:
set-led off
查詢 LED 狀態
set-led status
假如 LED 是開的,set-led status 會顯示 "LED is on",否則的話會顯示 "LED is off"。
註:雖然指令列工具是同一支,但因為 hid-custom-rq 用的 VID/PID 跟 custom-data 不一樣,custom-data 用的是 0x16c0/0x05dc,而 hid-custom-rq 的是 0x16c0/0x05df,所以 set-led 指令列工具必須重新編譯才行,不然執行時會找不到 device。
custom-class 是 V-USB 所附的一個 custom class device 範例,它示範如何直接使用 default control pipe 傳送與接收小量的資料。
custom-class 包在 V-USB 套件裏:
● usbconfig.h:
定義所用的 D+ 和 D- data lines 腳位。必須根據你的硬體調整 USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 和 USB_CFG_DPLUS_BIT。
● Makefile:
定義所用的 MCU 跟時脈頻率,必須根據你的硬體調整 DEVICE 和 F_CPU。
定義所用的 LED 接腳,必須根據你的硬體調整 LED_PORT_DDR, LED_PORT_OUTPUT 和 LED_BIT。
下指令編譯韌體,你會需要 WinAVR:
cd custom-class/firmware
make hex
接著把韌體燒錄到板子上,讓裝置重新上電,安裝 libusb driver,然後「裝置管理員」視窗裏就會出現剛剛安裝的裝置:
下指令編譯 PC 端指令列工具,你會需要 MingGW, MSYS 和 libusb-win32 函式庫:
cd custom-class/commandline
make -f Makefile.windows
這會產生 set-led.exe。
註:libusb-win32 函式庫的安裝方法為,把 include\usb.h 複製到 C:\MingW\include\,而把 lib\gcc\libusb.a 複製到 C:\MingW\lib。
custom-class 範例的使用方法為:
打開 LED:
set-led on
關閉 LED:
set-led off
查詢 LED 狀態
set-led status
假如 LED 是開的,set-led status 會顯示 "LED is on",否則的話會顯示 "LED is off"。
HID-Mouse 是 V-USB 提供的一個範例,它實作了一個很簡單的滑鼠裝置。這個範例示範 HID device 的實作。
因為現在大部份作業系統都有內建 USB 滑鼠驅動程式,所以跑 HID-Mouse 不需要安裝驅動程式。
HID-Mouse 包在 V-USB 套件裏:
基本上,HID-Mouse 可以用在所有 V-USB 支援的電路上。底下是一個參考電路,由於 USB D+ 和 D- 用 3.3V 的電壓,因此在 D+ 和 D- 上使用稽納二極體 (Zener diodes)。你必須確保 D- 準位在 2.5V 與 3.6V 之間。
● usbconfig.h:
定義所用的 D+ 和 D- data lines 腳位。必須根據你的硬體調整 USB_CFG_IOPORTNAME, USB_CFG_DMINUS_BIT 和 USB_CFG_DPLUS_BIT。其它不需要改變。
● Makefile:
定義所用的 MCU 以及時脈頻率。必須根據你的硬體調整 DEVICE 和 F_CPU。
Hid-mouse 在 "vusb-xxxx/examples/hid-mouse" 資料夾裏。
下指令編譯韌體,你會需要 WinAVR:
cd examples/hid-mouse/firmware
make hex
接著把韌體燒錄到板子上,讓裝置重新上電,然後你就會看到電腦畫面上的滑鼠指標會自己移動。
USBaspLoader 是給 AVR microcontrollers 使用的 USB bootloader,它可以用在支援 2 KB 以上 bootloader section 的所有 AVRs 上,例如 ATMega8。USBaspLoader 會燒錄到 Flash 的上層記憶體 (upper memory),並且會在 reset 的時候取得 MCU 的控制權。假如硬體狀況有符合 (這個狀況可以設定,例如利用 jumper),bootloader 會等待 USB bus 上的資料,然後把應用程式自我燒錄到 Flash 裏,當硬體狀況解除時 (例如拿掉 jumper),bootloader 就會把控制權交給應用程式。
USBaspLoader 跟 Thomas Fischl 的 avrusbboot 以及 bootloadHID 很像,不過 USBaspLoader 不需要特殊撰寫的燒錄工具,它模擬了 Thomas Fischl 的 USBasp programmer,因此你只需要用 avrdude 便可以燒錄韌體。
另外,由於 USBaspLoader 可以搭配 avrdude 使用,因此它同時也可以跟 Arduino IDE 整合。
USBaspLoader 可以在底下的網址取得:
USBasp 驅動程式:
基本上,USBaspLoader 可以用在所有 V-USB 支援的電路上 (MCU 的 bootloader section 至少要有 2 KB)。底下是一個參考電路,由於 USB D+ 和 D- 用 3.3V 的電壓,因此在 D+ 和 D- 上使用稽納二極體 (Zener diodes)。你必須確保 D- 準位在 2.5V 與 3.6V 之間。
BootloadHID 是給 AVR microcontrollers 使用的 USB bootloader,它可以用在支援 2 KB 以上 bootloader section 的所有 AVRs 上,例如 ATMega8。BootloadHID 會燒錄到 Flash 的上層記憶體 (upper memory),並且會在 reset 的時候取得 MCU 的控制權。假如硬體狀況有符合 (這個狀況可以設定,例如利用 jumper),bootloader 會等待 USB bus 上的資料,然後把應用程式自我燒錄到 Flash 裏,當硬體狀況解除時 (例如拿掉 jumper),bootloader 就會把控制權交給應用程式。
BootloadHID 用的是 HID device class,除了這點以外,BootloadHID 跟 Thomas Fischl 的 avrusbboot 很像,由於大部份作業系統都有內建 HID 驅動程式,所以跑 BootloadHID 不需要安裝驅動程式。
BootloadHID 可以在底下的網址取得:
基本上,BootloadHID 可以用在所有 V-USB 支援的電路上 (MCU 的 bootloader section 至少要有 2 KB)。底下是一個參考電路,由於 USB D+ 和 D- 用 3.3V 的電壓,因此在 D+ 和 D- 上使用稽納二極體 (Zener diodes)。你必須確保 D- 準位在 2.5V 與 3.6V 之間。
USooBie 是一 USB 介面的 AVR 開發板, 硬體和韌體都是 Open Source 的,它可以插在麵包板上使用,而且還提供 bootloader 功能與運作電壓的選擇。
USooBie 的特色如下:
USooBie 的電路圖如下:
AVR Stick 是一個簡單的 data logging 裝置,基於 ATtiny85,它會把自己當成是一個 HID Keyboard 定時回報伴隨 timestamp 的電壓資訊。AVR Stick 使用 V-USB 這套純軟體實作的 USB 1.1 裝置,它是基於 V-USB 的 EasyLogger 範例撰寫而成。AVR Stick 的硬體電路如下:
AVR Stick 的使用方法很簡單:把它插進電腦 USB Port,過一陣子,電腦就會辨識出裝置並把 AVR Stick 當成 keyboard 看待,然後 AVR Stick 會自動開始回報量測到的電壓。因此要取得量測結果,只要打開 notepad 或 excel,然後把 AVR Stick 插到電腦即可。AVR Stick 預設使用 2.56V 參考電壓,如果需要,必須自行調整程式碼。
底下是 ATtiny85 的規格摘要:
AVR Stick 的電路圖、PCB Layout 和韌體原始碼都可以在 AVR Stick 官網取得。
V-USB 是一個專門為 Atmel AVR microcontrollers 設計相容於 USB 1.1 的純軟體低速 USB device (software-only implementation of a low-speed USB device ),它讓開發者能夠用幾乎任何 AVR microcontroller 建立 USB 硬體。
V-USB 可以採用 GNU GPL (General Public License) 授權或者是用商業授權。
官網提供很充份的範例,示範廣泛的可能的應用。
底下是 V-USB 的特色:
ADC (Analog to Digital Convertor) 是類比轉數位的模組。ADC 受底下這幾個暫存器控制:
ADC 可以用中斷的方式運作,不過不在本文的討論範圍。
底下簡介各個暫存器:
首先是 ADMUX – ADC Multiplexer Selection Register:
利用 PWM (Pulse Width Modulation, 脈衝寬度調變) 控制 LED 燈光亮度。
這篇內容大部份出自 Ken Shirriff "Secrets of Arduino PWM" 一文,所有 credits 均屬 Ken Shirriff。
ATmega168/328 晶片有三個 PWM timers,控制 6 個 PWM 輸出。直接操控晶片的 timer 暫存器,你會獲得比 analogWrite() 函式更多的控制權。
ATmega328 有三個 Timer: Timer0, Timer1 以及 Timer2。每個 Timer 都有兩個控制 PWM 輸出寬度的 output compare 暫存器: 當 timer 到達 compare 暫存器的值時,對應的輸出就會切換。每個 timer 的兩個輸出的頻率通常是一樣的,不過 duty cycle 可以不一樣,取決於各自的 output compare 暫存器。
每個 Timer 都有一個可以產生 timer clock 的 prescaler,prescaler 提供除頻的效果,除率 (prescale factor) 諸如 1, 8, 64, 246 或 1024。Arduino 的 CPU clock 為 16 MHz,而 timer clock 將是 CPU clock 除以 prescale factor。注意,相較於其它 timers,Timer2 有不一樣的 prescale 設定值。