ラベル avr-libc の投稿を表示しています。 すべての投稿を表示
ラベル avr-libc の投稿を表示しています。 すべての投稿を表示

2021/02/21

Raspberry Pi上でATtiny202のコンパイル環境を構築してLチカまで(1)

1.きっかけ


秋月電子のホームページにある新商品紹介ページで知ったのがきっかけです。
 最初は小さくて安いのがでたなぁという感想でしたが、新シリーズのようで仕様をみると結構豪勢なんです。ADC, UART, I2C, SPIを搭載しており、内蔵オシレータも20MHz動作です。さすがにメモリ類は少なくプログラムメモリ:2KB、RAM:128B、EEPROM:64Bです。安くて機能豪華、これは遊んでみたいという気持ちになりました。

 ただし、プログラミング方式がISPではなくUPDIというプロトコルに変更されており、愛用していたAVRISPmkIIは使えないことがわかりました。しかし、数年前にAtmel-ICEなるものを購入しており、これがUPDI対応とのことで一安心。(Atmel-ICEは購入してから一度も使っておらず、これが後に災いとなったことは内緒です)

2.購入


遊ぶにはブレッドボードに刺さるようにしたいのでDIP変換基板も併せて購入。

通販コード 品名 単価 数量 小計 説明
I-15731 ATTINY202-SSNR 40円 2 80円 AVRマイコン ATTINY202-SSNR
P-05154 AE-SOP8-DIP8 100円 1 100円 SOP8(1.27㎜) DIP変換基板 金フラッシュ(9枚入)
C-04392 PHA-1x4SG 4円 10 40円 細ピンヘッダ 1x4

3.組み立て


早速組み立てです。1.27mmピッチなので難しいところはなく、サクッと組み立て完了です。

2018/08/14

Raspberry PiのAVR開発環境を最新化する(改訂版)

昔の手順より良い方法があったので手順を変更して再掲します。


先日、avr-libcのHomePageを眺めていた時にtime.hを見つけました。time.hはその名の通り時刻に関する操作を行うライブラリです。時計を作るのに使えそうだなと思い、簡単なコードを書いてコンパイルしたところコンパイラが"time.hがない"と言うではありませんか! ソースコードを確認したけどスペルミスはない。「またまた、ご冗談を…」と/usr/lib/avr/include/を覗いてみたところ確かに無かった。(絶句)

どうやらavr-libcのバージョンが異なるのが原因のようです。

  • avr-libcのHomePageの最新バージョンはv2.0.0
  • Raspberry Piにインストールされているavr-libcバージョンはv1.8
そこでRaspberry PiのAVR開発環境を最新化することにしました。

(1)最新化に必要なソフト


せっかくなのでgccも最新化します。

・binutils-2.31.tar.xz
 https://www.gnu.org/software/binutils/

・gcc-8.2.0.tar.xz
 https://gcc.gnu.org/

・avr-libc-2.0.0.tar.bz2
 http://www.nongnu.org/avr-libc/

・avr-size用パッチ
 https://gist.github.com/larsimmisch/4190960

(2)コンパイル手順


avr-libcのHomePageにコンパイル手順の説明があります。基本的にこの手順で実施すればOKですが、スクリプト"download_prerequisites"を実行するとgccをビルドするのに必要なライブラリ(gmp,mpfr,mpc等)を自動的にダウンロードしてくれます。さらにgccのビルド時にダウンロードしたライブラリも一緒にビルドしてくれます。

(2-1)環境設定


$ mkdir $HOME/local
$ export PREFIX=$HOME/local
$ export PATH=$PREFIX/bin:$PATH

(2-2)GNU Binutilsのビルド


$ mkdir $HOME/src/avr-gcc
$ cd $HOME/src/avr-gcc
$ wget http://ftp.jaist.ac.jp/pub/GNU/binutils/binutils-2.31.tar.xz
$ wget https://gist.github.com/larsimmisch/4190960/archive/16c6b9627f8451eeebd644a4b9a741edfdb0c45e.zip
$ unzip 16c6b9627f8451eeebd644a4b9a741edfdb0c45e.zip
$ tar xvf binutils-2.31.tar.xz
$ cd binutils-2.31/binutils
$ patch -u < ../../4190960-16c6b9627f8451eeebd644a4b9a741edfdb0c45e/avr-binutils-size.patch
$ cd ..
$ mkdir obj-avr
$ cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --disable-nls
$ make -j4
$ make install

