PIC12F1822/16F1823 駄資料室 その1

安くて、高機能な8ビットマイコン、PIC16F18xxシリーズ
アマチュア無線家として、最も扱い易いマイコンと思っています。
ここでPICの解説をしよう等と言う訳ではありません(できません)
一無線家のPICユーザからの視点で、記します。
勿論、間違い等はあちこちにあると思って下さい、悪しからず (^^ゞ

マニュアルをちまちま読みながら調べた事・・・
プログラミングしていて、派生してできたもの・・・
実験本文等で挿入できない駄資料・・・
その他思いつくまま・・・

このページは「PIC12F1822/16F1823を使ってみた」の関連ページです。

アッセンブラ・プログラミングで気付いた事など(概要)

最初に気が付くのが、SFRマップがかなり変更になっている事です。
各レジスタの機能や使用方法は12F683や16F688のそれと同じ場合が多いですが、変更も多々ありますので、とりあえず使用する機能の関連レジスタを把握する必要があります。
次に、アドレッシング命令が拡張・変更が加えられています。
よって、活用するにはメモリイメージとそれに関わるレジスタを把握する必要があります。
割込みは、コアレジスタ(注1)の自動退避機能が加わり、楽になりました。
とは言え、ほとんどの既存ルーチンは、レジスタアクセス変更程度で使えそうです。
ただ、バンク切替を常に意識する必要が出てきました。
12F683ではプログラム中で頻繁にアクセスするSFRは、うまくBANK0に収まっていました。
よって、SFRやGPR(定義された広域変数)はバンクを意識せずプログラムできました。
しかし、12F1822では各モジュールの関連レジスタが複数のバンクに分散してます。
レジスタや定義変数をアクセスする時は、現在自分がいるバンクを(BSRレジスタを)常に意識する必要があります。(注2)
定義変数は殆どバンク0にあるので、バンクを切替てSFRにアクセスしたら、すぐにバンク0に戻す癖を付けないと、バグの原因となります。
じゃあ、変数はコモンレジスタを使用すれば良さそうですが、何せ少ないです。
割込みルーチン等で使用する変数に使用するのが良さそうです。

注1)コアレジスタ
各バンクのSFR領域の最初の12バイトのレジスタ(INDF0からINTCONまで)の事を言う。
これらのレジスタは、どのバンクからでも切替無でアクセス可能。
このアドレス以降のSFRはBSRでバンク指定してからアクセスする。
バンク切替用のマクロが標準で定義されていますので、それを使用すると見易いですし、ソースの移植がやり易いです。
当局はマクロの文字数が多いので、安直に「MOVLB」命令で直接BSRに格納していますが・・・良くない方法です。

注2)BSRレジスタ
MPLAB_SIMでデバッグする時、BSRはコアレジスタなので、SFRウィンドウの上位位置にあるのですが・・・
SFRウインドウは表示が多く、結局スクロールして使うので、一旦目を離すと目的のSFRを探すのが面倒(老化現象Hi)
当局はWatchウィンドウの一番上にW_REG、2番目にBSRを配置して、すぐに視野に入るようにしています。
この方が見易いですが、すべてをWatchウインドウに入れたのでは本末転倒です・・・

内部発振器ブロック マニュアルP56参照

2種類の独立した発振ソースと専用PLLが用意されており、それらを使い分けている様です。

HFINTOSC
 500KHZ発振ソースと専用HFPLLで16MHZを発生
 それをポストスケーラで分周して各種周波数を生成しています。
MFINTOSC
 500KHZ発振ソース出力をポストスケーラで分周し、各種周波数を生成しています。
LFINTOSC
 31KHZ発振ソースをそのまま出力

よって、12F1822/16F1823にはシステムクロック用内部発振器が3種類あるように見えます。
システムクロック出力はOSCCONレジスタで設定します。
また同じ周波数でも発振ソースが違う場合があります。

