AVR入門

AVRって何ぞ?


必要なもの

AVR本体

まずは100円のTiny2313から始めると良いと思う.A/Dコンバータが欲しいとか,もう少し色々やりたい人はもっと性能のいいAVRを選ぼう.
  • AVRの一覧

名称 価格 ピン数 フラッシュメモリ RAM EEPROM タイマ ポート 備考
Tiny2313 100 20 2k 128 128 8bit*1,16bit*1 PORTA(3bit,1RST,2XTal),PORTB(8bit),PORTD(7bit) 20MHzまで使える5Vくらい駆動のものと10MHzまでの低電圧用であるものが売られている
Mega8 200 28 8k 1024 512 8bit*2,16bit*1 PORTB(8bit),PORTC(7bit,6ADC,1RST),PORTD(8bit) 16MHzまでのものが売られている
Mega168 300 28 16k 1024 512 8bit*2,16bit*1 PORTB(8bit),PORTC(7bit,6ADC,1RST),PORTD(8bit) 20MHzまでのものが売られている
Mega164 400 40 16k 1024 512 8bit*2,16bit*1 PA(8bit,8ADC),PB(8bit),PC(8bit),PORTD(8bit) 20MHzまでのものが売られている

ちなみにPUとSUの2種類あるものもある。この違いはDIP(PU)か表面実装(SU)かの違い

開発環境

WinならAVRの制作元が出してるAVR-Studioがベスト.てかこれ一択.
C言語でプログラムを書くならWinAVRもインストールしよう.
Linuxならgcc-avrでコンパイルavrdudeで書き込みが出来る。Debian系ならsudo apt-get install avr-gcc avrdudeでおk。RHEL系ならsudo yum install avr-gcc avrdudeだった希ガス。(RHEL系はあんまシラネ)
VineLinuxとかだとソース落として自分でコンパイルする必要あり。
この項目ではCで書く事を前提にCソースしか書かないから絶対に入れてね.

AVRライタ

それなりにするけど純正ライタのAVR ISP MkIIを買うのが確実で手っ取り早い.でも,ドライバインストールとか管理者権限が必要だとかで制約もある.
WinXPとかで動かすのであれば共立エレショップにあるライタAVRWRT2でもおk。

こんなもん買えん.自作する! って人はHIDaspxというUSBのHIDとして認識するAVRライタがあります.HIDとは,Human Interface Device(ヒューマン・インタフェース・デバイス)のことで,OSに最初からドライバが組み込まれているのでドライバのインストールが必要がなくUSBポートに接続すればすぐに使う事が出来ます.また,書き込みプログラムも単体で動作するので,USBメモリ等に入れておける等,PCに依存しない開発環境が構築できます.問題は,自分で回路を組まないと行けない点と,AVRライタを作るためにAVRライタが必要という鶏が先か卵が先かという話になってしまいがちな点です.

HIDaspxについて

HIDaspxとは,山形県立産業産業技術短期大学の千秋氏が公開しているドライバインストール不要のAVRライタ回路です.
書き込み用プログラムとしては,hidspxが使用できます.詳細は本家を読んでください.

とりあえずライタとして動くものを作ろう

本家で紹介されている回路図は,ファームウェア更新用端子やUART端子などの拡張性を考慮した色々なものが実装されてます.しかし,実際にライタとして作動させる分には必要ないものもそれなりにあります.そこで,ライタとして動作する最小限のみの回路をここに紹介します.これは,bukkunが勝手に必要ないと判断したものであり,この回路を使った事によるいかなる損害も補償しませんし,動作確認はしていますが,実際に動くかは保証しません.ちゃんとしたものを作りたい人は本家の回路図をそのまま組んでください.

実体配線図

必要な素子一覧


実際に動かしてみよう

では,実際にプログラムを作成し,AVRで動かしてみましょう.

ポートの設定について

*方向レジスタ

ポートのI/O設定は方向レジスタ"DDRX"(X=A,B,C,...)で行う.DDRXの各ビットがポートXの各ピンX0,X1,X2,...のI/Oを設定する.
0が書き込まれたbitに対応するピンは入力設定に,1が書き込まれたbitに対応するピンは出力設定となる.
例えば,
  1. DDRB=0x0f;
とDDRBにバイナリ値 0000 1111'b を書き込んだ場合,ポートBの0~3番ピンは出力ピンに,
5~7番ピンは入力ピンに設定される.ここで,"0xY"は16進数の値Yを示している.

*出力レジスタ

AVRの出力用データレジスタは"PORTX"(X=A,B,C,...)の表記で指定できる.
方向レジスタで出力設定にしたピンXnに対応する出力レジスタPORTXのビット値が,ポートXのピンXnの出力値(Hi/Low)を設定する.
また,方向レジスタで入力設定としたピンXnに対応するPORTXのビットを1に設定すると出力ピンが内部でVCCにプルアップされ,
0に設定するとプルアップされないハイインピーダンス(Hi-Z)と呼ばれる状態になる.ハイインピーダンスの設定にした時は,外部回路でプルアップ若しくはプルダウンを行わないと動作が不安定になることがあるので注意する事.

例えば,
  1. DDRB = 0x0f;
  2. PORTB = 0x33;