(2-3) gccのコンパイル


$ wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-8.2.0/gcc-8.2.0.tar.xz
$ tar xvf gcc-8.2.0.tar.xz
$ cd gcc-8.2.0
$ ./contrib/download_prerequisites
$ mkdir obj-avr
$ cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp --with-dwarf2
$ make -j4
$ make install

(2-4)avr-libcのコンパイル


$ wget http://download.savannah.gnu.org/releases/avr-libc/avr-libc-2.0.0.tar.bz2
$ tar xvf avr-libc-2.0.0.tar.bz2
$ cd avr-libc-2.0.0/
$ ./configure --prefix=$PREFIX --build=`./config.guess` --host=avr
$ make -j4
$ make install

(3)PATH設定


下記を$HOME/.profileに追加する
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/local/bin" ] ; then
    PATH="$HOME/local/bin:$PATH"
fi

2017/12/03

Raspberry PiのAVR開発環境を最新化する

より良い方法があったのでこちらをご覧ください。


先日、avr-libcのHomePageを眺めていた時にtime.hを見つけました。time.hはその名の通り時刻に関する操作を行うライブラリです。時計を作るのに使えそうだなと思い、簡単なコードを書いてコンパイルしたところコンパイラが"time.hがない"と言うではありませんか! ソースコードを確認したけどスペルミスはない。「またまた、ご冗談を…」と/usr/lib/avr/include/を覗いてみたところ確かに無かった。(絶句)

どうやらavr-libcのバージョンが異なるのが原因のようです。

  • avr-libcのHomePageの最新バージョンはv2.0.0
  • Raspberry Piにインストールされているavr-libcバージョンはv1.8
そこでRaspberry PiのAVR開発環境を最新化することにしました。

(1)最新化に必要なソフト


せっかくなのでgccも最新化します。

・binutils-2.29.1.tar.xz
 https://www.gnu.org/software/binutils/

・gcc-7.2.0.tar.xz
 https://gcc.gnu.org/

・gmp-6.1.2.tar.xz
 https://gmplib.org/

・mpfr-3.1.6.tar.xz
 http://www.mpfr.org/

・mpc-1.0.3.tar.gz
 http://www.multiprecision.org/index.php?prog=mpc

・avr-libc-2.0.0.tar.bz2
 http://www.nongnu.org/avr-libc/

・avr-size用パッチ
 https://gist.github.com/larsimmisch/4190960

(2)コンパイル手順


avr-libcのHomePageにコンパイル手順の説明があります。基本的にこの手順で実施すればOKです。

(2-1)環境設定


$ mkdir ~/local
$ PREFIX=$HOME/local
$ export PREFIX
$ PATH=$PATH:$PREFIX/bin
$ export PATH

(2-2)GNU Binutilsのコンパイル


$ cd ~/src/avr
$ wget https://ftp.gnu.org/gnu/binutils/binutils-2.29.1.tar.xz
$ tar xvf binutils-2.29.1.tar.xz
$ wget https://gist.github.com/larsimmisch/4190960/archive/16c6b9627f8451eeebd644a4b9a741edfdb0c45e.zip
$ unzip 16c6b9627f8451eeebd644a4b9a741edfdb0c45e.zip
$ cd binutils-2.29.1/binutils
$ patch -u < ../../4190960-16c6b9627f8451eeebd644a4b9a741edfdb0c45e/avr-binutils-size.patch
$ cd ..
$ mkdir obj-avr
$ cd obj-avr/
$ ../configure --prefix=$PREFIX --target=avr --disable-nls
$ make -j4
$ make install

(2-3) GNU gmpのコンパイル


