アーカイブ
Mac OSXにおける近代的なAVRマイコン開発環境
久しぶりにAtmel AVRマイコンを直に使うプロジェクトをやるので、環境を整えてみた。@rain_yukizoraと@qt_fbが色々教えてくれた。
これが最強の組み合わせだ!!
- Mac OSX Snow Leopard
- Cross Pack for AVRに入っているavr-gcc
- macportsでインストールしたavrdude
- aitendoで売ってるusbasp
- 秋月やマルツで売っているATMega168か168pか328p
この記事では、MacでのAVRマイコン開発環境の構築と、ATMega168pでLEDを1秒間隔で点滅させるプログラムを作成して、マイコンに書き込んで動作させる所までを解説します。
Macbook Air + usbasp + ATMega168pで開発しているところ

■Cross Pack for AVRをインストールする
CrossPack – A Development Environment for Atmel’s AVR Microcontrollers
ここからダウンロードしてインストールする。
普通は /usr/local/CrossPack-AVR にインストールされるはず。
■usbaspを買う
aitendoで売ってるusbaspを買う。
これはMacからAVRマイコンに書き込みをする機械(writer)で、USBで動作するライターの中で最も安いし対応デバイスも多いのでオススメ。
朝買ってすぐ銀行に振りこんだら昼には発送されてた。
■XCodeをインストールする
次の項目のmacportsのインストールのために、XCodeが必要なのでインストールする。
Developer Downloads & ADC Program Assets
有料のXCode4が最新だけど、無料の3系でも良い。
■Macportsをインストールする
macports.orgからダウンロードしてインストールする。
■macportsとCross Pack for AVRのPATHを通す
$HOME/.profile を開く(無ければ作る)
これを下の方に書く
export PATH=$PATH:/opt/local/bin
export PATH=$PATH:/usr/local/CrossPack-AVR/bin
新しいterminalを開いて、PATHがセットされているか確かめる。
echo $PATH
■macportsでavrdudeをインストールする
Cross Pack for AVRに入っているavrdudeはUSBで使えないので、USBで使えるavrdudeを作る。
sudo port install git-core libusb avrdude
which avrdude
/opt/local/bin/avrdude が出てくればok。Cross Packの方が出てきたら、前のPATHの設定の順序が間違っている。
(homebrewでもavrdudeがインストールできるが、libusbを先にインストールしていても使えない。よくわからない。)
■avrdude.confにATMega168pのデバイス設定を追加する
ATMega168pを使う人だけ。168や328pを使うなら必要ない。
https://github.com/shokai/atmel-avrgcc-studyからavrdude.confをダウンロードしてきて、 /opt/local/share/avrdude.confと入れ替える。
git clone git://github.com/shokai/atmel-avrgcc-study.git
sudo cp /opt/local/etc/avrdude.conf /opt/local/etc/avrdude.conf.bak
sudo cp atmel-avrgcc-study/avrdude.conf /opt/local/etc/avrdude.conf
このavrdude.confはmacportsでインストールしたavrdude.confに、Kimio Kosakaさんが作ったavrdude.confにあったatmega168pの設定を追加した物です。
これで環境は整ったので、プログラムを書く。
俺が作ったプログラムは https://github.com/shokai/atmel-avrgcc-study/tree/master/28pin/led_blinkにある。これをそのまま書きこんで動かしても良いと思う
■avr-gccプロジェクトを作る
LEDを点滅させるプロジェクトを作る
avr-project led_blinkいきなりコンパイルしてみた。何も修正していなければエラーが無いのでコンパイルはできるはず。
cd led_blink/firmware
make
xcode用のファイルも生成されるが、xcodeを使っても全く意味が無いので無視する。
■ATMega168pで回路を組む
写真を見て回路を組む。
左の2つのLED(PB0, PD7)が交互に1秒ごとに点滅する。右のLED(PB1)はスイッチ(PB2)を押している間だけ点灯する。


ATMega168pのピン配置はこれ。VCC(AVCC)とGNDを接続する。

usbaspのケーブルの穴側から見たピン配置はこうなっている。
RESET,MISO,MOSI,SCKをAVRライターと接続する。VCCとGNDは回路のそれぞれと接続する。