と,ポートBの下位4ピンを出力設定に上位4ピンを入力設定とし,PORTBにバイナリ値 0011 0011'b を書き込んだ場合,
ポートBの0,1番ピンはHi出力に,2,3番ピンはLow出力に設定される.また,ポートBの4,5番ピンは内部でプルアップされた入力ピンに,6,7番ピンはHi-Zの入力ピンに設定される.

*入力レジスタ

AVRの入力用データレジスタは"PINX"(X=A,B,C,...)の表記で指定できる.
入力レジスタPINXの各ビットはポートXの各ピンX0,X1,X2,...の電圧値を示す.但し,方向レジスタで目的のピンを入力設定にしておく必要がある.
例えば,
  1. unsigned char buf;
  2. DDRB = 0x00;
  3. buf = PINB;
と書くと,ポートB全体を入力設定にし,その後ポートBの各ピンの電圧値を符号無しchar型変数(8bitレジスタ)に代入する.

LEDを光らせてみる

回路

図のように回路を構成する.
LED.png
この回路は,ポートBの0番ピン(B0)とVCCとの間に,LEDと電流制限抵抗を直列に繋いだ回路である.

今回の様にLED一つのだけのときはB0とグランドの間にLEDと抵抗をつなぎAVRの出力から直接点灯させても良いが,LEDが多量になるとAVRが供給する必要のある電流量が多くなる.
そのため,VCCとB0の間にLEDと抵抗をつなぎ,B0が"0"の時電流がB0に流れ込み点灯,"1"のとき消灯となるようにする.

ソースコード

ソースを以下に示す.動作はコメントの通り.
Bポートの0番ピン以外の全てのピンをプルアップ入力に,0番ピンをLow出力に設定する.
これにより,Bポートの0番ピンに接続されたLEDが点灯する.

#include <avr/io.h>

int  main( void )
{  
    /*                       初期化する。                       */
    PORTB    =    0xff;                            /* PORTB のデータを初期化。  */
    DDRB    =    0x01;                            /* ポートの入出力方向を設定。 DDR = _VB(PB0);でも同じ動作.*/
    /* 0000 0001  1=OUT  0=IN    */
    
    for( ; ; ){/* ずっと光らせるために無限ループ */
        /* ポートBの0番ポートのみを0に設定 */
        PORTB = 0xfe; /* PORTB&= ~_VB(PB0);でも同じ動作.~は全ビット反転命令, */
        /*_VB(bit)はbit目のビットを1にセットした値を返すマクロ,PB0はBポートの0番ピンのbit番号を返すマクロ*/
    }
    
    return 0;
}    

コンパイル

AVRstudioだとコンパイルコマンドがあるはず.
avr-gcc -

書き込み

自分の持っているライタの説明に従って書き込みを行ってください
HIDaspxを持っているなら,ライタソフトHIDspxのGUI版(hidspx-GUI.exe)もあるのでそれをどうぞ.
hidspxの書き込みコマンドは
hidspx main.c
の最小構成でおkのはず

LEDを点滅させてみる

回路・コンパイル方法は前と同じ.

ソースコード

ソースを以下に示す.動作はコメントの通り.
Bポートの0番ピン以外の全てのピンをプルアップ入力に,0番ピンをLow出力に設定する.
これにより,Bポートの0番ピンに接続されたLEDが点灯する.

#include <avr/io.h>
/* 遅延用関数のインポート
#define F_CPU 1000000UL  // クロック周波数を遅延用関数に教えるための定数
// 自分の使うクロックを書き込んでください(今回は初期設定の1MHz). <util/delay.h>より前に定義すること
#include <util/delay.h> 

int  main( void )
{  
    /*                       初期化する。                       */
    PORTB    =    0xff;                            /* PORTB のデータを初期化。  */
    DDRB    =    0x01;                            /* ポートの入出力方向を設定。 DDR = _VB(PB0);でも同じ動作.*/
    /* 0000 0001  1=OUT  0=IN    */
    
    for( ; ; ){/* ずっと光らせるために無限ループ */
        /* ポートBの0番ポートをxorを使って反転 */
        PORTB ^= 0x01;
        /* 1秒なにもしないで待機 */
        _delay_ms(1000.0); /* void _delay_ms(double __ms)  */
    }
    
    return 0;
}    

スイッチを押してLEDを光らせてみる

スイッチでLEDの光り方を切り替える

タイマを使ってLEDを点滅させてみる

タイマを使ってLEDの光り方を切り替えてみる

キッチンタイマーを作ってみる

LEDでキッチンタイマーの残り時間を表示する

スイッチでキッチンタイマーの時間を切り替える.

スイッチでキッチンタイマーの時間を設定する.


もう少し色々やってみる

クロックを変化させてみる

外部クロックで動作させてみる

ポート割り込みを使ってスイッチのOn-Offを検出する

PWMを使ってLEDの光量を変化させてみる

大量のLEDで絵を表示する

スイッチマトリクスで遊んでみる


さらに色々やってみる

USBとして認識させる

スイッチのオンオフをパソコンに通知する

パソコンからLEDを光らせる


おまけ

抵抗値の読み方

コンデンサ容量の読み方


  • 最終更新:2009-10-27 18:45:33

このWIKIを編集するにはパスワード入力が必要です

認証パスワード