gccをコンパイルするためにはgmp, mpfr, mpcが必要なため、先にコンパイルします。
$ cd ~/src/avr
$ wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.xz
$ tar xvf gmp-6.1.2.tar.xz
$ cd gmp-6.1.2/
$ ./configure --prefix=$PREFIX
$ make -j4
$ make -j4 check
$ make install

(2-4) GNU mpfrのコンパイル


$ cd ~/src/avr
$ wget http://www.mpfr.org/mpfr-current/mpfr-3.1.6.tar.xz
$ tar xvf mpfr-3.1.6.tar.xz
$ cd mpfr-3.1.6
$ ./configure --prefix=$PREFIX --with-gmp-build=../gmp-6.1.2
$ make -j4
$ make -j4 check
$ make install

(2-5) GNU mpcのコンパイル


$ cd ~/src/avr
$ wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
$ tar xvf mpc-1.0.3.tar.gz
$ cd mpc-1.0.3
$ ./configure --prefix=$PREFIX --with-gmp=$PREFIX --with-mpfr=$PREFIX
$ make -j4
$ make -j4 check
$ make install

(2-6) gccのコンパイル


$ cd ~/src/avr
$ wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-7.2.0/gcc-7.2.0.tar.xz
$ tar xvf gcc-7.2.0.tar.xz
$ cd gcc-7.2.0/
$ mkdir obj-avr
$ cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp --with-dwarf2 --with-gmp=$PREFIX --with-mpfr=$PREFIX --with-mpc=$PREFIX
$ make -j4
$ make install

(2-7)avr-libcのコンパイル


$ cd ~/src/avr
$ wget http://download.savannah.gnu.org/releases/avr-libc/avr-libc-2.0.0.tar.bz2
$ tar xvf avr-libc-2.0.0.tar.bz2
$ cd avr-libc-2.0.0/
$ ./configure --prefix=$PREFIX --build=`./config.guess` --host=avr
$ make -j4
$ make install

2017/11/12

Raspberry PiでAVR開発

 以前にdebianのAVR開発環境を紹介しましたが、Raspberry Piでも同じ手順でAVR開発環境が作れます。

■Raspberry Pi(Raspbian)でAVR開発環境を構築する手順

# apt update
# apt upgrade
# apt install gcc-avr binutils-avr avr-libc avrdude
 Raspberry PiでAVR開発するメリットは、「ソース修正→ISP書き込み」が気軽にどこでもできるということに尽きます。Raspberry Piに移行する前はノートPCのAVR開発環境にAVRISPmkIIを接続してデバッグしていたのですが、この場合、開発対象とノートPCをAVRISPmkIIのケーブルが届く範囲に留める必要があり、結局のところ、開発対象の近くにノートPCを持っていくしかありませんでした。
 Raspberry PiにAVR開発環境を置く場合、ノートPCは作業机に、Raspberry Piは開発対象の近くに設置し、ノートPCとRaspberry Pi間はイーサネット(無線LANでもOK)で接続し、SSHでRaspberry Piにログインして作業することができます。

2014/10/25

JJYシミュレータの試作(AVRマイコン)

 すこし前に購入した電波時計モジュール(40KHz) [MAS6180-40KHZ]を使って電波時計を作ってみることにしました。電波時計モジュールから出力されるパルス信号をAVRマイコンでデコードして7segLEDかLCDに表示するつもりです。
 ところが実際にデバッグを始めたところ困ったことが発生。電波時計モジュールから出力されるパルス信号がノイズだらけでデコードできないようなのです。電波時計モジュールとAVRマイコンを窓際に持っていくと正しいパルスが出てくるのですが、マイコンデバッグ用PCに接続するためにPCが設置されている場所まで持っていくと出力パルスが怪しくなります。原因として考えられるのは以下の2点です。

 1)電波が弱いため窓際でないと正しく受信できない。
 2)PCが出すノイズに邪魔される。

 PCの電源を落とすとだいぶ改善されるので2)の要因が大きいのだと思います。

 PCなしではマイコンのデバッグができないので、電波時計モジュールのパルス出力を疑似出力する「JJYシミュレータ」なるツールをAVRマイコンで試作することにしました。