■Makefileを修正する
修正する箇所はDEVICE,CLOCK,PROGRAMMER,FUSESの4つ。
DEVICE = atmega168pATMega168の時はDEVICE = atmega168にする。
CLOCK = 8000000
PROGRAMMER = -c usbasp
FUSES = -U hfuse:w:0b11011111:m -U lfuse:w:0b11100010:m
ここに完成品がある https://github.com/shokai/atmel-avrgcc-study/blob/master/28pin/led_blink/Makefile
fusebitの設定については橋本商会 » ATmega168のクロックを内蔵8Mhzに切り替えるに書いた。
■プログラムを書く
main.c を書く
#include <avr/io.h>
#include <util/delay.h>
#define TRUE 1
#define FALSE 0
#define NULL '\0'
#define sbi(BYTE,BIT) BYTE|=_BV(BIT)
#define cbi(BYTE,BIT) BYTE&=~_BV(BIT)
#define LED0_ON() sbi(PORTB, PB0)
#define LED0_OFF() cbi(PORTB, PB0)
#define LED1_ON() sbi(PORTD, PD7)
#define LED1_OFF() cbi(PORTD, PD7)
#define LED2_ON() sbi(PORTB, PB1)
#define LED2_OFF() cbi(PORTB, PB1)
void check_sw(void){
if(PINB&_BV(PB2)) LED2_ON();
else LED2_OFF();
}
int main(void)
{
DDRB = 0b00000011;
DDRD = 0b10000000;
LED2_ON();
for(;;){
LED0_ON();
LED1_OFF();
check_sw();
_delay_ms(1000);
LED0_OFF();
LED1_ON();
check_sw();
_delay_ms(1000);
}
return 0;
}
出力方向レジスタを指定する時は0bで2進数で書くと楽。
LED点滅の1秒(1000ミリ秒)のdelayはutil/delay.hを使った。
■コンパイルする
makeエラーがあるか確かめられる。
■ヒューズビットを書きこむ
Makefileで指定した、内蔵クロック8MHz駆動のfusebitを書きこむ。
make fuseこの操作は1回で良い。
■プログラムを書き込む
make flashusbaspが書きこんでくれる。
avrdudeがSCKを使えていないというメッセージが出るが、書き込める。
usbaspが電源も供給してくれるので、回路にACアダプタや電池などの他の電源は接続してはならない。
usbaspの電源供給は基板上のjumper pinを抜けばOFFにできる。
これでAVRマイコンをMacで開発できる環境が整った。
avr-gccのレジスタ操作で16進数とか使わない方法
最近出たこの本、すごくいい。
マイコンもATmega168で最新だし、gccでのコードが載っているのでよくわかる。
電波新聞社 (1982/01)
売り上げランキング: 23347
でもIOの操作で16進数とか使うのがあんまり好きじゃない。別にどう書いても動けばいいんだけど…
PORTB = 0×21;
とか。0×21、つまり10進数の33を代入しているので、PB5とPB0のピンを出力に設定しているという事だ。
でもこう書いたほうが好きだな。
PORTB = _BV(PB5)|_BV(PB0);
それかアセンブラ風にこういうのも好き。
sbi(PORTB,PB5);
sbi(PORTB,PB0);
こういう書き方の方が16進数慣れてない人には見やすい。ピン配置とプログラムをある程度柔軟に変えやすいのが近代的。(PB0からPB3に変えるのも、エディタの置換で一発だ)
どうなってるのかというと……
3軸加速度センサ KXM52を使って傾斜を測定
半年前にACA302という加速度センサを試したが、秋月電子で手に入らなくなった(取り扱い品がACA302からACB302になった)ので、樹に薦められたKXM52-1050モジュールを試してみた。
ACA302は3.3Vを作らなければならなかったが、KXM52の動作電圧は2.7~5.5Vそのままで動くし、ノイズも全然無いのにACB302より200円安く、感度も6倍でいい感じ。Pileus2号機に採用する予定。
そういえば最近ACB302は2000円から1000円に値下げになったけどね
■とりあえず動かしてみた
SourceCode, hex, Makefile(avr-gcc 3.4.6)
ATmega168のADC0,1,2でX,Y,Z軸の出力値をAD変換し、文字列に変換してUARTでPCに送っている。
x,y軸の値は通常520ぐらいで、傾けると730~300ぐらいの間で変わる。これは重力加速度を検出しているということ
ATmega168でピン変化割り込み
ATmega88以降は全てのI/Oピンに「外部入力割り込み」が付いている。これは、それぞれのピンに電流がONになったり、OFFになったりするとイベントが起こるという事だ。
今まではmain()の中のループで各ピンをずっと監視し続けなければならなかったが、この外部入力ピンを使うと完全にイベントドリブンでプログラムを書ける様になる。ちなみにArduinoからは使えない機能です。


■作った
PB1につながったスイッチを押した時に割り込み(SIG_PIN_CHANGE0)が発生し、UARTでPCに通知する。PB0のLEDも光らせる。スイッチを離すとLEDを消し、UARTで通知する。
SourceCode, hex, Makefile(avr-gcc 3.4.6)
■外部入力割り込みの仕組み
2箇所設定する必要がある。
1.「ピン変化割り込みレジスタ」でピン変化割り込みを許可する
2.入力割り込みを受け取るピンを「ピン変化割り込みマスクレジスタ」で指定する
ピン変化割り込み0,1,2(PCIE0,1,2)の3つがあり、それぞれPORTB,PORTC,PORTDに対応している。
つまり、割り込み1つで7~8個のピンを受け持つという所がINT0,INT1の外部入力割り込みと違う。
ATmega88のデータシートの41ページを見るとPCICRというレジスタのPCIE0ビットに1をセットしてやるとピン変化割り込み0が許可される事がわかる。
sbi(PCICR,PCIE0); // ピン変化割り込み0
ATmega168でAD変換
ATmega168でADコンバータも試した。
CdS(光量センサ)と10kΩの抵抗を使った。

ADC0でAD変換した値を文字列に変換して、UARTでPCに送る
ADC0の値が700以上の時、LEDを点灯させる。700以下だったら消灯する。
動いているところ
■コード
SourceCode, hex, Makefile(avr-gcc 3.4.6)
AD変換の準備のadc_init()、実際にAD変換を行ない値(int)を取るadc_convert(int pin)、USARTで文字列を送る関数 usart_sendStr()、intをStringに変換するintToStr(int, buf)を作った。
s.h.log: Arduino – UART、LED、AD変換を試したでも書いたが
シリアル通信で送信できるのは8bitまで。AD値は10bit。
なので、そのままSerial.print()してしまうと上位2bitが飛んで変な値になる。こういう時は
・上位2bit/下位8bitを2回に分けて送信し、PC側で連結する
・マイコン側で、AD値が0~50の時は’a'を送る/51~100の時は’b'を送るの様に、プロトコルを決める
・Stringにして送信して、PC側で数値に直す
・4で割ると、10bitの最大値1023が8bitの最大値255に納まる。ただし精度は4分の1になる
のどれかで対処する。
なので今回は文字列に変換して送ってみた。これが無いとデバッグとかやってられない。


最近のコメント