12F1501覚書

〔PICの動かせ方入門に戻る〕


忘れないうちにメモします。
ここでの記載はMPLAB X V2.15
MPLAB(R) XC8 C Compiler Version 1.32を使用しての内容です。 *2)
データシートはこちらです。 *4)
12F1822との違いは、PWM出力機能が4個有る事と、CLCNCOCWG機能の追加です。
また、12F1501には通信機能(UASRT/I2C/SPI)が有りません、通信機能が欲しい時は上位の
PIC16F1503(14P:USART無)/1508(20P)/1509(20P)を利用する。
それに、12F1822にくらべてプログラムメモリ・データメモリが半分しかないです。

内蔵発振回路
PICの内部に付いているクロック周波数回路は4MHz/8MHz/16MHzを利用できる。
また、外部クロック(EC Mode)ならMAX20MHzまで利用できる。

内部クロックを利用する場合
コンフィギュレーションを
#pragma config FOSC = INTOSC
にして
OSCCONレジスターにて使用する周波数を設定します。
OSCCON = 0b01111000 ;赤い数字部分を変更する事により周波数を変更できます。
赤い数字部分以外はそのまま使用する。
1111 16MHz
1110 8MHz
1101 4MHz
1100 2MHz
1011 1MHz
その他 500KHz/250KHz/125KHz 62.5KHz/31.25KHz/31KHz

外部クロック20MHzを利用する場合(但しEC Modeのみ)
このPICは外部用の発振回路を内蔵していません、なので水晶振動子やセラロックは接続不可ですが
水晶発振器を取り付けてECモードで動作させる事は可能です。
コンフィギュレーションを
#pragma config FOSC = ECH
にして
OSCCON = 0b0xxxx011 として動作させます。

コンフィギュレーション *2)
#pragma config キーワード1 = 設定値 , キーワード2 = 設定値   の様に記述する。
#pragma config BOREN = ON , BORV = HI , FOSC = INTOSC  // 記述の例

 FOSC         :オシレータ選択ビット
                    ECH =外部発振器で高い振動子を使用する(ECモード)
                    INTOSC=内部クロックを使用し、CLKINピン(RA5)はデジタルピンとする
 WDTE         :ウォッチドッグタイマの有無設定ビット
                    ON = ウォッチドッグタイマを有効にする
                    OFF= ウォッチドッグタイマを無効にする
                    NSLEEP = 動作時に有効、スリープ中に無効にする
                    SWDTEN=WDTCONレジスタのSWDTENビットで制御する
 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
 LPBOR       :低消費電力ブラウンアウトリセットの有無設定ビット
                    ON =電源電圧が一定の電圧(2.1V付近)より下がったらリセットを行う
                    OFF= 低消費電力ブラウンアウトリセットは無効とする
 WRT         :1KWのフラッシュメモリ自己書き込み保護ビット
                    OFF= 保護しない
                    BOOT=000h-1FFhを書込み保護にし、200h-1FFFhをEECON制御によって変更可能
                    HALF=000h-FFFhを書込み保護にし、1000h-1FFFhをEECON制御によって変更可能
                    ALL=000h-1FFFhを書込み保護にし、EECON制御によるアドレス変更を不可にする
 STVRENR    :スタックがオーバフローやアンダーフローしたらリセットを行うかの有無設定ビット
                    ON = リセットを行う
                    ON = リセットを行なわない
 BORV         :電源電圧降下常時監視の電圧設定ビット
                    HI =リセット電圧(VBOR)のトリップポイントを高(2.55V)に設定する
                    LO =リセット電圧(VBOR)のトリップポイントを低(1.9V)に設定する
 LVP          :低電圧プログラミング機能の有無設定ビット
                    ON =低電圧プログラミングを行う(RA3のI/Oピンは使用不可)
                    OFF= 低電圧プログラミングは行わない

delay
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)
4番ピンの使い方(MCLR) *1)
Vpp
 PICチップにプログラムを書込む時の、書込み電圧を負荷するピンという意味なので、
 動作時には気にしなくて良い。

MCLR
 外部リセット信号を入力する場合のピンとして使用。
 リセット信号はLOW(0V:GND接続)でリセットが掛かります。
 リセットスイッチを付けない場合は、内部でプルアップされているので端子はオープンでも構わない。

RA3
 MCLRをDisable(禁止)にしI/OのRA3の入力端子とした方が良いでしょう。
 #pragma config MCLRE = OFF,LVP = OFF
 を記述すればDisableに出来ます。
 但し、プルアップが無効になるので利用する場合は別途プルアップをONさせる必要が有ります。