構成


  • いつものAVRマイコン(ATmega168/328マイコンボードキット)を使用します。
  • ATmega168/328マイコンボードキットのPB5ピンにはLEDが実装されているので、このピンをパルス出力ピンにします。
  • パルス出力のフォーマットはNICTの長波JJY送信方法を参考にしました。
  • 時刻情報はタイマ1で生成した10Hzから生成します。
  • 時刻合わせ機能はありません(プログラム上で初期値を定義し、常に初期値からスタート)
  • タイマ0で40kHzを生成し、PD6(OC0A)ピンに出力します。このときパルス出力で送信OFF/ONを制御します。
  • パルス出力の状況はシリアル(RS232C)に出力します。
今回はパルス出力だけで良かったのですが、遊びで40kHz出力もつけてみました。

使ってみて


 まだ本来の目的(パルス出力を使って電波時計のデバッグ)は試していません。
 替わりに40kHz出力を試してみたところ見事に動きました。PD6ピンに15cmぐらいの線材を接続し市販電波時計に近づけてみたところ同期してくれました。10cmぐらい離しても同期します。
 本物のJJYの電波形式(A1B)とはちょっと違う40kHzの矩形波のON/OFFですがうまく動きました。
 頭では分かっているけど、実際に動いている所をみると電波は面白いというか不思議ですね。

シリアル出力例


<<< JJY Simulator >>>
 Copyright (c) 2014 Being. Ver0.1

00M 2016/02/29 23:14
M00100101M001000011M000000110M000000110M_________M000000000M 2016/02/29 23:15
M00100110M001000011M000000110M000000110M000010110M001000000M 2016/02/29 23:16
M00100111M001000011M000000110M000000100M000010110M001000000M 2016/02/29 23:17
M00101000M001000011M000000110M000000100M000010110M001000000M 2016/02/29 23:18
M00101001M001000011M000000110M000000110M000010110M001000000M 2016/02/29 23:19
M01000000M001000011M000000110M000000110M000010110M001000000M 2016/02/29 23:20

2014/08/18

7segLED時計の試作(AVRマイコン)

AVRマイコンと4桁7segLEDを使った時計を試作しました。今回は時刻合わせ機能も入れてあります。

用意するもの


1秒の作り方


前回と同じ方法で作ります。

回路図


今回は4桁7segLEDをダイナミック点灯方式で使います。以下に回路図を示します。

図1 7segLEDボード回路図

手持ち部品がアノードコモンタイプの7SegLEDとNPNトランジスタのみだったので一般的なエミッタ接地ではなく、コレクタ接地(エミッタフォロワ)回路になっています。

図2 ボード間接続図

プッシュスイッチにプルアップ抵抗がありませんが、AVR内蔵のプルアップで代用しています。

機能


時計表示機能
 24時間表記で時分を表示します。4桁LEDなので秒数は表示できません。
 秒数は7seg LEDの小数点を点滅させることで表現します。
 秒数により点滅する小数点の位置を変え、大まかな秒数が把握できるよう
 にします。
  00-14秒:1桁目の小数点を点滅、2-4桁目は消灯
  15-29秒:2桁目の小数点を点滅、1桁目は点灯、3-4桁目は消灯
  30-44秒:3桁目の小数点を点滅、1-2桁目は点灯、4桁目は消灯
  45-59秒:4桁目の小数点を点滅、1-3桁目は点灯

日付表示機能

 Bボタンを押すと年(4桁)を表示します。
 さらにBボタンを押すと月日を表示します。
 さらにBボタンを押すと曜日を表示します。

日時修正機能

 Aボタンを長押し(3秒)すると日時修正モードに入ります。
 年→月→日→時→分→秒の順に入力します。
 Bボタンを押すことにより各値がインクリメントされます。
 秒修正時はBボタン押下で00秒に設定されます。
 3秒間何も操作しないと時計表示モードに戻ります。(そこまでに
 入力した値は反映されます)
 曜日は入力しません。(年月日から自動計算されます)
 うるう年を認識します。(2/29はうるう年のみ入力を受け付けます)