OSCCONレジスタ (BANK1 099H) マニュアル69ページ参照
 SPLLEN ソフトウエアPLLイネーブルビット
  1 = 4xPLL有効
  0 = 4xPLL無効(リセット後)
  *コンフィグレーションワードPLLEN=1の時、この設定は無視される。
 IRCF 内部発振器クロック選択ビット
  000x = 31KHZ LF
  0010 = 31.25KHZ MF
  0011 = 31.25KHZ HF
  0100 = 62.5KHZ MF
  0101 = 125KHZ MF
  0110 = 250KHZ MF
  0111 = 500KHZ MF(デフォルト)
  1000 = 125kHZ HF
  1001 = 250kHZ HF
  1010 = 500kHZ HF
  1011 = 1MHZ HF
  1100 = 2MHZ HF
  1101 = 4MHZ HF
  1110 = 8MHZ or 32MHZ HF
  1111 = 16MHZ HF
 SCS システムクロック選択ビット
  1x = 内部発振器
  01 = タイマ1発振器
  00 = FOSCで指定された発振器(リセット後)

  HF=HFINTOSC(16MHZ)からポストスケーラで分周したもの
  MF=MFINTOSC(500KHZ)からポストスケーラで分周したもの
  LF=LFINTOSC(31KHZ)

今回はただの実験で、クロックの正確さは要求しないので、内部発振を利用してみます。
せっかくですので、最高速の32MHZで動作させてみます。

32MHZ内部発振の利用方法 マニュアル 62ページ

コンフィグレーションワードの設定
 FOSCビット=100(INTOSC)とする。
 PLLEN=0(4xPLLは無効)でOK、SPLLENビットで指定の方が自由度が高い(注1)

OSCCONレジスタの設定
 SPLLENビット=1(4xPLL有効)
 SCSビット=00(コンフィグ指定に従う)
 IRCFビット=1110(8MHZ HFINTOSC)(注2)

(注1)設定はどちらかでOKだが、PLLEN=1とすると、 OSCCONのSPLLEN=0の設定は無効となる。
(注2)4XPLLイネーブルの時は8MHZのHFINTOSC以外選択の余地が無い。

SFR(SPECIAL FUNCTION REGISTER)

BANK0〜BANK31まで存在している様で、1つのバンクは128バイトです。(注1)
各バンクは先頭から00H〜1FHまでの32アドレスに特殊レジスタが割り振られています。
その内、00H〜0BHの12バイトははコアレジスタと呼び、どのバンクからでも切替無にアクセス可能です。
0CH〜1FHの20バイトは今まで通りの特殊機能レジスタとなります。
20H〜6FHの80バイトは汎用RAM領域(GPR)で、今まで通りバンク切替でアクセスできます。
PIC12F1822では、バンク0とバンク1の一部にしかGPRは存在してないようです。
70H〜7FHの16バイトは共通RAM領域で、どのバンクからでもバンク切替無でアクセス可能です。
それらの領域は間接アドレッシングにおいて、リニアにアクセスできるようです。(注2)
GPRも2000Hからリニアにアクセスできるように工夫されているようです。(注3)
当局の様なアッセンブラでポチポチと楽しんでいる者には、あまり関係無かったりしますが。
プログラム規模が大きくなる時や面倒なモジュール等を使用する時は、Cコンパイラの方が、はるかにプログラミングが楽なのは承知しています。
しかし、当局はアマチュアですので、趣味の無線工作を楽しんでいます。
8ビット小規模マイコンでのアッセンブラ・プログラミングは、ブラックボックスのLSIであるPIC内部に対して、そのハードウエアと対等ですし、ソフトウエアとは言え、「電子工作」らしくて好きです。

バンク切替(直接アドレッシング)
12F683ではSTATUSレジスタで切り替えていましたが、12F1822ではBSRレジスタを使用します。
BSRレジスタは8ビットですが、下位5ビットを使用し、0〜31バングを切り替えます。
コアレジスタはBSRの値に関係なくアクセスできます。

(注1)BANK31は特別で、コアレジスタの退避等に使用されている様です
(注2)リニアアクセス
   FSRレジスタはFSRxLとFSRxHの16ビットに拡張されました。
   これにより64Kバイトのアドレスを間接指定可能となりましたが、工夫や制約があります。
   とりあえず、制約はあるものの、各バンクはリニアにアクセスできるようです。
   また、間接アドレッシングとプログラム領域においてのアドレッシングでは、指定のメモリ部位が違います。
   プログラム領域での0000Hから始まるアドレスは、間接アドレッシングでは8000Hからに見えます。
   よって、間接アドレッシングで8000Hから始まるプログラム領域をアクセスできますが、書込みはできません。
(注3)GPRのアドレッシング
   GPRは各バンクに分けて配置されており、バンク内ではリニアにアクセス可能ですが、バンクが違えばアドレスも違います。
   しかし、各バンクのGPRは2000Hからバンクを意識する事無くリニアに見える様に工夫されています。
   これはプログラム領域において、間接アドレッシングで見えるもので、直接アドレッシングでは見えません。

コンフィグレーションワード

PIC12F683/16F688(どちらも新旧同じ)は1ワードで済んでいたのに、2ワードと拡張されました。
1ワード目は一見同じになっているようですが、良く見ると「WDTE]のビットが2つに増えています。
新設の設定ビットは2ワード目にまとめられています。
まずはここが最初の作業となりますが、旧CONFIGのままではだめなので、書き直す必要があります。
詳細はソースファイルのコンフィグレーションワード設定コメントおよび設定方法を参考にして下さい。
当局は例によって、1行にだらだら記述するのは嫌なので、ビット列で記述しています。
ここで面白いのが、システムクロック(Fosc)の設定が一見変わらないように見えますが、従来とは一味違っています。
内部発振モジュールの使い勝手が良くなりました。
よって、外部RC発振は事実上不要となりました。

 PORTへの入出力
;
PORT入出力方法は基本的には互換性が保たれている様です。
よって、機能設定について
 TRISA(C)で入出力機能指定
 ANSELA(C)で、デジタルアナログ指定
 PORTA(C)で入出力
以上で問題無いようです。
しかし、PIC12F1822(16F1823)ではLATA(C)レジスタが見えるようになりました。
PORTへの出力(書き込み方法)は下記2種類となり、どちらも結果的には、ほぼ同じです。
ただ、処理方法が違うようなので、連続書き込みの際は、LATA(C)への書き込みの方が、良いようです。
 PORTA(C)へ書き込む(従来通り)
 LATA(C)へ書き込む
普通の?書込みの際は、PORTA(C)はBANK0、LATA(C)はBANK1と言う事を考えると、結局使い易い方が良いのでは?
ここで面白いのは、TRISxで入力に設定していても、LATxには書き込み可能です。
そこで、入力設定の状態でLATxに書込み、TRISxでいきなり出力に設定を変えると、LATxの状態が即反映される事になります。
何かに使えるかな?

PORTの読込
PORTA(C)からの読込はPORTピンの状態を表現しています。
LATA(C)からの読込はその時点でのPORTピンの状態を表現してはいません。
実際はLATA(C)レジスタの保持データ内容を読み込む事になります。
よって、従来通りPORTA(C)からの読込とした方が良いようです。

PORTA(C)とLATA(C)との詳細な違いはマニュアルを読んでください。

 レジスタ(DACCONxやLATx等のBANK0以外のSFR)への別のアクセス方法

SFRへのアクセスには、新設されたBSRにBANKxアドレスを予め入力しておけば、アクセスできます。
つまり、例えばDACCON1レジスタに(DATA)の内容を書き込む場合、(通常時はBANK0にあるとする)

例1
 MOVF     DATA,W
 MOVLB    02H
 MOVWF    DACCON1
 MOVLB    00H

と言った感じです。
PIC18xxではFSRxレジスタが16ビットに拡張されました。
と言う事は、予めFSRxにSFRアドレスを設定しておけば、BANKを気にせずダイレクトにINDFxを通してアクセス可能となります。

上の例1を書き換えると、(INDF0を使うとする)

 MOVLW    019H
 MOVWF    FSR0L
 MOVLW    01H
 MOVWF    FSR0H   これでFSR0=0119H(DACCON1のアドレス)となった。
   ・
   ・
   ・
 MOVF     DATA,W
 MOVWF    INDF0

となります。
上の例1の4行のソースコードは2行のソースコードとなり、簡単になりました。
固定アドレスに繰り返しアクセスするには有効と思います。
実際今回のプログラムにも使用しています。

注意しなければならないのは、プログラムエリアにこの方法でアクセスするには注意が必要です。
プログラムエリアの0000H〜は、8000H〜となるからです。
また、すべてのメモリエリアにアクセスできる訳では無いようです。