PWM機能
12F1822ではPWMは1つでしたが、12F1501では4つのPWM出力(PWM1/2/3/4)を行う事が出来ます。
なので、レジスターが4つに増えただけで操作は12F1822での場合と同じです。
尚、PWMの周波数はタイマー2(TIMER2)で発生させますので発生源は1つです。
また、PWM出力はCLCCWGの入力源にもなります。
12F1822の機能でステアリング制御(相補PWM出力)はCWG(相補波形ジェネレータ)で行うようです。

次の順番で使用します。(PWM1での記述とします)
他のPWM機能を利用する場合はレジスター名のPWM1を2/3/4と変えればOKです。

@ PWM1機能を使用する事の宣言を行います。
   PWM1CON = 0b11000000 ;
   赤い数字部分でPWMモジュールを使用するか決めます、 1:使用する 0:使用しない
   緑の数字部分でPWMをピンに出力するのかを決めます、 1:出力する 0:出力しない
A デューティ値レジスターを初期化します。
   PWM1DCH = 0 ;    // デューティ値は0で初期化
   PWM1DCL = 0 ;
B TMR2プリスケーラ値(TIMER2)の設定を行います。
   T2CON = 0b00000010 ;  // この設定は16倍に設定
   赤い数字部分にて設定します、1倍=00 4倍=01 16倍=10 64倍=11
C PWMの周期を設定しカウンターを初期化します。
   PR2 = 124 ;     // この設定はPWM周波数1000Hz(1KHz)で設定
   TMR2 = 0 ;     // タイマー2カウンターを初期化
D TMR2(PWM機能)のスタートを行います。
   TMR2ON = 1 ;
E あとはデューティ値を(PWM1DCH/PWM1DCL)に設定します。
   (PR2が255設定でないので、デューティ値解像度は10ビットの内8ビットのみ使用される)

PR2の値を計算する(PWM周波数=1KHz)

 PR2 = ( クロック周波数 / (PWM周波数 × 4 × TMR2プリスケール値) ) - 1

 ・PICのクロック周波数が8MHzとします。
  PR2 = ( 8,000,000 / (PWM周波数 × 4 × TMR2プリスケール値) ) - 1
 ・PWM周波数を1000Hz(1KHz)にしたい場合です。
  PR2 = ( 8,000,000 / (1000 × 4 × TMR2プリスケール値) ) - 1
 ・TMR2プリスケール値を1倍・4倍・16倍・64倍で計算します。
  PR2 = 1999 = ( 8,000,000 / (1000 × 4 × 1) ) - 1
  PR2 = 499 = ( 8,000,000 / (1000 × 4 × 4) ) - 1
  PR2 = 124 = ( 8,000,000 / (1000 × 4 × 16) ) - 1
  PR2 = 30.25 = ( 8,000,000 / (1000 × 4 × 64) ) - 1

 結果PR2の最大値は255までですので、16倍での124を選択します。
 TMR2プリスケール値を16倍にしてPR2を124に設定します。

デューティ値の設定方法
memo1  デューティ値は10ビット(0-1023)で指定
 します。

 PWM1DCH/PWM1DCLレジスターは8ビット
 なので、PWM1DCHを上位8ビットとして、
 下位2ビットをPWM1DCLレジスターの
 7-6ビット目を使用しセットします。

この様にセットするのが面倒い場合は、PWM1DCLレジスターは0でセットして置き、
設定したいデューティ値を4で割り、その値をPWM1DCHレジスターにセットすれば良いかもね。

PWM周波数(1KHz)とデューティ値のPWM波形概要

memo2
但し、デューティ値10ビット(0-1023)はPR2が255の場合で、それ以外は10ビット以下になります。
(PWM制御についてのもう少し詳しい話はこちらのページを参考にして下さい。)

PWMのサンプルプログラムは「可変抵抗のツマミを回してLEDの明るさを可変します」を参照して下さい。

CWG(相補波形ジェネレータ)機能
12F1822ではPWMのエンハンスモード(ハーフブリッジ:ステアリング制御)と言っていた機能と同じです。
ステアリング制御の話はこちらを参考にして下さい。

memo3  左図の様にCWG1AピンがHIGH時はCWG1BピンはLOWを
 出力する様に反転させます(差動出力)、これを
 相補PWM出力制御と言います。


12F1501では入力源がPWMだけでなく、コンパレータ・NCO・CLCの出力も利用出来るようです。
また、波形の立上がり/立下り時のデッドバンドも細かく設定可能な様です。

CWGのサンプルプログラムは「CWG機能を動作させて見ます」を参照して下さい。

NCO(数値制御オシレータ)機能
周波数の直線的な制御を高解像度(20bit)で実現する事が出来るので、
周波数発生器(トーンジェネレータ)として利用。
周波数のカウンターとして利用したりパルス周波数変調(PFM)なども出来る様です。

