2011年7月27日 星期三

7) ADC

ADC 暫存器

ADC (Analog to Digital Convertor) 是類比轉數位的模組。ADC 受底下這幾個暫存器控制:

  1. ADMUX: 參考電壓的選擇 (透過 REFS0 和 REFS1 位元),轉換結果靠右或靠左對齊的選擇 (透過 ADLAR 位元)以及 Channel 的選擇 (透過 MUX3:MUX0 位元)
  2. ADCSRA 暫存器: 啟用 ADC(ADEN), 開始 ADC 轉換 (ADSC), 啟用中斷 (ADIE) 以及 Prescale 的設定 (透過ADPS2:ADPS0 位元)
  3. ADCL 及 ADCH 暫存器: 存放 ADC 轉換結果

ADC 可以用中斷的方式運作,不過不在本文的討論範圍。

底下簡介各個暫存器:

首先是 ADMUX – ADC Multiplexer Selection Register:

image

image

2011年7月26日 星期二

6.2) Fading

實驗目的

利用 PWM (Pulse Width Modulation, 脈衝寬度調變) 控制 LED 燈光亮度。

材料
  • Arduino 主板 x 1
  • LED x 1
  • 220 ohm 電阻 x 1
  • 單心線 x N
接線
  • LED 接到 pin9 和 GND,長腳 (陽極) 串接一顆 220 ohm 電阻到 pin9,短腳 (陰極) 直接接到 GND

2011年7月25日 星期一

6.1) PWM modes part2

這篇將用 Proteus 觀察 PWM 的波形,計算 Pulse 的寬度,看程式產生的 Pulse 寬度是否正確。

image
▲ Barebone Arduino

2011年7月22日 星期五

6.1) PWM modes part1

這篇內容大部份出自 Ken Shirriff  "Secrets of Arduino PWM" 一文,所有 credits 均屬 Ken Shirriff。

直接控制 ATmega PWM 的暫存器

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 設定值。

2011年7月19日 星期二

6) PWM

PWM 簡介

PWM (Pulse-width modulation,脈衝寬度調變) 是一種利用數位訊號來控制類比輸出的技術。

數位輸出 (Digital Output) 可以控制訊號的開跟關,開 (ON) 意味著通電,關 (OFF) 意味著斷電,假如我們進一步控制通電的時間比例,就能讓類比輸出產生變化。Arduino 的數位輸出電壓是 5V,如果腳位 ON 的時間佔整個週期 (Period) 的 50%,那麼平均電壓就是 2.5V。

Duty Cycle 為每一個週期通電時間 (ON) 所佔的比例,中文稱為工作週期或責任週期,在大陸地區稱為占空比。Duty Cycle 的變化可以從 0% 到 100%:

2011年7月17日 星期日

5.2) USART Receiver

這篇將示範如何使用 USART 收資料。

首先,先看使用 Arduino 的版本:

程式很簡單,所以就不解釋了。接著我們改用直接控制 USART 暫存器來接收資料。

非中斷版本

底下這支程式會從 Serial Port 接收資料,並且把收到的資料回傳回去 (Echo back):

5.1) USART Transmitter

這篇將示範如何使用 USART 傳輸資料。

首先,先看使用 Arduino 的版本:

程式很簡單,就不解釋了。接著讓我們改用直接控制 USART 暫存器來傳輸資料。

非中斷版本

底下這支程式會在 Serial Port 印出 "Hello World" 訊息:

2011年7月16日 星期六

5) USART

USART 簡介

ATmega168/328 晶片上有一個 USART (Universal Synchronous and Asynchronous serial Receiver and Transmitter),又稱 Serial Port,用來做序列通訊。如下圖所示,USART 使用 RXD 和 TXD 這兩支接腳來接收與傳送資料:

image

2011年7月14日 星期四

4.2) Timer as a Counter

實驗目的

練習把 Timer1 當成 Counter 使用。

材料
  • Arduino 主板 x 1
  • Pushbutton x 1
  • 10K 歐姆電阻 x 1
  • 麵包板 x 1
  • 單心線 x N
接線
  • 把 pushbutton 一支腳接到 +5V,另一支腳接到 pin 2 同時接一顆 10K 電阻連到 GND

2011年7月13日 星期三

4.1) Blink with Timer

實驗目的
使用 Timer 計算時間,讓一顆燈號閃爍,每隔一秒切換一次燈號。
材料
  • Arduino 主板 x 1
  • LED x 1
接線
  • 把 LED 接到 Arduino 板子上,LED 長腳 (陽極) 接到 pin13,短腳 (陰極) 接到 GND,如下圖:

