12F675覚書
〔PICの動かせ方入門に戻る〕
忘れないうちにメモします。
ここでの記載はHI-TECH C Compiler for PIC10/12/16 MCUs(Lite Mode)を使用しての内容です。
データシートはこちらです。英語だけどね
PICの内部に付いているクロック周波数回路(4MHz)を利用する場合、
PICのプログラムメモリエリアの最終番地(3FF)にリセット電圧の閾値と内蔵クロック周波数回路の
精度を良くする為の調整用キャリブレーション・データが書き込まれています。
プログラミング時にこのデータを利用する処理を記述しないといけない、
だが、"HI-TECH C Compiler"はこの処理を自動的にコンパイル時追加するので処理の記述は必要ないです
ちなみに記述する場合は、
OSCCAL = _READ_OSCCAL_DATA() ;
です。
最終番地のデータを消してしまった時の為にデータを書いたシールをPICに張り付けた方がいいかも。
精度が良いクロック発振周波数が欲しいなら外付けの発振子を付けます、最大20MHzが付けられます
ソフトで通信を行う場合、どうしてもタイミングが合わないなどの時に外付けの発振子を付けると出来る
場合があります。
外付けの発振子を付ける場合は、__CONFIG(INTIO) ;を__CONFIG(HS) ;に代えます。
__CONFIG(MCLRDIS):外部リセット信号は使用しない、GP3がデジタル入出力で使えます。
リセット信号を使用する場合は、MCLRENとします。
__CONFIG(BOREN):電源電圧降下の常時監視機能を許可します、
だいたい2.025-2.175Vに降下したらリセットがかかります。
delay関数を使用する場合は、
#include <htc.h>のヘッダファイルを追加して
#define _XTAL_FREQ 4000000の行を追加するただしこれはクロックが4MHzの場合
__delay_us(197120) __delay_ms(197) クロック4MHzならこの値まで設定可能
ただし、( )の中は変数使用不可です、直接数値を入力、うんん...ちょっとぉいまいち!
197ms以上待たせたいなら、
for (i=0 ; i < 100 ; i++) __delay_ms(10) ; // 1秒待つ
という感じにします。
PS.
air variableさんのブログ情報によればHI-TECH C Compiler Ver9.80以降では
delay関数の設定可能時間がのびているらしいです。
クロック4MHzで__delay_us(50462464) __delay_ms(50462)
Vpp
PICチップにプログラムを書込む時の、書込み電圧を負荷するピンという意味なので、
動作時には気にしなくて良い。
MCLR
外部リセット信号を入力する場合のピンとして使用。
リセット信号はLOW(0V:GND接続)でリセットが掛かります、だから
外部リセットを使わない時は100Ω〜10KΩ抵抗を介してVddに接続しなければならない。
GP3
Vddに接続するのは面倒なのでMCLRをDisable(禁止)にし、GP3の入力端子とした方が良いでしょう。
__CONFIG(MCLRDIS)を記述すればDisableに出来ます。
TIMER0機能は設定した時間毎に割込み処理を行うものです。
また、外部ピン入力からの信号でカウントする機能があります。
割込みとは?
たとえば、Aさんと電話していて、Bさんから割込みキャッチホンがはいれば、
Bさんと話して終わったらAさんと続きを話しますよね、これと同じ事です。
プログラムのmain()を処理中にTIMER0割込みがはいれば、main()を一時中断後
interrupt InterTimer()を処理して再びmain()を再開します。
(InterTimerの関数名は変更できます)
割込み発生タイミング
TIMER0はTMR0(8ビット)のレジスターをカウントアップして行きます、
256になった時点(オーバーフロー)で割込みを発生させます。
例えば、TMR0=100と設定した場合は100から256までカウントアップして行きます、
256-100で156カウントした所でオーバーフローし割込み発生です。
(割込み発生したらTMR0はゼロになっています、TMR0=100したいなら割込み処理の中で再設定)
ワンカウントの時間は?
PICのクロック周波数とプリスケーラ設定値できまります。
・ 例えばクロック周波数4MHzでプリスケーラ設定値が128なら
((1/システムクロック周波数) x 4) x プリスケーラ設定値
((1 / 4MHz) x 4) x 128 = 128μs → これがワンカウントの時間です。
これを256回カウントアップさせると 128x256=32768us(32.768ms)が、プリスケーラ値128での
最大割込み時間です。
・プリスケーラ設定方法
OPTION_REG = 0b00000110 ; この設定はプリスケーラ値1:128です。
緑数字文字部分は常に0です。
赤数字文字の部分を下表から選択してセットします。
(OPTION_REGbits.PS = 0b110 で記述する事を勧めます。)
000 |
001 |
010 |
011 |
100 |
101 |
110 |
111 |
1:2 |
1:4 |
1:8 |
1:16 |
1:32 |
1:64 |
1:128 |
1:256 |
TIMER0の使い方は次の順番で行います
@ OPTIONレジスターの設定を行う
プリスケーラ設定は上記載を参照して下さい。
OPTION_REG = 0b00000110 ; 赤数字も緑数字も通常は00です
赤数字部分 0 = システムクロック周波数(Fosc/4)でカウントする 1 = 5番ピン入力でカウントする
(OPTION_REGbits.TMR0CS = 0 で記述する事を勧めます。)
緑数字部分 0 = 5番ピン入力時のパルス立下がりでカウントする 1 = 立上りでカウントする
(OPTION_REGbits.TMR0SE = 1 で記述する事を勧めます。)
※ OPTION_REGの6/7ビット目は異なる機能で使用する為にOPTION_REGbitsを使用しましょう。
A TMR0カウントアップレジスターの初期化を行う
カウントアップを256までカウントさせたいならTMR0 = 0です。
100カウントだけさせたいなら256 - 100 = 156だからTMR0 = 156です。
(ただし、TMR0=156の場合は割込み処理の中で再び初期化する必要があります)
B T0IFの割込みフラグを初期化します
T0IF = 0 ;
C 割込み機能を許可します
T0IE = 1 ; // TIMER0の割込みを許可する
GIE = 1 ; // 全体の割込み処理を許可する
割込み関数の書き方
void interrupt 割込み関数名( void )
{
if (T0IF == 1) { // タイマー0の割込み発生か?
TMR0 = 156 ; // タイマー0の再ど初期化(256までカウントアップさせるならこの行は必要ない)
T0IF = 0 ; // タイマー0割込フラグをリセット(再カウントアップ開始)
}
}
TIMER0のサンプルプログラムは「タイマー割込みを使ってLEDを点滅させます」を参照して下さい。
1秒がしりたい場合は?
はっきり言って1秒ピッタリは無理ですが、出来るだけ1秒に近づける場合算出方法
ピッタリがほしい場合はTIME1を使えばいけるかも?
((1秒 / TIME0)/(プリスケーラ設定値 x(4 x 1000000 /クロック周波数)))
・クロック4MHzで1秒なら
((1000000/ TIME0)/(プリスケーラ設定値 x(4 x 1000000 /4000000)))
・TIME0=256カウントアップ プリスケーラ設定値=1:256
((1000000/256)/(256*(4*1000000/4000000)))=15.25879 割込み回数を15回数えれば約1秒
・TIME0=195カウントアップ プリスケーラ設定値=1:128
((1000000/195)/(128*(4*1000000/4000000)))=40.06410 割込み回数を40回数えれば約1秒
上の場合が15.25879で下の場合が40.06410ですが、誤差は上が.25879で下が.06410ですね。
この場合は下を採用した方がよさそうですね。
プリスケーラ値1:128でTMR0:256-195=61をセットして、割込み回数を40回数えれば約1秒です。
って事で、TIME0とプリスケーラ設定値を適度に入れてみて計算して下さい。
基本的はTIMER0と同じですが、
TIMER1は動作システムクロック周波数とは別に外部クロック周波数での動作も選べます。
また、カウンターレジスターが16ビットとなっています。
割込み発生タイミング
TIMER1はTMR1(16ビット)のレジスターをカウントアップして行きます、
65536になった時点(オーバーフロー)で割込みを発生させます。
だからで割込み発生時点でTMR1は0(オーバーフロー)になっています。
ワンカウントの時間は?
PICのクロック周波数とプリスケーラ設定値できまります。
・ 例えばクロック周波数4MHzでプリスケーラ設定値が8なら
((1/システムクロック周波数) x 4) x プリスケーラ設定値
((1 / 4MHz) x 4) x 8 = 8μs → これがワンカウントの時間です。
これを65536回カウントアップさせると 8x65536=524288us(524.288ms)が、プリスケーラ値8での
最大割込み時間。 なら、
8x62500=500000us(500ms)にして、割込み回数を2回数えれば1000msだから、
プリスケーラ値1:8でTMR1:65536-62500=3036をセットして、割込み回数を2回数えたら1秒が出来ます
・プリスケーラ設定方法
T1CON = 0b00110000 ; この設定はプリスケーラ値1:8です。
赤数字文字の部分を下表から選択してセットします。
00 |
01 |
10 |
11 |
1:1 |
1:2 |
1:4 |
1:8 |
TIMER1の使い方は次の順番で行います
@ T1CONレジスターの設定を行う
プリスケーラ設定は上記載を参照して下さい。
T1CON = 0b00000001 ;
赤数字部分 0:システムクロック(Fosc/4)でカウントする 1:外部クロックでカウントする
緑数字部分は1で、それ以外の数字部分は通常0でセットして使って下さい。
A TMR1カウントアップレジスターの初期化を行う
カウントアップを65536までカウントさせたいならTMR1 = 0です。
62500カウントだけさせたいなら65536-62500=3036だからTMR1 = 3036です。
(ただし、TMR1=3036の場合は割込み処理の中で再び初期化する必要があります)
・TMR1のセット方法
TMR1Hに上位の8ビットをセットして、TMR1Lに下位の8ビットをセットします。
で、16ビットカウンターとなります。
TMR1H = (3036 >> 8) ;
TMR1L = (3036 & 0x00ff) ;
こんな感じでセットします。
B TMR1IFの割込みフラグを初期化します
TMR1IF = 0 ;
C 割込み機能を許可します
TMR1IE = 1 ; // TIMER0の割込みを許可する
PEIE = 1 ; // 周辺装置割り込み有効
GIE = 1 ; // 全体の割込み処理を許可する
割込み関数の書き方
void interrupt 割込み関数名( void )
{
if (TMR1IF == 1) { // タイマー1の割込み発生か?
TMR1H = ???? ; // タイマー1(TMR1)の再ど初期化
TMR1L = ???? ; // (65536までカウントアップさせるならこの2行は必要ない)
TMR1IF = 0 ; // タイマー1割込フラグをリセット(再カウントアップ開始)
}
}
TIMER1のサンプルプログラムは「タイマー割込みを使ってLEDを点滅させます」を参照して下さい。
- 電源電圧は2.0〜5.5Vで駆動可能、ピンにつなげられる電流は最大25mA(通常20mA以下)まで
(2.5Vから使い物になるみたい)
- 初期値のピン割り当てがアナログ入力となっています
デジタル入力として使うときは ANSEL レジスタで指定します。
デジタルI/O時のANSELの使い方はこちらを参照して下さい。
アナログI/O時のANSELの使い方はこちらを参照して下さい。
- 4番ピンのGP3には内部プルアップ抵抗は付いていない
内部プルアップ抵抗の使い方は「スイッチの入/切でLEDを点灯させます」を参照して下さい。
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2011 Shigehiro Kimura All Rights Reserved.