アプリケーションの例として
蛍光灯等の照明の制御・照明のバラスト・モータ駆動・モデム・D級オーディオアンプ・超音波測距など

NCOのサンプルプログラムは「NCO機能を動作させて見ます」を参照して下さい。

CLC(ロジックセルモジュール:)機能
12F1501には2個の構成可能なロジックセルモジュールが有ります、
この機能によりソフトウエアではなくハード的にロジック(AND/OR等)が構成出来ます。
1つのモジュールあたり4つの入力が出来、16個の選択可能な入力源(PWM/OSC/TMR/外部PIN等)
が有ります。
ロジック機能はAND-OR/OR-XOR/4-InputAND/Dフロップ/Dラッチ/SR/JKなどです。

尚、CLC機能を設計する場合に便利かもなツールがMicrochip社のこちらからダウンロード出来ます。
(HPの下の方最後にダウンロードリンクが有ります)
また、ツールのマニュアルはこちらが日本語なので良いかもね。

現在は、MPLAB X IDEのMCC機能に統合されたので上記ツールは削除されています、
詳しくはこちらを参照下さい。 *3)

CLCのサンプルプログラムは「CLC機能を動作させて見ます」を参照して下さい。

TIMER0とTIMER1
Timer0 モジュールは 8 ビットのタイマ/カウンタです。
TIMER0 のサンプルプログラムはこちらからダウンロードして下さい。

Timer1 モジュールは 16 ビットのタイマ/カウンタです。
TIMER1 のサンプルプログラムはこちらからダウンロードして下さい。

Timer0/1 はタイマー動作の他に、 CLC機能の入力にもなります。

こちら「タイマー割込みを使ってLEDを点滅させます」は12F1822(4MHz)での記事ですが
同じ機能なので参考になるでしょう。

TIMER2
Timer2 モジュールは 8 ビットのタイマ/カウンタで、タイマー動作の他に、PWMモード時の動作のタイム ベースとして使用されます。
タイマー動作機能は設定した時間毎に割込み処理を行うものです。

割込みとは?
 たとえば、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のクロック周波数とプリスケーラ設定値できまります。
 ・ 例えばクロック周波数8MHz(Fosc/4)でプリスケーラ設定値が 1:16 なら
  ((1/システムクロック周波数) x 4) x プリスケーラ設定値
  ((1 / 8MHz) x 4) x 16 = 8μs → これがワンカウントの時間です。
  これを256回カウントアップさせると 8x256=2048us(2.048ms)が、1回の最大割込み時間ですが、
  ポストスケーラが1:16倍なら16x2048us=32768usで割込みが発生する。
  なら1秒は1000000/32768us=30.517回割り込みを数えればよさそう。
 ・ 1秒ピッタリは?
  クロック周波数8MHz プリスケーラ 1:16 ポストスケーラ 1:10 カウントアップは250回
  にして割込みを50回数える、PR2の周期レジスター設定値は250-1=249をセットする。
 ・プリスケーラ設定方法
  T2CON = 0b00000010 ; この設定はプリスケーラ値16です。
  赤数字文字の部分を変更します、 1 = 00 4 = 01 16 = 10 64 = 11 となります。

使い方は次の順番で行います

@ タイマー制御レジスターの設定を行う
  プリスケーラ設定は上記載を参照して下さい。
  T2CON = 0b00000110 ;
  緑数字部分 1:TIMER2を動作させる 0:TIMER2を動作させない
  赤数字部分でポストスケーラの設定を行います。
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

A 周期レジスター(PR2)の設定を行う
  TMR2を何カウントアップさせるかの設定です、
  PR2=249 とした場合は、TMR2は0から249までカウントアップし250カウントめで割込み発生です。

B TMR2カウントアップレジスターの初期化を行う
  TMR2 = 0 ;

C TMR2IFのタイマー2割込みフラグを初期化します
  TMR2IF = 0 ;

D 割込み機能を許可します
  TMR2IE = 1 ;      // TIMER2の割込みを許可する
  PEIE = 1 ;      // 周辺装置割り込み有効
  GIE = 1 ;      // 全体の割込み処理を許可する

 割込み関数の書き方
void interrupt 割込み関数名( void )
{
     if (TMR2IF == 1) {  // タイマー0の割込み発生か?
          TMR2IF = 0 ;   // タイマー0割込フラグをリセット(再カウントアップ開始)
          /* ここで割り込み回数を数える */
     }
}
TIMER2のサンプルプログラムはこちらからダウンロードして下さい。

その他



リンク切れ見直し(*4) 2020/03/22
記事一部追記(*3) 2016/12/01
MPLAB X用に記事変更(*2) 2015/10/01
記事変更(*1) 2015/06/30


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2020 Shigehiro Kimura All Rights Reserved.