12F1612覚書
〔PICの動かせ方入門に戻る〕
忘れないうちにメモします。
ここでの記載はMPLAB X V2.15と
MPLAB(R) XC8 C Compiler Version 1.32を使用しての内容です。
(XC8 C Compiler Version 1.32 以上のみ対応のようです)
データシートはこちら(日本語版)です。
このPICは、、小型モータや汎用アプリケーションの制御向け、安全が重視される家庭用電化製品と
白物家電をサポートします、だそうです。
AC信号とグランドの交差を検出するゼロクロス検出器(ZCD)、パルス等の計測を行う為の
24ビット信号計測タイマ(SMT)とモータ類を制御する為のCCP(PWM)/相補波形ジェネレータ(CWG)や
PID制御を行う為の算術演算アクセラレータ(PID)等が充実している様です。
12F1612/16F1613にはPID機能やUSART/SPI/I2C機能は実装されていないので、
その機能を利用したい場合は上位の16F1614/5/8/9を使う事になります。
因みに、上位の16F1614/8用のデータシートはこちら(英語版)です。
他にメモリのチェック値を計算する巡回冗長検査(CRC)モジュールが有ったりします。
又、12F1501/12F1822はタイマーがT0/T1/T2のみですが、
12F1612にはT0/T1/T2/4/6とSMTタイマー(24bit)が有りTimer使いには最高かもぉ。
※ CCP/CWG/Timer2のレジスター操作が、今までの12F1822/12F1501等と少々異なっている
模様です。
(このデバイスは2015/07現在、まだ日本では手に入りにくそうなので、詳しくは調べていません)
※ 2017/01/11現在、12F1612/16F1619が秋月電子通商でも手に入ります *1)
PICの内部に付いているクロック周波数回路は4MHz/8MHz/16MHz/32MHzを利用出来る。
外部はMAX20MHZ、内部・外部とも32MHZにする場合は、内蔵4xPLL回路を通す必要がある。
内部クロックを利用する場合
コンフィギュレーションを
#pragma config PLLEN = OFF , FOSC = INTOSC
にして
OSCCONレジスターにて使用する周波数を設定します。
OSCCON = 0b01111010 ;
緑の数字部分が内部クロックを使用する時の設定です。
赤い数字部分を変更する事により周波数を変更できます。
それ以外の数字部分はそのまま使用する。
1111 |
16MHz |
1110 |
8MHz |
1101 |
4MHz |
1100 |
2MHz |
1011 |
1MHz |
その他 |
500KHz/250KHz/125KHz
62.5KHz/31.25KHz/31KHz
|
内部クロック32MHzを利用する場合(4xPLLで動作)
コンフィギュレーションを PLLEN = ON , FOSC = INTOSC にして
OSCCON = 0b01110000 として 8MHz x 4倍 で動作させます。
(16MHzの場合は2分周してPLLに入力します、と有るので16MHzもOKでしょう)
外部クロックを利用する場合
このPICは外部用の発振回路を内蔵していません、なので水晶振動子やセラロックは接続不可ですが
水晶発振器を取り付けてECモードで動作させる事は可能です。
#pragma config キーワード1 = 設定値 , キーワード2 = 設定値 の様に記述する。
#pragma config BOREN = ON , BORV = HI , FOSC = INTOSC // 記述の例
CONFIG1
FOSC :オシレータ選択ビット
ECH =
外部発振器で高い振動子を使用する(ECモード)
INTOSC=
内部クロックを使用し、CLKINピン(RA5)はデジタルピンとする
PWRTE :パワーアップタイマの有無設定ビット
ON = 電源ONから64ms後にプログラムを開始する
OFF= パワーアップタイマは無効とする
MCLRE :MCLR/VPP ピン機能選択ビット
ON =
ピンはMCLR(外部リセットピン)として機能する
OFF= ピンはデジタル入力ピン(RA3)として機能する
LVP=ONの場合はこのビットは無視される。
CP
:プログラムメモリー保護の有無設定ビット
ON = プログラムメモリーの保護を行う
OFF= プログラムメモリーの保護はしない
BOREN :電源電圧がBORVより下がったらリセットを行うかの設定ビット
ON = 電源電圧降下常時監視機能は有効とする
OFF= 電源電圧降下常時監視機能は無効とする
NSLEEP = 動作時に有効、スリープ中に無効にする
SBODEN=
BORCONレジスタのSBORENビットで制御する
CLKOUTEN :クロック出力の有無設定ビット
ON = CLKOUTピンは有効とする
OFF=
CLKOUTピンは無効、RA4ピンとして使用する
CONFIG2
WRT
:2KWのフラッシュメモリ自己書き込み保護ビット
OFF= 保護しない
BOOT=
00h-1Fhを書込み保護にし、200h-7FFhをPMCON制御によって変更可能
HALF=
000h-3FFhを書込み保護にし、400h-7FFhをPMCON制御によって変更可能
ALL=
000h-7FFhを書込み保護にし、PMCON制御によるアドレス変更を不可にする
nZCD :ゼロクロス検出回路の有無設定ビット
OFF =
ゼロクロス検出回路は無効、、ZCDCONのZCDSENビットで変更可能
ON =
ゼロクロス検出回路は常時有効とする
PLLEN :4xPLLを動作させるかの有無設定ビット
OFF= 動作させない
ON =
動作させる(クロックを32MHzで動作させる場合に使用)
STVRENR :スタックがオーバフローやアンダーフローしたらリセットを行うかの有無設定ビット
ON = リセットを行う
ON = リセットを行なわない
BORV :電源電圧降下常時監視の電圧設定ビット
HI =
リセット電圧(VBOR)のトリップポイントを高(2.7V)に設定する
LO =
リセット電圧(VBOR)のトリップポイントを低(2.45V)に設定する
LPBOR :低消費電力ブラウンアウトリセットの有無設定ビット
ON =
電源電圧が一定の電圧(2.1V付近)より下がったらリセットを行う
OFF= 低消費電力ブラウンアウトリセットは無効とする
LVP :低電圧プログラミング機能の有無設定ビット
ON =
低電圧プログラミングを行う(RA3のI/Oピンは使用不可)
OFF= 低電圧プログラミングは行わない
CONFIG3
WDTE :ウォッチドッグタイマの有無設定ビット
ON = ウォッチドッグタイマを有効にする
OFF= ウォッチドッグタイマを無効にする
NSLEEP = 動作時に有効、スリープ中に無効にする
SWDTEN=
WDTCONレジスタのSWDTENビットで制御する
WDTCPS = WDTCPS1F// WDT Period Select (Software Control (WDTPS))
WDTCWS = WDTCWSSW// WDT Window Select (Software WDT window size control (WDTWS bits))
WDTCCS = SWC // WDT Input Clock Selector (Software control, controlled by WDTCS bits)
delay関数を使用する場合は、
#define _XTAL_FREQ 4000000の行を追加するただしこれはクロックが4MHzの場合
__delay_us(50462464) __delay_ms(50462) クロック4MHzならこの値まで設定可能
ただし、( )の中は変数使用不可です、直接数値を入力、うんん...ちょっとぉいまいち!
50秒以上待たせたいなら、
for (i=0 ; i < 5000 ; i++) __delay_ms(10) ; // 50秒待つ
という感じにします。
クロック 4MHz __delay_us(50462464) __delay_ms(50462)
クロック 8MHz __delay_us(25231232) __delay_ms(25231)
クロック16MHz __delay_us(12615616) __delay_ms(12615)
Vpp
PICチップにプログラムを書込む時の、書込み電圧を負荷するピンという意味なので、
動作時には気にしなくて良い。
MCLR
外部リセット信号を入力する場合のピンとして使用。
リセット信号はLOW(0V:GND接続)でリセットが掛かります。
リセットスイッチを付けない場合は、内部でプルアップされているので端子はオープンでも構わない。
RA3
MCLRをDisable(禁止)にしI/OのRA3の入力端子とした方が良いでしょう。
__CONFIG(MCLRE_OFF)、__CONFIG(LVP_OFF) を記述すればDisableに出来ます。
但し、プルアップが無効になるので利用する場合は別途プルアップをONさせる必要が有ります。
オープンドレイン制御
通常ポート出力ピンは電流のソースとシンクが可能な標準のプッシュプルドライバですが、
ODCONAレジスタの各ピンに該当するビットをONにすると、その対応するポート出力は電流のシンク
のみ可能なオープンドレインドライバとなります。
スルーレート制御
SLRCONAレジスタの各ピンに該当するビットをONにする事により、その対応するポートピンの
駆動スルーレートを変更できます。
立ち上がり時間の速い矩形波をオペアンプに入力し増幅すると出力波形は変化速度が追いつかず
傾いた波形になる事が有るのでこのような時にスルーレートを変更出来る様になっている様です。
デフォルトは制限が掛かっているので早い立ち上がりが欲しい場合は変更しないとダメかもね。
1 = ポートピンのスルーレートを制限する(デフォルト値)
(波形エッジの立上り/立下りが緩やかになります)
0 = ポートピンのスルーレートを最大にする
入力しきい値制御
INLVLAレジスタは入力ピンのON/OFF判断電圧値のしきい値を制御します。
1 = ポートの読み出しと状態変化割り込みに使うST(ショットトリガ)入力(デフォルト値)
0 = ポートの読み出しと状態変化割り込みに使うTTL入力
・ I/Oポートに入出力を行う際の注意点
I/Oポートへ高速クロックで連続的に入出力を繰り返した場合に上手く入出力が出来ない場合が
有ります、そんな時はPORTAレジスタで入力し、LATAレジスタで出力します。
・ 初期値のピン割り当てがアナログ入力となっています。
ANSELA レジスタの各ピンに該当するビットをクリアすればデジタル入力として使う事が
出来ます。
・ PIC内部プルアップ抵抗の使い方は?
使用する場合は、下記のレジスターにて設定する必要があります。
OPTION_REG = 0b00000000 ; 赤い所0を1とするとプルアップを使用しないです。
デフォルトは内蔵プルアップは使用しないです。
また、使用する場合は何れのピンをプルアップするのかを指定する必要が有ります。
WPUA = 0b00000110 ; // RA1/RA2は内部プルアップ抵抗を指定する
右のビットから左へ RA0〜RA5 の順番です。
CCP機能は、キャプチャ/コンペア/PWMを行うモジュールです。
キャプチャモードでは、外部イベントの発生時間を計測する事が出来ます。
コンペアモードでは、予め設定した時間が経過した時点で外部イベントをトリガする事が出来ます。
PWM モードでは、各種周波数とデューティサイクルのパルス幅変調信号を生成出来ます。
又、CCP出力はCLC・CWGの入力源となります。
キャプチャモード
コンペアモード
PWMモード
今までの12F1822/12F1501等のCCPと少しレジスターの使い方が異なっている様です。
次の順番で使用します。(CCP1とTimer4での記述例)
@ CCPの出力ピンを設定します。
CCP2はRA0ピンからの出力ですが、CCP1はRA2とRA5の何方かを選ぶ必要が有ります。
"CCP1SEL"ビットで設定 0 = 5番ピン(RA2) 1 = 2番ピン(RA5) となります。
A PWM機能を使用する事の宣言を行います。
CCP1CON = 0b11001100 ; // CCP1を有効にしPWM機能を使用する。
B Timer2/4/6の中から使用するタイマーを選択します。
CCPTMRS = 0b00000001
水色数字部分でCCP2用の設定、赤色数字部分でCCP1用の設定を行います。
00 = Timer2 01 = Timer4 10 = Timer6
C タイマー制御のクロック源の設定を行う
T4CLKCON = 0b00000000 ; // この設定はクロック源はFosc/4です。
赤色数字文字の部分を変更します、 000 = FOSC/4 001 = FOSC 110 = TxIN(外部ピン)
その他はデータシート参照。
D タイマー制御レジスターの設定を行う
T4CON = 0b01100000 ;
水色数字部分でプリスケーラの設定、この設定は16倍に設定。
赤色数字部分でポストスケーラの設定、この設定は1回(1:1)に設定。
詳しい設定は、下記の[Timer2/4/6]を参照
E PWMの周期を設定します。
PR4 = 124 ; この設定はPWM周波数1000Hz(1KHz)で設定
F カウンターなどのレジスターを初期化します
CCPR1L = 0 ; // デューティ値は0で初期化
CCPR1H = 0 ;
TMR4 = 0 ; // タイマー4カウンターを初期化
G TMR4(PWM機能)のスタート要求を行います。
TMR4ON = 1 ;
H あとはデューティ値を(CCPR1L/CCPR1H)に設定します。
(デューティ値解像度は10ビットの内8ビットのみ使用される、PR4が255の時のみ10ビット)
※PR4の値を計算する(PWM周波数=1KHz)
PR4 = ( クロック周波数 / (PWM周波数 × 4 × TMR4プリスケール値) ) - 1
・PICのクロック周波数が32MHzとします。
PR4 = ( 32,000,000 / (PWM周波数 × 4 × TMR4プリスケール値) ) - 1
・PWM周波数を1000Hz(1KHz)にしたい場合です。
PR4 = ( 32,000,000 / (1000 × 4 × TMR4プリスケール値) ) - 1
・TMR4プリスケール値を4倍・16倍・64倍で計算します。
PR4 = 1999 = ( 32,000,000 / (1000 × 4 × 4) ) - 1
PR4 = 499 = ( 32,000,000 / (1000 × 4 × 16) ) - 1
PR4 = 124 = ( 32,000,000 / (1000 × 4 × 64) ) - 1
結果PR4の最大値は255までですので、64倍での124を選択します。
TMR4プリスケール値を64倍にしてPR4を124に設定します。
※PWM周波数(1KHz)とデューティ値のPWM波形概要

