ポートレジスタ (AVR)

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

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



ピンとポート

ピンとポートの対応表です。AVR 系 Arduino でメジャーな を比較してみます。

PIN 328P 32U4 2560
D0PD0PD2PE0
D1PD1PD3PE1
D2PD2PD1PE4
D3PD3PD0PE5
D4PD4PD4PG5
D5PD5PC6PE3
D6PD6PD7PH3
D7PD7PE6PH4
PIN 328P 32U4 2560
D8 PB0PB4PH5
D9 PB1PB5PH6
D10PB2PB6PB4
D11PB3PB7PB5
D12PB4PD6PB6
D13PB5PC7PB7
PIN 328P 32U4 2560
D14PJ1
D15PJ0
D16PH1
D17PH0
D18PD3
D19PD2
D20PD1
D21PD0
PIN 328P 32U4 2560
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
A0PC0PF7PF0
A1PC1PF6PF1
A2PC2PF5PF2
A3PC3PF4PF3
A4PC4PF1PF4
A5PC5PF0PF5
A6 PF6
A7 PF7
PIN 328P 32U4 2560
A8PK0
A9PK1
A10PK2
A11PK3
A12PK4
A13PK5
A14PK6
A15PK7
PIN 328P 32U4 2560
SDAPC4PD1PD1
SCLPC5PD0PD0
PIN 328P 32U4 2560
RESETPC6
PIN 328P 32U4 2560
(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
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
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
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
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
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
PORT G
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4
2560 D4 D40 D41
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
PORT J
bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
128 64 32 16 8 4 2 1
328P
32U4
2560 D14 D15
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
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


ポート操作

DDR (Data Direction Register)

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

PORT (Data Register)

ピンの状態です。1 が HIGH 、0 が LOW です。PORTB は ポート B のピンの状態を調べたり変更したりできます。機能的には digitalRead() / digitalWrite() と同等です。

PIN (Input Pins Register)

入力状態です。1 が HIGH 、0 が LOW です。PINB は 入出力の方向が出力 (INPUT) になっているポート 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

注意点


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

メニュー: