ポートレジスタ (AVR)

ポートレジスタを操作すれば digitalRead() / digitalWrite() を高速化できます。

例えば LED を本当に同時に点灯させる必要がある場合や、ボタンの入力を高速に読み取る必要がある時に使えますが、MCU の違いによって操作するポートレジスタが異なります。



ピンとポート

ピンとポートの対応表です。AVR 系 Arduino で使われているを比較してみます。

PIN 328P 32U4 2560 4809
D0PD0PD2PE0PC5
D1PD1PD3PE1PC4
D2PD2PD1PE4PA0
D3PD3PD0PE5PF5
D4PD4PD4PG5PC6
D5PD5PC6PE3PB2
D6PD6PD7PH3PF4
D7PD7PE6PH4PA1
PIN 328P 32U4 2560 4809
D8 PB0PB4PH5PE3
D9 PB1PB5PH6PB0
D10PB2PB6PB4PB1
D11PB3PB7PB5PE0
D12PB4PD6PB6PE1
D13PB5PC7PB7PE2
PIN 328P 32U4 2560 4809
D14PJ1
D15PJ0
D16PH1
D17PH0
D18PD3
D19PD2
D20PD1
D21PD0
PIN 328P 32U4 2560 4809
D22PA0
D23PA1
D24PA2
D25PA3
D26PA4
D27PA5
D28PA6
D29PA7
D30PC7
D31PC6
D32PC5
D33PC4
D34PC3
D35PC2
D36PC1
D37PC0
D38PD7
D39PG2
D40PG1
D41PG0
D42PL7
D43PL6
D44PL5
D45PL4
D46PL3
D47PL2
D48PL1
D49PL0
D50PB3
D51PB2
D52PB1
D53PB0
PIN 328P 32U4 2560 4809
A0PC0PF7PF0PD3
A1PC1PF6PF1PD2
A2PC2PF5PF2PD1
A3PC3PF4PF3PD0
A4PC4PF1PF4PA2
PF2
A5PC5PF0PF5PA3
PF3
A6 PF6PD4
A7 PF7PD5
PIN 328P 32U4 2560 4809
A8 PK0
A9 PK1
A10PK2
A11PK3
A12PK4
A13PK5
A14PK6
A15PK7
PIN 328P 32U4 2560 4809
SDAPC4PD1PD1
SCLPC5PD0PD0
PIN 328P 32U4 2560 4809
RESETPC6PF6
PIN 328P 32U4 2560 4809
(ICSP) MISOPB3PB3PB3
(ICSP) SCLKPB1PB1PB1
(ICSP) MOSIPB2PB2PB2

328P 以外はキレイに並んでいるとは言い難いです。



ポートとピン

ポートとピンの対応表です。

PORT A
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4
2560 D29 D28 D27 D26 D25 D24 D23 D22
4809 [A5] [A4] D7 D2
PORT B
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P (ICSP) SCLK
D13
(ICSP) MISO
D12
(ICSP) MOSI
D11
D10 D9 D8
32U4 D11 D10 D9 D8 (ICSP) MISO (ICSP) MOSI (ICSP) SCLK (TX LED)
2560 D13 D12 D11 D10 (ICSP) MISO
D50
(ICSP) MOSI
D51
(ICSP) SCLK
D52
D53
4809 D5 D10 D9
PORT C
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P (RESET) SCL
A5
SDA
A4
A3 A2 A1 A0
32U4 D13 D5
2560 D30 D31 D32 D33 D34 D35 D36 D37
4809 D4 D0 D1
PORT D
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P D7 D6 D5 D4 D3 D2 D1 D0
32U4 D6 D12 (RX LED) D4 D1 D0 SCL
D2
SDA
D3
2560 D18 D19 SCL
D20
SDA
D21
4809 A8 A7 A6 A0 A1 A2 A3
PORT E
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4 D7
2560 D3 D2 D5 D1 D0
4809 D8 D13 D12 D11
PORT F
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4 A0 A1 A2 A3 A4 A5
2560 A7 A6 A5 A4 A3 A2 A1 A0
4809 (RESET) D3 D6 [A5] [A4]
PORT G
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4
2560 D4 D40 D41
4809
PORT H
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4
2560 D9 D8 D7 D6 D16 D17
4809
PORT J
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4
2560 D14 D15
4809
PORT K
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4
2560 A15 A14 A13 A12 A11 A10 A9 A8
4809
PORT L
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4
2560 D42 D43 D44 D45 D46 D47 D48 D49
4809