オートディマー(減光機能)

 夜間(23-06時)は減光モードになります。ボタンを押すと通常モードに
 なります。5秒間何も操作しないと減光モードに戻ります。

状態遷移図


上述の機能を状態遷移図化したものを以下に示します。

図3 状態遷移図

完成


こんな感じで動きます。

2014/07/05

時計もどきの試作(AVRマイコン)

AVRマイコンとLCDを使った時計もどきを試作しました。なぜ「時計もどき」かと言うと、時刻合わせを行う機能がないからです。

用意するもの


1秒の作り方


マイコン内蔵クロックは精度が悪いため時計には使わないほうが良いでしょう。マイコンボードには20MHzのX'talが搭載されているのでこれを使います。20MHzクロックはマイコン内部で1/8(=2.5MHz)にされ、CPU Coreの動作クロック、およびタイマ/カウンタの動作クロックとして使われます。タイマ/カウンタは20mS周期(=50Hz)でタイマ割り込みを発生させます。プログラムはタイマ割込50回で秒針を1進めるようになっています。


図1 クロック構成

回路図


今回使用したLCDモジュールはマイコンとI2Cバスで接続します。図2に回路図を示します。


図2 回路図

I2Cバスのアクセス方法


マイコン内蔵のTWI機能を使ってI2Cバスにアクセスします。TWIの使い方は面倒そうだったのでAVR315付属のサンプルコードを使いました。ただし、avr-libcで使う場合は割り込み関係のソースを少し修正する必要があります。以下に修正ポイントを示します。

リスト1 TWI_Master.cの冒頭 修正ポイント:1~4行目、7行目を追加

リスト2 TWI_Master.cの割込みルーチン 修正ポイント:9~11行目、14行目を追加

完成


こんな感じで動きます。 電源入れたまま10日ほど放っておいたら10秒遅れました。月差に換算すると30秒ぐらいなのでまあまあの精度です。

2014/04/12

PWM制御でLED点滅

 今度はLED点滅にPWM(Pulse Width Modulation)を使ってみます。

ゴール


  • LEDの点滅周期は約2秒(点灯1秒、消灯1秒)
  • PWM制御で「ふわっと点灯」、「ふわっと消灯」を実現する

ふわっと点灯、ふわっと消灯


 「ふわっと」を実現するため、LEDの明るさを制御します。LED輝度制御方法として今回はPWMを使います。PWMは変調方式の一つで、パルス波のDuty比(点灯と消灯の比率)を変化させることにより変調を行う方式です。簡単に言うと、
  • LEDを超高速点滅させる
  • 点滅時のDuty比を変えることにより明るさを調節する
となります。
 「超高速点滅」とは、例えば1秒間に1,000回点滅のように点滅してることが人間に認識できないほど速くします。
 「Duty比を変えることにより明るさを調節」というのは、例えばDuty比=90%(点灯90%,消灯10%)とDuty比=10%(点灯10%,消灯10%)ではDuty比=90%のほうが明るく見えるということです。

AVRでのPWM制御について


 AVRはタイマ/カウンタをPWMモードにすることにより、PWM制御を行うことができます。8bitタイマと16bitタイマがありますが、Duty比の指定は8bit(=256段階)あれば十分なので8bitタイマであるTimer/Counter0を使います。タイマの動作モードはFast PWM Mode (WGM2:0=3)を使います。このモードはパルス波周期が256 timer clock固定で、Duty比はOCR0Aレジスタで指定できます。Timer clockを1MHzにすると、LEDの点滅回数は1秒間に3,900回ぐらいになります。タイマで作ったPWM信号はOC0A(PD6ピン)に出力されます。

LEDとPD6ピンの接続


 参考文献2を見るとマイコンのPB5端子の先にLEDが接続されています。PD6端子でLEDを制御するため、PD6端子とPB5端子を接続する必要があります。どちらの端子もマイコンボードのコネクタに接続されているので、コネクタ上で接続するのが簡単です。
