上野家のホームページ
ナーマル,マリン,ココ
[
新規
|
一覧
|
検索
|
最新
|
ヘルプ
]
開発/AVR/入出力ポート
をテンプレートにして作成
資料室
開発/AVR/入出力ポート をテンプレートにして作成
[
差分
|
バックアップ
|
リロード
]
[ ]
開始行:
#contents
*AVR内の汎用レジスタ・メモリ・I/Oレジスタ
**AVRのメモリマップ
AVRには,3タイプのメモリエリアがある。1つは,「プログラ...
もう1つが汎用レジスタ,SRAMメモリ,I/Oレジスタなどがある...
汎用レジスタとSRAMメモリは,データの記憶に用いられます。~
さらにもう1つ,EEPROMというメモリを持っていますが,これ...
***I/Oレジスタとは
I/Oレジスタ(特殊機能レジスタ)とは,AVRの内蔵機能にアクセ...
「内蔵機能」には,UARTやTIMER,汎用I/Oポートなどがある。
**入出力ポートの使いかた
入出力ポートに関係するレジスタは,ポート毎に3つある。
ポートBについて記述するが,ポートA,C,Dなどでも同様になっ...
-ポートB方向レジスタ DDRB (ポートAならDDRA) ~
DDRBにデータを書き込むと,1が書き込まれたbitに対応するピ...
DDRB = 0xF0; // ポートBのpin0~3を入力に,pin4~7を出...
WinAVR上では,レジスタは8bit整数変数のように使えます。代...
-ポートB出力レジスタ PORTB (ポートAならPORTA) ~
このレジスタは,ポートBに対応する出力用データレジスタです...
DDRB = 0xFF; // ポートBを全て出力設定
PORTB = 0xAA; // PORTBのpin7,5,3,1をHigh,pin6,4,2,...
char res = PORTB; // PORTBを変数resに読み取る((ピンの入...
なお,書き込んでからピンの電圧が変化するまでに最悪で1.5サ...
-ポートB入力レジスタ PINB (ポートAならPINA) ~
これはポートBに対応する,入力用データレジスタです。入力設...
WinAVR上では,レジスタは8bit整数変数のように使えます。変...
DDRB = 0x00; // ポートBを全て入力設定
PORTB = 0xFF; // PORTBの各ビットを全てセット
// →対応する入力ポートのプルアップ
char res = PINB; // ポートBに与えられた電圧を変数resに...
// Highなら1,Lowなら0
char res2 = PORTB; // これは、先にPORTBに書き込んだ値が...
入力ピンに対応するPORTBレジスタをセット(1)にすると,入力...
外部につなぐ回路に応じて選択する。
***PINXへの書き込み→PORTXのトグル
一部のAVR(*)には通常の入力レジスタのPINBのbit-nに1を書き...
DDRB = 0xFF; // ポートBを全て出力設定
PORTB = 0xF0; // PORTB書き込み→ポートBのPB4からPB7...
PINB = 0xFF; // PINBのbit7-0に書き込む→ポートBのPB...
((PINxnに1を書き込むと,PORTxnの値が反転するMCU は,ATtin...
**ポート・メモリ・レジスタを操作するために便利なマクロなど
***_BV(bit)
ヘッダファイル<avr/io.h>で,AVR各レジスタのビット名とビッ...
たとえば,PORTBのbit0からbit7に対応して,PB0からPB7という...
ビット位置から簡単にレジスタに出力すべき値を記述できるよ...
これを使って特定のビットを読み取る処理をわかりやすく書け...
たとえば,_BV(PINA6)は (1<<PINA6)を返し,これはPINA6に対応...
// _BVの使用例
PORTB = _BV(PB1); // PB1ピンだけをHighにし...
PORTB = PORTB | _BV(PB1); // PB1ピンをHighにし,残...
PORTB |= _BV(PB1); // こう書いてもいい
PORTB = PORTB & ~_BV(PB1); // _BV(PB1)のビット反転と...
PORTB &= ~_BV(PB1); // こう書いてもいい
uint8_t result;
result = PINB;
result = result & _BV(PINB1); // 変数に対して使ってもいい
uint16_t tm;
tm = _BV(15); // 16bit整数のbit15を1にする
なお,_BV()はそのままでは16bitにしか対応できません。32bit...
#define _BV32(bit) (1L << (bit))
***sbi(),cbi() -- 2005/02時点にて既に削除されました。
最新版WinAVR(20050214)で削除されました。
void sbi (uint8_t port, uint8_t bit):
void cbi (uint8_t port, uint8_t bit):
sbi()関数で指定レジスタの指定のビットをセット(1)にするこ...
cbi()関数で指定レジスタの指定のビットをクリア(0)にするこ...
sbi(PORTB, 3); // PORTBのbit3をset
sbi(PORTB, PB3); // こちらでもいいです。
sbi(GIFR, INT0); // bit名に意味のある名前が付いている...
// それを使った方がわかりやすい
以下のように書いてください。
PORTB |= _BV(3); // PORTBのbit3をセット
PORTB &= ~_BV(4); // PORTBのbit3をクリア
しかしこのマクロ,削除するには惜しいほど使いやすいです。...
#define cbi(addr,bit) addr &= ~(1<<bit)
#define sbi(addr,bit) addr |= (1<<bit)
***ビットチェック bit_is_set(),bit_is_clear()
-bit_is_set()は指定レジスタの指定のビットがセット(1)され...
-bit_is_clear()は指定レジスタの指定のビットがセット(1)さ...
条件分岐などと共に使うと便利です。
// example:
if (bit_is_set(PINB, PINB3)) {
// ポートBの入力 PINB3が1(入力がHi)なら、if節内の処...
}
if (bit_is_clear(PINB, PINB3)) {
// ポートBの入力 PINB3が0(入力がLo)なら、if節内の処...
}
***loop_until_bit_is_set(),loop_until_bit_is_clear()
名前の通り指定のビットがセットされるまで/クリアされるまで...
loop_until_bit_is_set(PINB,PINB3);
// ポートBの入力 PINB3が1(入力がHi)になるまで待つ
↓この形式では利用できません。
loop_until_bit_is_set(PINB,PINB3)
{
// PINB3が1になるまでこの処理を行う・・・コンパイル...
}
↓このように使ってください。
while( bit_is_clear(PINB,PINB3) )
{
// PINB3が0の間この処理を行う
}
**I/Oポート(I/Oレジスタ)の使い方=入出力ポートと基本的に...
***I/Oポートとは?
入出力ポート以外にも多くの付加機能を持ったI/Oポートがあり...
あるものは内蔵機能の動きをコントロールし(コントロールレ...
WinAVRでの扱いは入出力ポートと同じです。
タイマ0のコントロールレジスタ→TCCR0
タイマ0のデータレジスタ→TCNT0
これらのI/Oレジスタは "Special Function Registers (SFR) ...
MPU名をmakefileで適切に指定してあれば,指定プロセッサにあ...
各レジスタはデータシートにある名前と同じ名の変数として扱...
***ペアレジスタ(16bitレジスタ)
レジスタやIOレジスタの中には,値が8bitに収まらないため上...
そのうちTimer1の16biレジスタなどについては,2バイトいっぺ...
a=TCNT1L; //TCNT1Lの値だけを取得 a = *(volatile uint8...
a=TCNT1; //TCNT1H*256+TCNT1Lを取得 a = *(volatile uint1...
AVRは8bitCPUで,1度に上位下位16bit分のレジスタ値を取得す...
1バイトずつアクセスする方法と対比させてみると以下のように...
従来の方法 新しい方法
uint16_t tm; uint16_t tm;
uint8_t tm_l,tm_h;
tm_l = TCNT1L;
tm_h = TCNT1H;
tm = tm_h<<8 + tm_l; tm = TCNT1; //TCNT1の性質に...
TCNT1H = tm>>8;
TCNT1L = tm&255; TCNT1 = tm; //TCNT1の性質に...
タイマ関連レジスタについては,それ自身の値や比較対象の値...
たいていの16bitレジスタは,上記のTCNT1のように,hogehogeL...
例外もあります。~
AD変換のデータレジスタは,ADCL,ADCHはADCではなく,ADCWと...
また,連続したアドレスにないためペアレジスタの形で扱えな...
**レジスタの取扱で注意する点
***1を書き込むとビットクリアとなるレジスタがあります。
GIFR(一般割り込み要求フラグレジスタ)やTIFR(タイマ割り込み...
GIFR=0xC0(INTF1,INTF0が1)の時、GIFR=_BV(INTF1);を実行
→GIFRは0x40になる(bit7(INTF1)のみクリア)
間違いの例
× GIFR = GIFR | _BV(INTF1);
× GIFR |= _BV(INTF1);
× sbi(GIFR,INTF1);
→まちがい。これをやると、たとえばINTF0もセットされている...
INTF0に1を書き込むことになり、INTF0までクリアしてし...
(read-modify-write動作の落とし穴)
■■□□□□□□ GIFR INTF1(bit7)とINTF0(bit6)が立っている
■■□□□□□□ GIFR値|_BV(INTF1)
□□□□□□□□ ↑を書き込むと、INTF0もクリア対象になる!
通常のビットと,1書き込みでクリアとなるビット両方が混在し...
この場合は,通常ビットの部分はこれまでの値を,1書き込みで...
TWI(I2C)のTWCRレジスタなどがそれに該当します。~
以下のように通常ビットを他の変数や定数に保持しておくと便...
#define TWCR_value _BV(TWEN);
TWCR = TWCR_value | _BV(TWINT);
***複数のbitに同時に書き込みをかける必要があるレジスタ
一部のレジスタについては,同時に書き込みをかけないと機能...
EEPROM制御アドレスEECRのEEPM1/EEPM0(mega/tinyシリーズ)な...
***書き込みに時間制限があるレジスタ
容易に変更されては困るビットの中には,ビットを鍵として,...
WDTCR(ウォッチドッグタイマコントロールレジスタ)などがそれ...
**備考
PINxnのsbi命令でのトグル動作の不思議
-新しいMCUはPINXnを書き込むとPORTxnの値が反転になる仕様で...
-sbi命令はリードモデファイライト命令であるので,ポートの...
-データシートの標準デジタル入出力回路構成を見ると,読み書...
これは1ビット単位での書き換えは出来ないことを意味してい...
入出力回路構成図にもビット単位で処理できるような構造は描...
sbi,cbiではポート読込⇒ビット処理⇒ポート書込とやっているは...
-DDRxやPORTxにsbi命令を使用してもMCU外部からの影響は受け...
-PINxはピンの状態が反映されるのでPORTxnを出力にして1を出...
-ここで疑問~
PINxnに1を書くとPORTxnが反転するのであるが,sbi命令で操...
-確認してみました・・・(ATmega48)~
PORTB0,PORTB1を出力にしてともに1を出力しておく。~
sbi PINB,0を実行してみる~
PORTB0だけが反転しました(問題なし)~
これはPINBに0bxxxxxx01 を書き込んだことになる~
-ちなみにPINBを読み込んでBit0を1にしてPINBに書き込むとい...
PORTB0,PORTB1ともに反転しました~
これは,PINBに0bxxxxxx11を書き込んだことになる。~
-いったいどうゆう機構になっているのでしょう?
sbiは[ポート読込⇒ビット処理⇒ポート書込]とは違う?~
PINxに対してのsbiだけ特別な機構があるのでしょうか?~
-結論~
PINxに対してsbi命令を使用しても問題なし(データシートにも...
パルスを高速に連続して出力するにはout命令でPINxに書き込む...
**付加機能
多くのポートは付加機能を持っている。~
いくつかのピンはプロセッサ内の付加機能の入出力としても使...
終了行:
#contents
*AVR内の汎用レジスタ・メモリ・I/Oレジスタ
**AVRのメモリマップ
AVRには,3タイプのメモリエリアがある。1つは,「プログラ...
もう1つが汎用レジスタ,SRAMメモリ,I/Oレジスタなどがある...
汎用レジスタとSRAMメモリは,データの記憶に用いられます。~
さらにもう1つ,EEPROMというメモリを持っていますが,これ...
***I/Oレジスタとは
I/Oレジスタ(特殊機能レジスタ)とは,AVRの内蔵機能にアクセ...
「内蔵機能」には,UARTやTIMER,汎用I/Oポートなどがある。
**入出力ポートの使いかた
入出力ポートに関係するレジスタは,ポート毎に3つある。
ポートBについて記述するが,ポートA,C,Dなどでも同様になっ...
-ポートB方向レジスタ DDRB (ポートAならDDRA) ~
DDRBにデータを書き込むと,1が書き込まれたbitに対応するピ...
DDRB = 0xF0; // ポートBのpin0~3を入力に,pin4~7を出...
WinAVR上では,レジスタは8bit整数変数のように使えます。代...
-ポートB出力レジスタ PORTB (ポートAならPORTA) ~
このレジスタは,ポートBに対応する出力用データレジスタです...
DDRB = 0xFF; // ポートBを全て出力設定
PORTB = 0xAA; // PORTBのpin7,5,3,1をHigh,pin6,4,2,...
char res = PORTB; // PORTBを変数resに読み取る((ピンの入...
なお,書き込んでからピンの電圧が変化するまでに最悪で1.5サ...
-ポートB入力レジスタ PINB (ポートAならPINA) ~
これはポートBに対応する,入力用データレジスタです。入力設...
WinAVR上では,レジスタは8bit整数変数のように使えます。変...
DDRB = 0x00; // ポートBを全て入力設定
PORTB = 0xFF; // PORTBの各ビットを全てセット
// →対応する入力ポートのプルアップ
char res = PINB; // ポートBに与えられた電圧を変数resに...
// Highなら1,Lowなら0
char res2 = PORTB; // これは、先にPORTBに書き込んだ値が...
入力ピンに対応するPORTBレジスタをセット(1)にすると,入力...
外部につなぐ回路に応じて選択する。
***PINXへの書き込み→PORTXのトグル
一部のAVR(*)には通常の入力レジスタのPINBのbit-nに1を書き...
DDRB = 0xFF; // ポートBを全て出力設定
PORTB = 0xF0; // PORTB書き込み→ポートBのPB4からPB7...
PINB = 0xFF; // PINBのbit7-0に書き込む→ポートBのPB...
((PINxnに1を書き込むと,PORTxnの値が反転するMCU は,ATtin...
**ポート・メモリ・レジスタを操作するために便利なマクロなど
***_BV(bit)
ヘッダファイル<avr/io.h>で,AVR各レジスタのビット名とビッ...
たとえば,PORTBのbit0からbit7に対応して,PB0からPB7という...
ビット位置から簡単にレジスタに出力すべき値を記述できるよ...
これを使って特定のビットを読み取る処理をわかりやすく書け...
たとえば,_BV(PINA6)は (1<<PINA6)を返し,これはPINA6に対応...
// _BVの使用例
PORTB = _BV(PB1); // PB1ピンだけをHighにし...
PORTB = PORTB | _BV(PB1); // PB1ピンをHighにし,残...
PORTB |= _BV(PB1); // こう書いてもいい
PORTB = PORTB & ~_BV(PB1); // _BV(PB1)のビット反転と...
PORTB &= ~_BV(PB1); // こう書いてもいい
uint8_t result;
result = PINB;
result = result & _BV(PINB1); // 変数に対して使ってもいい
uint16_t tm;
tm = _BV(15); // 16bit整数のbit15を1にする
なお,_BV()はそのままでは16bitにしか対応できません。32bit...
#define _BV32(bit) (1L << (bit))
***sbi(),cbi() -- 2005/02時点にて既に削除されました。
最新版WinAVR(20050214)で削除されました。
void sbi (uint8_t port, uint8_t bit):
void cbi (uint8_t port, uint8_t bit):
sbi()関数で指定レジスタの指定のビットをセット(1)にするこ...
cbi()関数で指定レジスタの指定のビットをクリア(0)にするこ...
sbi(PORTB, 3); // PORTBのbit3をset
sbi(PORTB, PB3); // こちらでもいいです。
sbi(GIFR, INT0); // bit名に意味のある名前が付いている...
// それを使った方がわかりやすい
以下のように書いてください。
PORTB |= _BV(3); // PORTBのbit3をセット
PORTB &= ~_BV(4); // PORTBのbit3をクリア
しかしこのマクロ,削除するには惜しいほど使いやすいです。...
#define cbi(addr,bit) addr &= ~(1<<bit)
#define sbi(addr,bit) addr |= (1<<bit)
***ビットチェック bit_is_set(),bit_is_clear()
-bit_is_set()は指定レジスタの指定のビットがセット(1)され...
-bit_is_clear()は指定レジスタの指定のビットがセット(1)さ...
条件分岐などと共に使うと便利です。
// example:
if (bit_is_set(PINB, PINB3)) {
// ポートBの入力 PINB3が1(入力がHi)なら、if節内の処...
}
if (bit_is_clear(PINB, PINB3)) {
// ポートBの入力 PINB3が0(入力がLo)なら、if節内の処...
}
***loop_until_bit_is_set(),loop_until_bit_is_clear()
名前の通り指定のビットがセットされるまで/クリアされるまで...
loop_until_bit_is_set(PINB,PINB3);
// ポートBの入力 PINB3が1(入力がHi)になるまで待つ
↓この形式では利用できません。
loop_until_bit_is_set(PINB,PINB3)
{
// PINB3が1になるまでこの処理を行う・・・コンパイル...
}
↓このように使ってください。
while( bit_is_clear(PINB,PINB3) )
{
// PINB3が0の間この処理を行う
}
**I/Oポート(I/Oレジスタ)の使い方=入出力ポートと基本的に...
***I/Oポートとは?
入出力ポート以外にも多くの付加機能を持ったI/Oポートがあり...
あるものは内蔵機能の動きをコントロールし(コントロールレ...
WinAVRでの扱いは入出力ポートと同じです。
タイマ0のコントロールレジスタ→TCCR0
タイマ0のデータレジスタ→TCNT0
これらのI/Oレジスタは "Special Function Registers (SFR) ...
MPU名をmakefileで適切に指定してあれば,指定プロセッサにあ...
各レジスタはデータシートにある名前と同じ名の変数として扱...
***ペアレジスタ(16bitレジスタ)
レジスタやIOレジスタの中には,値が8bitに収まらないため上...
そのうちTimer1の16biレジスタなどについては,2バイトいっぺ...
a=TCNT1L; //TCNT1Lの値だけを取得 a = *(volatile uint8...
a=TCNT1; //TCNT1H*256+TCNT1Lを取得 a = *(volatile uint1...
AVRは8bitCPUで,1度に上位下位16bit分のレジスタ値を取得す...
1バイトずつアクセスする方法と対比させてみると以下のように...
従来の方法 新しい方法
uint16_t tm; uint16_t tm;
uint8_t tm_l,tm_h;
tm_l = TCNT1L;
tm_h = TCNT1H;
tm = tm_h<<8 + tm_l; tm = TCNT1; //TCNT1の性質に...
TCNT1H = tm>>8;
TCNT1L = tm&255; TCNT1 = tm; //TCNT1の性質に...
タイマ関連レジスタについては,それ自身の値や比較対象の値...
たいていの16bitレジスタは,上記のTCNT1のように,hogehogeL...
例外もあります。~
AD変換のデータレジスタは,ADCL,ADCHはADCではなく,ADCWと...
また,連続したアドレスにないためペアレジスタの形で扱えな...
**レジスタの取扱で注意する点
***1を書き込むとビットクリアとなるレジスタがあります。
GIFR(一般割り込み要求フラグレジスタ)やTIFR(タイマ割り込み...
GIFR=0xC0(INTF1,INTF0が1)の時、GIFR=_BV(INTF1);を実行
→GIFRは0x40になる(bit7(INTF1)のみクリア)
間違いの例
× GIFR = GIFR | _BV(INTF1);
× GIFR |= _BV(INTF1);
× sbi(GIFR,INTF1);
→まちがい。これをやると、たとえばINTF0もセットされている...
INTF0に1を書き込むことになり、INTF0までクリアしてし...
(read-modify-write動作の落とし穴)
■■□□□□□□ GIFR INTF1(bit7)とINTF0(bit6)が立っている
■■□□□□□□ GIFR値|_BV(INTF1)
□□□□□□□□ ↑を書き込むと、INTF0もクリア対象になる!
通常のビットと,1書き込みでクリアとなるビット両方が混在し...
この場合は,通常ビットの部分はこれまでの値を,1書き込みで...
TWI(I2C)のTWCRレジスタなどがそれに該当します。~
以下のように通常ビットを他の変数や定数に保持しておくと便...
#define TWCR_value _BV(TWEN);
TWCR = TWCR_value | _BV(TWINT);
***複数のbitに同時に書き込みをかける必要があるレジスタ
一部のレジスタについては,同時に書き込みをかけないと機能...
EEPROM制御アドレスEECRのEEPM1/EEPM0(mega/tinyシリーズ)な...
***書き込みに時間制限があるレジスタ
容易に変更されては困るビットの中には,ビットを鍵として,...
WDTCR(ウォッチドッグタイマコントロールレジスタ)などがそれ...
**備考
PINxnのsbi命令でのトグル動作の不思議
-新しいMCUはPINXnを書き込むとPORTxnの値が反転になる仕様で...
-sbi命令はリードモデファイライト命令であるので,ポートの...
-データシートの標準デジタル入出力回路構成を見ると,読み書...
これは1ビット単位での書き換えは出来ないことを意味してい...
入出力回路構成図にもビット単位で処理できるような構造は描...
sbi,cbiではポート読込⇒ビット処理⇒ポート書込とやっているは...
-DDRxやPORTxにsbi命令を使用してもMCU外部からの影響は受け...
-PINxはピンの状態が反映されるのでPORTxnを出力にして1を出...
-ここで疑問~
PINxnに1を書くとPORTxnが反転するのであるが,sbi命令で操...
-確認してみました・・・(ATmega48)~
PORTB0,PORTB1を出力にしてともに1を出力しておく。~
sbi PINB,0を実行してみる~
PORTB0だけが反転しました(問題なし)~
これはPINBに0bxxxxxx01 を書き込んだことになる~
-ちなみにPINBを読み込んでBit0を1にしてPINBに書き込むとい...
PORTB0,PORTB1ともに反転しました~
これは,PINBに0bxxxxxx11を書き込んだことになる。~
-いったいどうゆう機構になっているのでしょう?
sbiは[ポート読込⇒ビット処理⇒ポート書込]とは違う?~
PINxに対してのsbiだけ特別な機構があるのでしょうか?~
-結論~
PINxに対してsbi命令を使用しても問題なし(データシートにも...
パルスを高速に連続して出力するにはout命令でPINxに書き込む...
**付加機能
多くのポートは付加機能を持っている。~
いくつかのピンはプロセッサ内の付加機能の入出力としても使...
ページ名:
Counter: 0, today: 0, yesterday: 0
Copyright©2008 Yuji Ueno All Rights Reserved.
ログイン
ユーザ名:
パスワード:
IDとパスワードを記憶
パスワード紛失
メインメニュー
ホーム
でぶlog
資料室
最新ページ一覧
全ページ一覧
ヘルプ
フォーラム
お問い合わせ