image

2011年7月11日 星期一

4) Timers

Timers 簡介

簡單地說,Timer 是計時器,可以用來量時間。

來自石英振盪器脈衝 (pulse) 每一個 clock 會來一次,Timer 的內容會跟著計數遞增。所以,如果使用的是 16 MHz 的振盪器,Timer 的內容會每 62.5 ns (奈秒) 改變一次。

根據解析度的不同,Timer 通常有 8-bit 和 16-bit 兩種。如果是 8-bit Timer,那麼可以寫入的最大數值是 255 (16-bit 的話是 65535),假如超過了最大數值,Timer 就會自動 reset 為 0,這種情況稱為溢位 (overflow)。Timer overflow 的時候可以引發中斷,如果啟用了 Timer overflow 中斷,那麼你就必須在程式裏提供 ISR 處理中斷。

Timer 也可以當成一般的計數器 (Counter) 使用,或者是做 PWM 訊號輸出以及捕捉外部脈衝寬度 (Input Capture)。

Prescaler

Prescaler (預除器) 是一個用來提供 clock 給 Timer 的電路。如你所知,CPU clock 頻率通常是 1 MHz, 8 MHz, 16 MHz,而 Precaler 的用途則是除頻。

2011年7月7日 星期四

USBasp

USBasp 是給 AVR microcontrollers 使用的 USB 燒錄器 (in-circuit programmer)。USBasp 只需要 ATMega8, ATMega48 或 ATMega88 等 MCU 和少量的被動元件,除了電路圖和韌體原始碼外,官網上還提供多種 PCB Layouts 讓使用者下載。USBasp 可以搭配 avrdude 使用,因此可以跟 Arduino IDE 整合,見「整合 USBasp 與 Arduino IDE」一文。

下載

USBasp 可以在底下的網址取得:

http://www.fischl.de/usbasp/

USBasp 驅動程式:

http://www.fischl.de/usbasp/usbasp-windriver.2011-05-28.zip

硬體電路

底下是 USBasp 的參考電路,由於 USB D+ 和 D- 用 3.3V 的電壓,因此在 D+ 和 D- 上使用稽納二極體 (Zener diodes)。你必須確保 D- 準位在 2.5V 與 3.6V 之間。

 image
註: JP3 用來選擇低速燒錄

整合 USBasp 與 Arduino IDE

USBasp 可以跟 Arduino IDE 整合,方法是在 "arduino-00xx/hardware/programmers.txt" 裏加上底下這幾行:

usbasp.name=USBasp
usbasp.communication=usb
usbasp.protocol=usbasp

如下圖,然後 Arduino IDE 選單「Tools > Burn Bootloader 」底下會多一個 "w/ USBasp" 選項,你就可以直接在 Arduino IDE 用 USBasp 燒錄 Bootloader:

image

延伸閱讀

3.1) External Interrupts

實驗目的

練習處理外部中斷。在這個實驗中,你將利用 ISR() 巨集指令設定中斷服務函式 (Interrupt Service Routine, ISR),讓程式在 pin 2 產生外部中斷時自動執行 ISR。

材料
  • Arduino 主板 x 1
  • LED x 1
  • Pushbutton x 1
  • 10K 歐姆電阻 x 1
  • 麵包板 x 1
  • 單心線 x N
接線
  1. 把 LED 接到 pin13,長腳 (陽極) 接到 pin13,短腳 (陰極) 接到 GND
  2. 把 pushbutton 一支腳接到 +5V,另一支腳接到 pin 2 同時接一顆 10K 電阻連到 GND

2011年7月6日 星期三

3) Interrupts

什麼是 Interrupts?
當你在工作的時候,突然電話鈴聲響起,於是你把手邊工作停下來、接電話、講電話,然後回來繼續剛剛工作 -- 這就是所謂的中斷 (Interrupt),而電話便是中斷源。
在微控制器中,中斷的來源有很多,諸如 Reset, 外部中斷, Timer, USART, EEPROM, ADC 等。比如,當 Timer Overflow 時可以引發中斷,當 USART 收到資料或資料傳輸完畢時可以引發中斷…
跟人一樣,在遇到中斷的時候,微控制器的 CPU 也會把手邊的工作停下來,然後跳到預設的位址 (接電話),接著執行一段程式 (講電話),執行完後回來繼續進行剛剛的工作。
在發生中斷的時候,CPU 會老老實實的做這幾個動作:

2.2) Button

實驗目的
使用按鍵 (PushButton) 控制 LED,按鍵被按下時打開 LED,按鍵放開時關掉 LED。
材料
  • Arduino 主板 x 1
  • LED x 1
  • Pushbutton x 1
  • 10K 歐姆電阻 x 1
  • 麵包板 x 1
  • 單心線 x N
接線
  1. 把 LED 接到 pin 13,長腳 (陽極) 接到 pin 13,短腳 (陰極) 接到 GND
  2. 把 pushbutton 一支腳接到 +5V,另一支腳接到 pin 2 同時接一顆 10K 電阻連到 GND

image

2011年7月5日 星期二

2.1) Blink part 2

用 _BV() 巨集把程式變得清晰易讀

前一篇的程式,如果用 _BV() 巨集改寫的話,會變得比較清晰易讀:

BV 是 Bit Value 的縮寫。_BV() 巨集的定義為:

所以 _BV(5) 就是 bit 5,由此我們馬上可以聯想到,DDRB |= _BV(5) 這行代表的是「把 PB5 這支腳位設置設 OUTPUT」(註: 1 是 OUTPUT,0 是 INPUT)。

2.1) Blink part 1

實驗目的
讓一顆燈號閃爍,每隔一秒切換一次燈號。
材料
  • Arduino 主板 x 1
  • LED x 1
接線
  • 把 LED 接到 Arduino 板子上,LED 長腳 (陽極) 接到 pin13,短腳 (陰極) 接到 GND,如下圖:
image

2) I/O Ports

I/O Ports

Arduino 板子所用的晶片 (以 ATmega8 和 ATmega168/328 為例) 有三個 8-bit 的 PORTs :

  • B: 對應 Arduino 的 digital pin 8 to 13
  • C: 對應 Arduino 的 analog input pin 0 to 5
  • D: 對應 Arduino 的 digital pins 0 to 7
Arduino 與 AVR 晶片腳位對應表

底下這張圖顯示 Arduino 跟 ATmega8 之間的腳位對應關係:

image_thumb5  
▲ 圖片來源: arduino.cc 

例如,Arduino 的 pin 13 對應的腳位為 PB5。

1) AVR 晶片簡介

AVR 晶片簡介

AVR 是 ATmel 這家公司設計的 8 位元晶片,晶片架構來自於 Alf-Egil Bogen 和 Vegard Wollan 的構想。AVR 是 Alf (Egil Bogen) and Vegard (Wollan) 's Risc processor 的縮寫。

AVR 目前大概可分為下列幾個家族:

  • 8-bit tinyAVR 系列
  • 8-bit megaAVR 系列
  • 8/16-bit XMEGA 系列
  • 32-bit AVRs 系列

排愈後面的等級愈高,主要是記憶體較大、速度較快、腳位和周邊也比較多。

如果沒有特別聲明,這系列教學中提到的 AVR 指的都是 8 位元的晶片。

Arduino 與 AVR 晶片的關係

前面說過,Arduino 用的就是 AVR 的晶片,你可以在 Arduino 板子上找到 AVR 晶片,以 Arduino UNO 為例,晶片所在的位置如下圖所示:

image 
▲ Arduino UNO

From Arduino to AVR 單晶片教學

前言

單晶片微電腦 (Single Chip Microcomputer),或稱微控制器 (Microcontroller,縮寫為 µC 或 MCU),是一個將 CPU、記憶體、I/O Port 等周邊電路全部整合為一體的晶片。不像微處理器需要外部電路連接周邊,微控制器的應用只要少許的電路就可以運作,因為所有必要的周邊它都內建了。微控制器主要用在嵌入式系統,例如汽車電子、工業控制、機械控制等領域。

著名的 Arduino 板子上也有一顆微控制器,它是 AVR 的晶片,例如 Arduino UNO, Duemilanove 用的是 ATmega328,Arduino Diecimila 的是 ATmega168,而早期的 Arduino USB 則是使用 ATmega8。

Arduino 在歐美非常流行,因為它超簡單,很快就可以上手,我認為從 Arduino 到 AVR 是一條進入單晶片韌體開發的捷徑,因此著手撰寫這一系列的教學文件,希望這可以幫助想學單晶片韌體開發的新手,也希望能夠拋磚引玉,藉此引出高手發表佳文,同時也希望路過的先進不吝指教。

教學目標

我假設讀者你是單晶片新手,我不打算一次把所有與單晶片有關的東西全塞到你腦袋裏,因為這麼做其實是揠苗助長,適得其反,因此這系列的教學將維持 Arduino 一貫的簡約風格,點到為止。這系列教學的目標為:

  • 帶你認識 AVR 單晶片以及其周邊,包括 I/O Ports, Interrupt, Timer, USART, PWM, ADC 等。