図1 コネクタ上の接続(PB5端子とPD6端子)

 なお、PD6端子とPB5端子がショートしないようにプログラム上でPB5端子をInputに設定しておきます。

プログラム


 例によってdebian環境(avr-gcc+avr-libc)で作成しています。

リスト1 main.c

/*
 * LED点滅プログラム(PWM制御)
 *
 * For AE-ATmega borad
 *
 * Ver0.1 2013/04/12
 */

/*
 * AE-ATmega boardはPORTB bit5にLEDが接続されている。
 * このLEDをPWM制御で点灯させるため、タイマ出力であるPORTD Bit6を
 * LEDに接続する。(ショートしないようにPORTB bit5は入力モードに
 * しておく)
 */

#include <avr/io.h>
#include <util/delay.h>

int main() {
  unsigned char i = 0;

  DDRB = 0x00;          // PORTB bit5を入力モードにする
  DDRD = _BV(DD6);      // PORTD bit6を出力モードにする

  /* Set 8-bit Timer Register */
  TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00);
  TCCR0B = _BV(CS00);

  /* タイマ設定
   * clkI/O      : 1MHz (= 内蔵OSC 8MHz + CLKDIV8)
   * プリスケーラ: なし
   * モード      : Mode3 (高速PWM/0xFF)
   * OC0A端子    : 非反転モードで使用
   */

  while(1) {
    while(i<0xFF) {     // 2mSec間隔で輝度を上げていく
      OCR0A = ++i;
      _delay_ms(2);
    }
    _delay_ms(1000);    // 最高輝度で1秒保持

    while(i>0x00) {     // 2mSec間隔で輝度を下げていく
      OCR0A = --i;
      _delay_ms(2);
    }
    _delay_ms(1000);    // 最低輝度で1秒保持
  }
}

動画1 点滅の様子

参考文献


  1. Atmel ATmega48P/V 88P/V 168P/V datasheet
  2. ATmega168/328マイコンボード回路図

2014/03/30

タイマ割込みでLED点滅(AVR)

 前回の記事はLED点滅タイミングに_delay_ms()関数を使いましたが、今回はAVR内蔵タイマを使ってみたいと思います。ついでに外部クロックも使ってみたいと思います。

