2020年6月21日日曜日

atmega328pbや328pの水晶振動子用のピンは、内部クロックを使う場合、MiniCoreを利用すればデジタルピンとして利用できる


背景

atmega328pbで追加されたピンを操作したりI2Cポートを同時に利用したりしたときに利用したMiniCoreというボード情報のピンの定義を見ていると、振動子に割り当てられているピンをデジタルピンとしても利用できそうな記述を発見しました。
試してみると利用できたので、備忘録を兼ねてやったことを共有します。

使ったもの

  • PlatformIOを利用できるPC
    ArduinoIDEでもMiniCoreをボード情報として設定すれば同様のことをできると思いますが、PlatformIOの方が設定が楽だと思うので試していません。
  • atmega328pb
  • Arduino as ISPを書き込んだProMicro
  • ブレッドボード、抵抗、LED、ジャンパワイヤ、タクトスイッチ、はんだ、はんだごて、ホットメルト
    信号線を引き出してLEDを光らせたり、ボタンの値を入力したりしました。

ピンを引き出す

atmega328pbや328pの水晶振動子用のピンはVQFNや32MULパッケージでは7番8番ピンとして出ています。



隣り合っているピンを両方を出すのは難しかったため、8番ピンとして出ているPB7を引き出しました。
線が細くて剥がれやすいため、はんだ付けした後にホットメルトでワイヤーを固定しています。


このピンで動作を確認します。

プログラムを書き込むためのプロジェクトを準備

PlatformIOで、atmega328pbを内部クロックで8MHzとして動かし、Arduino as ISPでプログラムを書き込むプロジェクトを作りました。
platformio.ini
[env:ATmega328PB]
platform = atmelavr
board = ATmega328PB
framework = arduino
board_build.f_cpu = 8000000L
upload_protocol = stk500v1
upload_port = /dev/ttyACM0
upload_speed = 19200
upload_flags =
-b$UPLOAD_SPEED
-P$UPLOAD_PORT
; use internal 8MHz and not divide it by 8
-Ulfuse:w:0xE2:m

要所を解説します。

ボード情報をATMega328PBとして動かします。
[env:ATmega328PB]
platform = atmelavr
board = ATmega328PB
framework = arduino

内部クロックを利用して8MHzで動作させます。
ヒューズの詳しい設定が知りたい場合はマイコンのデータシートを見てください。
[env:ATmega328PB]
board_build.f_cpu = 8000000L
upload_flags =
; use internal 8MHz and not divide it by 8
-Ulfuse:w:0xE2:m

書き込みはArduino as ISPを書き込んだLeonardoを利用します。
プログラマーの設定はPlatormIOのページ(Upload using Programmer)が参考になると思います。
[env:ATmega328PB]
upload_protocol = stk500v1
upload_port = /dev/ttyACM0
upload_speed = 19200
upload_flags =
-b$UPLOAD_SPEED
-P$UPLOAD_PORT

プログラマーを設定したので、下記のようなprogramコマンドでプログラムを書き込めます。
pio run -t program

このプロジェクトのsrc/main.cppにプログラムを書きます。

MiniCoreで水晶振動子用のピンはD20とD21に定義されている

ボード情報のピンの定義を見ると、D20にPB6が、D21にPB7が割り当てられていることが分かります。


LEDを光らせる

D21でLEDを1秒ことに光らせたり消したりします。
#include <Arduino.h>
#define PIN_OUT 21

void setup() {
pinMode(PIN_OUT, OUTPUT);
}

void loop() {
digitalWrite(PIN_OUT, HIGH);
delay(1000);
digitalWrite(PIN_OUT, LOW);
delay(1000);
}


LEDを点滅させれました。

ボタンの入力を受け付ける

D22をLEDに接続し、INPUT_PULLUPで動作するD21の電位が下がったとき(ボタンを押された時)にD22の電位を上げてLEDを光らせます。

#include <Arduino.h>
#define PIN_IN 21
#define PIN_OUT 22

void setup() {
pinMode(PIN_OUT, OUTPUT);
pinMode(PIN_IN, INPUT_PULLUP);
}

void loop() {
digitalWrite(PIN_OUT, !digitalRead(PIN_IN));
delay(100);
}


D21でボタンの入力を受け付けて、押した時にLEDが光る仕組みを作れました。

余談: Arduino Unoなどを定義するcore-avrでは水晶振動子用のピンはデジタルピンとしては定義されていない

UnoでのPB6とPB7の扱いがどうなっているのか調べてみたところ、ポートBの端子は0-5はデジタルピンとして割り当てられていましたが、水晶振動子用のPB6とPB7は割り当てられていませんでした。


まあ、Arduinoではそのピンは水晶振動子に割り当てている設計なので、利用は想定していないようです。
ポートレジスタを使えば電位を変えられると思いますが、水晶振動子の波を認識できなくなるので、多分動作停止すると思います。

まとめ

内部クロックで動作させるatmega328pbでMiniCoreのボード情報を利用して、水晶振動子を割り当てられるピンでLEDの点滅やボタンの入力ができました。
水晶振動子を利用しない場合は利用できるピンの数が増えることが分かり、嬉しいです。

0 件のコメント :