ポート操作 (megaAVR)

DDRx (Data Direction Register)

入出力の方向です。1 が出力 (OUTPUT)、0 が入力 (INPUT) です。DDRB は ポート B の入出力の方向を調べたり変更したりできます。機能的には pinMode() と同等です。

PORTx (Data Register)

ピンの状態です。1 が HIGH 、0 が LOW です。PORTB は入出力の方向が出力 (OUTPUT) になっているポート B のピンの状態を調べたり変更したりできます。機能的には digitalRead() / digitalWrite() と同等です。

PINx (Input Pins Register)

入力状態です。1 が HIGH 、0 が LOW です。PINB はポート B のピンの状態を調べられます。機能的には digitalRead() と同等です。



ポート操作 (megaAVR 0-series)

ATMega4809 では ATMega328P エミュレーションでないと上記ポート操作ができません。ATMega4809 でネイティブなポート操作を行うには VPORTx を使います。これはポートレジスタを I/O 空間にマップした仮想ポートです。

VPORTx.DIR

入出力の方向です。1 が出力 (OUTPUT)、0 が入力 (INPUT) です。VPORTB.DIR は ポート B の入出力の方向を調べたり変更したりできます。機能的には pinMode() と同等です。

VPORTx.OUT

ピンの状態です。1 が HIGH 、0 が LOW です。VPORTB.OUT は入出力の方向が出力 (OUTPUT) になっているポート B のピンの状態を調べたり変更したりできます。機能的には digitalRead() / digitalWrite() と同等です。

VPORTx.IN

入力状態です。1 が HIGH 、0 が LOW です。VPORTB.IN はポート B のピンの状態を調べられます。機能的には digitalRead() と同等です。

備考



コード移植

UNO のコード

例えば以下のようなコードがあったとします。UNO の MCU は ATMega328P です。

/*
 Conditions only for Arduino UNO
   RST_N- Pin9   
   SS   - Pin10
   MOSI - Pin11
   MISO - Pin12
   SCK  - Pin13
 */
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0

// only for Arduino UNO
void set_ss_pin(int val) {
    if(val ==HIGH) PORTB |= (4);
    else PORTB &= ~(4);
}

// only for Arduino UNO
void set_rst_pin(int val) {
    if(val ==HIGH) PORTB |= (2);
    else PORTB &= ~(2);
}

digitalWrite() で置き換えると以下のようになります。

/*
 Conditions only for Arduino UNO
   RST_N- Pin9   
   SS   - Pin10
   MOSI - Pin11
   MISO - Pin12
   SCK  - Pin13
 */
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0

// only for Arduino UNO
void set_ss_pin(int val) {
    digitalWrite(10, val);
}

// only for Arduino UNO
void set_rst_pin(int val) {
    digitalWrite(9, val);
}

UNO のボード画像の一部です。

SS ピンは D10 を使っています。UNO なので PB2、つまり PORT B の 2bit 目を操作しています。最下位ビットは bit0 なので 4 を OR したりビット反転した 4 を AND していたりします。

PORT B
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
0 0 0 0 0 1 0 0

RST ピンは D9 を使っています。UNO なので PB1、つまり PORT B の 1bit 目を操作しています。最下位ビットは bit0 なので 2 を OR したりビット反転した 2 を AND していたりします。

PORT B
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
0 0 0 0 0 0 1 0

LEONARDO へのコード

それを踏まえると LEONARDO (ATMega32U4) では以下のようなコードになります。

/*
 Conditions only for Arduino LEONARDO
   RST_N- Pin9   
   SS   - Pin10
   MOSI - Pin11
   MISO - Pin12
   SCK  - Pin13
 */
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0

// only for Arduino LEONARDO
void set_ss_pin(int val) {
    if(val ==HIGH) PORTB |= (64);
    else PORTB &= ~(64);
}