ゴール


     
  • LEDの点滅周期は1秒(点灯0.1秒、消灯0.9秒)
  • 点灯、および消灯のタイミングをタイマ割込みで行う  
  • 外部クロック(20MHz X'tal)を使う

タイマ割込みについて


 ATmega168は8bitタイマと16bitタイマを持っていますが、秒単位の長い時間を測るには8bitでは足りないので16bitタイマを使うことにします。タイマをピンに出力し直接LEDを制御しても良いのですが、ここではタイマ割込みを使います。
 タイマ/カウンタのブロック図が参考文献1のFigure16-1(16-bit Timer/Counter block Diagram)にあります。眺めてみると、タイマ値TCNTnと比較レジスタOCRnAが一致した時に割込みを発生させることができるようです。同様にOCRnBとの一致でも割込みを発生できるようです。タイマのクリアは"Control Logic"で行うようですが、この"Control Logic"に"TOP"という入力があり、OCRnAと一致した時に発生できるようです。
 TOPになるとタイマ値をクリアできれば指定した時間周期での割込みが発生できそうです。このような使い方はタイマをMode=4(CTC/OCR1A)にするとできるようです。このモードはOCR1Aレジスタに設定した値になるとカウンタが0に戻ります。(詳細は参考文献1の16.9.2章を参照のこと)
 これで2種類のタイマ割込みが用意できました。OCR1Aを1秒にOCR1Bを0.1秒に設定すればそれぞれの割込みでLED点灯、LED消灯ができます。
 ではOCR1A/OCR1Bにどんな値を設定すれば良いでしょうか? それにはタイマの1カウントがどのくらいの時間かを知る必要があります。タイマの1カウントは1クロック分なのでタイマに入力するクロックを調べる必要があります。

タイマに入力するクロックについて


 前述のタイマ/カウンタのブロック図を引き続き眺めてみます。"Control Logic"の入力に"clkTn"があります。ここがタイマに入力するクロックのようです。外部ピン入力とプリスケーラ入力から選択できるようです。ここではプリスケーラ入力を選びます。プリスケーラは参考文献1のTable 16-5(Clock Select Bit Description)によるとclkI/Oを1/1024まで分周できるようです。clkI/Oは参考文献1のFigure9-1(Clock Distribution)によると"AVR Clock Control Unit"の出力です。
 "AVR Clock Control Unit"の入力であるSystem ClockはFuseビットで設定します。Fuseビットの設定はAVRISPmkIIで書き込みをする時に設定します。Fuse設定は以下の3点を変更しました。
  • BODLVEL=4V3
  • SUT_CKSEL=EXTFSXTAL_1KCK_14CK_0MS
  • CKDIV8にチェックを入れる
 ここだけはAtmel Studioを使って書き込みをしています。この設定により外部クロック(20MHz X'tal)を使い、内部で1/8(つまり2.5MHz)にしてからタイマにclkI/Oが供給されます。
 プリスケーラの設定(参考文献1のTable16-5)を幾つにするかですが1/64にしました。これでタイマのクロックは39.0625KHz(=2.5MHz/64)になります。1秒タイマにするにはOCR1A=0x9897(=39,063)にします。

LEDについて


 LEDは前回と同じくPORT Bのbit5に接続されているLEDを使います。

プログラムについて


 例によってdebian環境(avr-gcc+avr-libc)で作成しています。

リスト1 main.c

/*
 * LED点滅プログラム(タイマ割込み使用)
 *
 * For AE-ATmega board
 *
 * Ver. 1.0 2014/03/30
 */
#include <avr/io.h>
#include <avr/interrupt.h>

void init_timer1(void) {

  /*
   * タイマ設定
   * 外部クロック   : 20MHz (X'tal)
   * CKDIV8=1       : 20MHz / 8 = 2.5MHz
   * プリスケーラ   : 2.5MHz / 64 = 39,062.5 Hz
   * 比較レジスタ1A : 39,063 ( 39,063/ 39,062.5 = 1.000013 Hz)
   * 比較レジスタ1B :  3,906
   * 波形発生モード : CTC(OCR1A)
   */

  /*
   * 比較レジスタ1Aで1秒毎に割込みを発生させる。→LED ON
   * 比較レジスタ1Bは1A割込み発生の0.1秒後に割込みが発生。→LED OFF
   */

  TCCR1A = 0x00;
  TCCR1B = _BV(WGM12) | _BV(CS11) | _BV(CS10);
  TCCR1C = 0x00;
  OCR1AH = 0x98;        // 16bitレジスタなので上位バイトを先にライトする
  OCR1AL = 0x97;        // OCR1A=39,063=0x9897
  OCR1BH = 0x0F;        // OCR1B=3,906=-0x0F42
  OCR1BL = 0x42;
  TIMSK1 = ( _BV(OCIE1B) | _BV(OCIE1A) );
  sei();                // Enable all interrupts
}

ISR(TIMER1_COMPA_vect) {
  PORTB |= _BV(PB5);    // LED ON
}

ISR(TIMER1_COMPB_vect) {
  PORTB &= !(_BV(PB5)); // LED OFF
}

int main(void) {

  DDRB  = _BV(DDB5);    // PORTB bit5を出力に設定

  init_timer1();        // タイマ初期化
  while(1);             // 無限ループ(割込み待ち)
}

参考文献


  1. Atmel ATmega48P/V 88P/V 168P/V datasheet
  2. avr libcのinterrupt.h解説

2014/03/22

AVR開発環境インストールからLED点滅まで(AVRマイコンボード)

 AVRの開発環境として通常は"Atmel Studio"を使うと思いますが、ここではdebianで使える物を選択してみました。Linux用のCコンパイラを探してみたところ、avr-gcc + avr-libcが使えるようです。debinの場合、以下のコマンドでインストールできます。
# apt-get install gcc-avr
# apt-get install binutils-avr
# apt-get install avr-libc
# apt-get install avrdude

LED点滅プログラムについて


 ATmega168/328マイコンボード回路図を見るとマイコンのPB5端子の先にLEDが接続されています。PB5にHを出力すればLEDが点灯します。このLEDを点滅するプログラムを書いてみます。

リスト1 blink_LED.c

/*
 * LED 点滅プログラム
 *
 *  K-04590 (ATMEGA168/328用マイコンボード)
 *
 */
#include <avr/io.h>
#include <util/delay.h>

#define PB5_LED   5             // H: LED ON | L: LED OFF

int main(void) {

  DDRB   = _BV(PB5_LED);        // Port B bit 5の方向を出力に設定
  PORTB |= _BV(PB5_LED);        // Port B bit 5にHを出力(LED点灯)

  while (1) {
    _delay_ms(500);             // 0.5秒待つ
    PORTB ^= _BV(PB5_LED);      // Port B bit5を0/1反転
  }
}
 0.5秒毎にLED点灯、LED消灯を繰り返すプログラムです。_delay_ms()や_BV()はavr-libcで定義されています。詳細は"AVR Libc Home Page"に説明があります。

F_CPUについて


 _delay_ms()を使うには事前にマクロ"F_CPU"を定義しておく必要があります。F_CPUにはCPUのクロック周波数を設定します。ソースコードの中に書いても良いのですが、ここではMakefileの中に定義しました。マイコンのクロック周波数は1MHzです。これは工場出荷時はクロックソースとしてマイコン内蔵オシレータ(8MHz)が選択されており、さらにCKDIV8オプションが設定されているため、1MHz(=8MHz÷8)になっているためです。したがってF_CPU=1000000を設定します。

リスト2 Makefile

PROG=blink_LED
OBJS=${PROG}.o
MCU=atmega168p
F_CPU=1000000UL # internal 8MHz clock & CKDIV8 fuse bit enabled
#--------

ELF=$(PROG)
IHEX=$(PROG).ihex

CC=avr-gcc
CFLAGS=-g2 -O1 -mmcu=$(MCU) -DF_CPU=$(F_CPU) -Wall
LDFLAGS=-g2 -mmcu=$(MCU)
OBJCOPY=avr-objcopy

all: $(IHEX)

$(IHEX): $(ELF)

$(ELF): $(OBJS)

%.ihex: %
        $(OBJCOPY) -j .text -j .data -O ihex $< $@

clean:
        -$(RM) $(ELF) $(IHEX) $(OBJS)

flash:
        sudo avrdude -c avrispmkII -P usb -p atmega168p -U flash:w:$(IHEX)

.PHONY: all clean
 Makefileを書くのは正直苦手で適当に書いています。(すみません)

リスト3 コンパイル&マイコン書き込み

$ make
avr-gcc -g2 -O1 -mmcu=atmega168p -DF_CPU=1000000UL  -Wall   -c -o blink_LED.o blink_LED.c
avr-gcc -g2 -mmcu=atmega168p  blink_LED.o   -o blink_LED
avr-objcopy -j .text -j .data -O ihex blink_LED blink_LED.ihex

$ make flash
sudo avrdude -c avrispmkII -P usb -p atmega168p -U flash:w:blink_LED.ihex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e940b
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "blink_LED.ihex"
avrdude: input file blink_LED.ihex auto detected as Intel Hex
avrdude: writing flash (166 bytes):

Writing | ################################################## | 100% 0.05s

avrdude: 166 bytes of flash written
avrdude: verifying flash memory against blink_LED.ihex:
avrdude: load data flash data from input file blink_LED.ihex:
avrdude: input file blink_LED.ihex auto detected as Intel Hex
avrdude: input file blink_LED.ihex contains 166 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.05s

avrdude: verifying ...
avrdude: 166 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

$
 debianマシンにAVRISPmkII経由でAVRマイコンボードを接続し、"make flash"と入力すればマイコンにプログラムが書き込まれます。

マンデルブロ集合の彩色方法(5)

06.knit 1 発散判定式を変更する mandelbrot() 内の発散判定式 \(|z_n| > 2\) を変更する...