マイコン・メモ
AVRマイコンの使い方
ホームページに戻るトップページに戻る前ページに戻る次のページ最後のページ
AVRマイコンの基本的な使い方を、ATmega328P を例にこれまで製作したものを基に紹介します。
1.AVRマイコンの特徴

    ■GCC(GNU Compiler Collection)Cコンパイラ でのプログラミングに関わる点
ATmega328Pの写真
ATmega328P-PU

2.プログラミングの最初

ATmega328Pのプログラム作成で最初にすることを説明します。ただし、統合開発環境MicrochipStudio(旧AtmelStudio)を使ってC言語で作成するものとします。
まず、MicrochipStudioを起動して、下図の例のように新プロジェクトを作成します。
図中にある、プロジェクト名(Name, Location, Solution name)などは例です。好きな名称を入力してください。
プロジェクトを作成すると、メイン関数のファイル(main.c)が作成されます。ただし、空のファイルなので中身は自身で作ることになります(ここでは説明しません)。
C言語によるプログラムでは、リセット後すぐにメイン関数が実行されるわけではなく、前処理(準備)が必要です。しかし、MicrochipStudioを使うと、その部分を作成してくれます。ただし、ソースはないので編集はできません。

次のリストは、某プロジェクトで作成されたもので、リセットからメイン関数までに実行される部分です。
先頭0x0000番地から割り込みベクタがあります。ベクタと言ってもJMP命令の羅列です。ちなみに、その内容はどの割り込みを使っているかで異なります。
リセット後、0x0000番地にあるJMP命令、この例ではJMP 0x0068(JMP __ctors_end)から実行開始します。
0x0068番地(__ctors_end)からは、次のようなことを行っています。
  ①SREG(ステータスレジスタ)とSP(スタックポインタ)の初期化
  ②初期値付き変数の初期化(初期値コピー)
  ③初期値無し変数の初期化(ゼロクリア)
  ④メイン関数の実行
この例でもわかるように、SP(スタックポインタ)はSRAMの最終アドレスになっています。また、メイン関数から戻ってくると実行停止のエンドレスループに入ります(通常ならメイン関数から戻りません)。

3.I/Oポートを使う

I/Oポートとは、I/Oポートの機能を持つマイコンの端子(ピン)を指すものとします。
I/Oポートの特定のビットに'1'(High)や'0'(Low)を出力したり、また特定のビットの'0/1'状態を読み込んだりする方法を説明します。なおここでは、GCC(GNU Compiler Collection)Cコンパイラ を使うものとします(以降同じ)。
まず、ソースプログラムファイル(例えばmain.c)の始めの方で、次のようにヘッダファイル<avr/io.h>をインクルードしておきます※1。これはコンパイラに用意されているヘッダファイルで、これによってマイコンのハードウェアマニュアルにあるレジスタの名前が使えるようになります。
   #include  <avr/io.h>
※1.MicrochipStudioでプロジェクトを作成すると、ファイルmain.cには"#include  <avr/io.h>"が記述されています。

マイコンのI/Oポートは、通常次の3種類のレジスタに結び付いていて、これらを操作することで入力したり出力したりできるようになっています。各レジスタは8ビット構成ですが、操作は1ビットごとにできます。
   PORTn … ポートn出力レジスタ
   DDRn  … ポートn方向レジスタ
   PINn   … ポートn入力レジスタ
"n"の部分はポート番号で、アルファベット"A"~が入ります。ただし、どのポートが存在するかマイコンによって異なるので、使用するマイコンのハードウェアマニュアルで確認してください。ATmega328Pでは、"B","C","D"の3つのI/Oポートを使うことができます。
出力レジスタとは、I/Oポートに'1'や'0'を出力するためのレジスタです。
入力レジスタとは、I/Oポートの入力状態'1/0'を読み込むためのレジスタです。
方向レジスタとは、I/Oポートを出力として使うのか入力として使うのか決めるレジスタです。つまりI/Oポートは、使う前に出力か入力かどちらかに決めておかなければなりません。ちなみに、マイコンのリセット後は入力ポートになっています。

以降、ATmega328PのポートCを例に、指定のビットに'0'や'1'を出力する方法、また指定のビットの'0/1'状態を読み込む方法を説明します。
ATmega328PのポートCの制御レジスタは下記のようになっています。この図のように、ビット7は端子がないので使用できません。
注:ポートCのb6は、初期状態でRESET入力になっています。I/Oポートとして使用するには、ヒューズビットの上位バイトのb7(RSTDISBL)を'0'に書き換える必要があります。
ここでは、ビット6~4を出力に、ビット3~0を入力とするものとして、次のように初期化します。
   PORTC = 0x00;   … 初期状態として'0'をセットしておく※2
   DDRC = 0x70;    … b6~b4を出力に設定
・ビット4に'1'を出力する例
   PORTC |= 0x10;
・ビット6と5に'1'を出力する例
   PORTC |= 0x60;
・ビット4に'0'を出力する例
   PORTC &= 0xEF;
・ビット0が'0'か'1'か判断する例※3
   if((PINC & 0x01) == 0){
           … // '0'だった時の処理をここに書く
   }
   else{
           … // '1'だった時の処理をここに書く
   }
・ビット3~1が'101'か判断する例※3
   if((PINC & 0x0E) == 0x0A){
           … // '101'だった時の処理をここに書く
   }
   else{
           … // '101'ではなかった時の処理をここに書く
   }
※2.初期状態を'1'にしたいビットは、'1'をセットしておきます。
※3.入力設定/出力設定に関係なく、PINnで読み込むのは端子の状態です。つまり、出力設定では実際に出力している'0/1'状態を確認できます。

■_BV(※4)マクロを使って次のように書くこともできます。
   どちらがわかりやすいか考え、好きな方を使えばいいと思います。

・前記と同じポートCの初期化
   PORTC = 0x00;
   DDRC = (_BV(DDC6) | _BV(DDC5) | _BV(DDC4));
・ビット4に'1'を出力する例
   PORTC |= _BV(PORTC4);
・ビット4に'0'を出力する例
   PORTC &= ~_BV(PORTC4);
・ビット0が'0'か'1'か判断する例
   if((PINC & _BV(PINC0)) == 0){
           … // '0'だった時の処理をここに書く
   }
   else{
           … // '1'だった時の処理をここに書く
   }
・ビット3~1が'101'か判断する例
   if((PINC & (_BV(PINC3) | _BV(PINC2) | _BV(PINC1))) == (_BV(PINC3) | _BV(PINC1))){
           … // '101'だった時の処理をここに書く
   }
   else{
           … // '101'ではなかった時の処理をここに書く
   }
※4._BV()のカッコの中は、ハードウェアマニュアルの各I/Oレジスタの説明にあるビット名(ビット番号)です。

ホームページに戻るトップページに戻る前ページに戻る次のページ最後のページ
■■■ 注 意 ■■■
1.ここに掲載された内容(写真,図,表などを含む)の、全てまたは一部を無断で使用しないでください。
2.ここで紹介した手法(構造や仕組み,回路,プログラムなどを含む)を使用したことにより、問題や不利益が発生したとしても一切関知しません。
3.ここで紹介したプログラム例は、正常なコンパイルおよび正常な動作を保証するものではありません。