但し、デューティ値10ビット(0-1023)はPR2が255の場合で、それ以外は10ビット以下になります。
(PWM制御についてのもう少し詳しい話はこちらのページを参考にして下さい。)
CCP1のサンプルプログラムはこちらからダウンロードして下さい。
ZCDモジュールは、A/C 信号がグランド電位と交差するタイミングを検出(AC波形監視)します。
電子工作の実験室さんのこちらにこの機能を使って、ご家庭のAC100Vの周波数をカウントする例題が
掲載されています参考にして下さい。
12F1822ではPWMのエンハンスモード(ハーフブリッジ:ステアリング制御)と言っていた機能と同じです。
ステアリング制御の話は16F1827ですがこちらを参考にして下さい。
左図の様にCWG1AピンがHIGH時はCWG1BピンはLOWを
出力する様に反転させます(差動出力)、これを
相補PWM出力制御と言います。
入力源は外部ピン以外に、コンパレータ・CCP・CLCの出力も利用出来るようです。
また、波形の立上がり/立下り時のデッドバンドも細かく設定可能な様です。
CWGの話は、12F1501ですがこちらに書いていますが、レジスターの使い方が少し異なる様です。
このモジュールは12F1612/16F1613には有りません、上位のデバイスのみです。
2個或いは4個の構成可能なロジックセルモジュールが有ります、
この機能によりソフトウエアではなくハード的にロジック(AND/OR等)が構成出来ます。
1つのモジュールあたり4つの入力が出来、32個の選択可能な入力源(PWM/OSC/TMR/外部PIN等)
が有ります。
ロジック機能はAND-OR/OR-XOR/4-InputAND/Dフロップ/Dラッチ/SR/JKなどです。
尚、CLC機能を設計する場合に便利かもなツールがMicrochip社のこちらからダウンロード出来ます。
(HPの下の方最後にダウンロードリンクが有ります)
また、ツールのマニュアルはこちらが日本語なので良いかもね。
現在は、MPLAB X IDEのMCC機能に統合されたので上記ツールは削除されています、
詳しくはこちらを参照下さい。 *1)
CLCの話は、16F1705ですがこちらに書いています、参考にして下さい。
Timer0 モジュールは 8 ビットのタイマ/カウンタです。
Timer0はTimer1のゲート制御にも使われます。
概要は12F675(4MHz)での記事ですが、こちらを参考にして下さい。
Timer1 モジュールは 16 ビットのタイマ/カウンタで、
タイマー動作の他に、CCPモジュールのキャプチャ/コンペア機能でも使用されます。
また、Timer0からのオーバフロー・外部ピン・コンパレータ出力からの信号によるゲート制御機能が
追加されています、これによりパルスカウントやサイクル時間の測定が可能と思われますが、
ここではこの機能には触れません。
概要は12F675(4MHz)での記事ですが、こちらを参考にして下さい。
ただ、T1CONの設定とワンカウントの時間計算が少し異なります。
T1CONの設定
T1CON = 0b00000001 ;
青数字部分でTimer1のクロックソースを選択します。
00 = Fosc/4 01 = Fosc 10 = 外部入力(T1CKI) 11 = LFINTOSC
緑数字部分でプリスケーラの設定を行います。
00 = 1:1 01 = 1:2 10 = 1:4 11 = 1:8
黄色数字部分でクロック同期制御ビット
赤数字部分 1=TIMER1を動作させる 0=TIMER1を動作させない
ワンカウントの時間計算
システムクロックが8MHzとする場合での計算
・クロックソースが 00 = Fosc/4 でプリスケーラの設定が 11 = 1:8 なら
((1/8MHz)x 4)x8 = 4us
・クロックソースが 01 = Fosc でプリスケーラの設定が 11 = 1:8 なら
(1/8MHz)x 8 = 1us
Timer2/4/6 モジュールは 8 ビットのタイマ/カウンタで、タイマー動作の他に、
CCP(PWMモード)モジュールとPULSE-WIDTH MODULATION時の動作のタイムベースとして
使用されます。
12F1612ではCCP/CWGの改良により、今までの12F1822/12F1501等のタイマー操作とレジスターが
少し異なっている様です。
又、ハードウェアリミットタイマ(HLT)拡張機能(リセット機能?)を内蔵しているらしい。
以下はTimer2で記述しています。
割込みとは?
たとえば、Aさんと電話していて、Bさんから割込みキャッチホンがはいれば、
Bさんと話して終わったらAさんと続きを話しますよね、これと同じ事です。
プログラムのmain()を処理中にTIMER0割込みがはいれば、main()を一時中断後
interrupt InterTimer()を処理して再びmain()を再開します。
(InterTimerの関数名は変更できます)
割込み発生タイミング
TIMER2 はTMR2(8ビット)のレジスターを0からカウントアップして行きます、
PR2 のレジスター値と比較して一致したら、次のカウントでTMR2 のレジスター値は
0に戻り、ポストスケーラを駆動させます。
ポストスケーラは指定した回数(1〜16)だけカウントしたら割込みを発生させます。
例えば、ポストスケーラの設定値が1:1であれば、レジスター値を比較して一致したその都度割込み
が発生し、1:10 なら、レジスター値を比較して一致した回数が10 回したら割込みを発生させます。
ワンカウントの時間は?
PICのクロック周波数とプリスケーラ設定値できまります。(但し、クロックソースがFosc/4の場合)
・ 例えばクロック周波数32MHzでプリスケーラ設定値が 1:128 なら
((1/システムクロック周波数) x 4) x プリスケーラ設定値
((1 / 32MHz) x 4) x 128 = 16μs → これがワンカウントの時間です。
これを256回カウントアップさせると 16x256=4096us(4.096ms)が、プリスケーラ値128 での
最大割込み時間ですが、ポストスケーラが1:16倍なら16x4096us=65536usで割込みが発生する。
なら1秒は1000000/65536us=15.258回割り込みを数えればよさそう。
・ 1秒ピッタリは?
クロック周波数32MHz プリスケーラ 1:128 ポストスケーラ 1:10 カウントアップは250回
にして割込みを25回数える、PR2の周期レジスター設定値は250-1=249をセットする。
・ クロックソースがFosc時は?
(1/システムクロック周波数) x プリスケーラ設定値
使い方は次の順番で行います
@ タイマー制御のクロック源の設定を行う
T2CLKCON = 0b00000000 ; この設定はクロック源Fosc/4です。
赤色数字文字の部分を変更します、 000 = FOSC/4 001 = FOSC 110 = TxIN(外部ピン)
その他はデータシート参照。
A タイマー制御レジスターの設定を行う
T2CON = 0b11111001 ;
緑色数字部分 1:TIMER2を動作させる 0:TIMER2を動作させない
水色数字部分でプリスケーラの設定を行います。
1:1 |
1:2 |
1:4 |
1:8 |
1:16 |
1:32 |
1:64 |
1:128 |
000 |
001 |
010 |
011 |
100 |
101 |
110 |
111 |
赤色数字部分でポストスケーラの設定を行います。
1:1 |
1:2 |
1:3 |
1:4 |
1:5 |
1:6 |
1:7 |
1:8 |
1:9 |
1:10 |
1:11 |
1:12 |
1:13 |
1:14 |
1:15 |
1:16 |
0000 |
0001 |
0010 |
0011 |
0100 |
0101 |
0110 |
0111 |
1000 |
1001 |
1010 |
1011 |
1100 |
1101 |
1110 |
1111 |
B 周期レジスター(PR2)の設定を行う
TMR2を何カウントアップさせるかの設定です、
PR2=249 とした場合は、TMR2は0から249までカウントアップし250カウントめで割込み発生です。
C TMR2カウントアップレジスターの初期化を行う
TMR2 = 0 ;
D TMR2IFのタイマー2割込みフラグを初期化します
TMR2IF = 0 ;
E 割込み機能を許可します
TMR2IE = 1 ; // TIMER2の割込みを許可する
PEIE = 1 ; // 周辺装置割り込み有効
GIE = 1 ; // 全体の割込み処理を許可する
割込み関数の書き方
void interrupt 割込み関数名( void )
{
if (TMR2IF == 1) { // タイマー0の割込み発生か?
TMR2IF = 0 ; // タイマー0割込フラグをリセット(再カウントアップ開始)
}
}
TIMER2のサンプルプログラムはこちらからダウンロードして下さい。
一部追記(*1) 2017/01/11
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.