// only for Arduino LEONARDO
void set_rst_pin(int val) {
    if(val ==HIGH) PORTB |= (32);
    else PORTB &= ~(32);
}

LEONARDO のボード画像の一部です。

SS ピンは D10 を使っています。LEONARDO なので PB6、つまり PORT B の 6bit 目を操作しています。最下位ビットは bit0 なので 64 を OR したりビット反転した 64 を AND します。

PORT B
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
0 1 0 0 0 0 0 0

RST ピンは D9 を使っています。LEONARDO なので PB5、つまり PORT B の 5bit 目を操作しています。最下位ビットは bit0 なので 32 を OR したりビット反転した 32 を AND します。

PORT B
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
0 0 1 0 0 0 0 0

MEGA2560 へのコード

さらに MEGA2560 (ATMega2560) では以下のようなコードになります。

/*
 Conditions only for Arduino MEGA2560
   RST_N- Pin9   
   SS   - Pin10
   MOSI - Pin11
   MISO - Pin12
   SCK  - Pin13
 */
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0

// only for Arduino MEGA2560
void set_ss_pin(int val) {
    if(val ==HIGH) PORTB |= (16);
    else PORTB &= ~(16);
}

// only for Arduino MEGA2560
void set_rst_pin(int val) {
    if(val ==HIGH) PORTH |= (64);
    else PORTH &= ~(64);
}

MEGA2560 のボード画像の一部です。

SS ピンは D10 を使っています。MEGA2560 なので PB4、つまり PORT B の 4bit 目を操作しています。最下位ビットは bit0 なので 16 を OR したりビット反転した 16 を AND します。

PORT B
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
0 0 0 1 0 0 0 0

RST ピンは D9 を使っています。MEGA2560 なので PH6、つまり PORT H の 6bit 目を操作しています。最下位ビットは bit0 なので 64 を OR したりビット反転した 64 を AND します。

PORT H
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
0 1 0 0 0 0 0 0

Nano Every へのコード

Nano Every (ATMega4809) では ATMega328 エミュレーションを使えばコードの修正は不要です。

/*
 Conditions only for Arduino Nano Every
   RST_N- Pin9   
   SS   - Pin10
   MOSI - Pin11
   MISO - Pin12
   SCK  - Pin13
 */
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0

// only for Arduino Nano Every
void set_ss_pin(int val) {
    if(val ==HIGH) PORTB |= (4);
    else PORTB &= ~(4);
}

// only for Arduino Nano Every
void set_rst_pin(int val) {
    if(val ==HIGH) PORTB |= (2);
    else PORTB &= ~(2);
}

ATMega328 エミュレーションを使わない場合には、VPORT を使った次のようなコードになります。

/*
 Conditions only for Arduino Nano Every
   RST_N- Pin9   
   SS   - Pin10
   MOSI - Pin11
   MISO - Pin12
   SCK  - Pin13
 */
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0

// only for Arduino Nano Every
void set_ss_pin(int val) {
    if(val ==HIGH) VPORTB.OUT |= (2);
    else VPORTB.OUT &= ~(2);
}

// only for Arduino Nano Every
void set_rst_pin(int val) {
    if(val ==HIGH) VPORTB.OUT |= (1);
    else VPORTB.OUT &= ~(1);
}

Nano Every のボード画像の一部です。

SS ピンは D10 を使っています。Nano Every なので PB1、つまり PORT B の 1bit 目を操作しています。最下位ビットは bit0 なので 2 を OR したりビット反転した 2 を AND していたりします。

PORT B
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
0 0 0 0 0 0 1 0

RST ピンは D9 を使っています。Nano Every なので PB0、つまり PORT B の 0bit 目を操作しています。最下位ビットは bit0 なので 1 を OR したりビット反転した 1 を AND していたりします。

PORT B
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
0 0 0 0 0 0 0 1

注意点


ここにある情報が役に立って、「調べる手間が省けたからオマイに飯でもおごってやるよ」 というハートウォーミングな方がいらっしゃいましたら、下のボタンからどうぞ。

メニュー: