↑基礎からしっかりと解説されており、
この本と著者のHPで完璧?です。




↑ PIC16F1705

メモリ 8KW
RAM 1KB
最大クロック 32MHZ(8MIPS)
8bit DAC
OP-AMP×2
その他多彩な内蔵モジュール群
はじめに

PICキットとは、PICを差し込んで使用するCPUモジュールを中心に、
各種機能モジュールを接続していきます。
そして、PICのプログラミングと各種モジュールを使用した実験を行います。
結果的に、PICプログラミングの理解と、作りたい機器の試作ができます。
そこで終了しても楽しめますし、試作を元に実機を製作しても実用的に楽しいです。
そんな実験と試作を簡単に行うモジュール群をPICキットと勝手に名付けました・・・
基本的には「おもちゃ」なのですが、簡単なモジュールを製作し、それを接続し・・・
思うように動作させるために、悩んだり、思いついたりと、結構プログラミングを楽しめます。
Windowsでは、XP以降のPCがあれば、プログラミング・ツールは無料で高機能な
ソフトウエア群がマイクロチップHP上で用意されています。
それらの用意は各自自力での用意が必須事項です。

PICをこれから弄ってみたい各局様に対して、PIC16F1シリーズからのスタートを、
お勧めしたいのと、多少はお役にたてられれば良いな・・・的な所です。
そして、このシリーズでアッセンブラ・ブログラミングを楽しんで欲しい事もあります。
アマチュア無線家は「楽しむ」事が主目的ですので、この8ビットマイコンである、
PIC16F1シリーズはアッセンブラプログラミングで楽しむのが、良い選択と思っています。
当局もボケ防止と自分のグルーミングを兼ねてPICで遊んでいます。

アッセンブラで会得した変態的?なハードウエア構成を理解すると、8bitCPUとは言え、無線工作でもそこそこ使える高速処理(8MIPS)を甘受できます。
そして、無料のIDE(統合開発ツール)のデバッグ機能で、ほとんどのバグを潰せます。
当局と同じ様な年代の各局様は当時一世風靡したZ80CPUを聞いた事があると思いますが、その当時主流の4MHZのZ80の処理速度を考えると、遥かに高速処理します。
何より面倒なI/Oボードも不必要ですしね。
また恐縮ですが、レベル的にZ80等アッセンブラを経験したOM各局を対象にしています。

なぜ今更アッセンブラと言われると困るのですが、アマチュアですから・・・
PIC内蔵モジュールの関数が用意されていないXC8では自作関数頼りです。
また、当局の未熟さもありますが、XCでのデバッグが面倒で、なぜ思うように動作しないのかすぐには解らず、嵌まり込みます。
アッセンブラで基本的に動作している内蔵モジュールサブルーチンは、シビアなタイミングを要求されない限り、XCでも基本的に自作関数として移植しても動作します。

PICマイコンの良い所は、ネット上で当局より遥かに技術のあるOM諸氏の各種資料が
豊富に存在するので、独学に不自由しない事です。
マイクロチップ社がネット上で開発ツールや参考プログラムを公開しているのも大きいです。
技術に乏しい当局では出来る事は限られていますが、田舎のアマチュア無線家目線で実験しながらの解説で、表現および記録ができれば良いなと思っています。
部品や資料入手に関しても、そのような目線で行っています。
ここで使用するのはPIC16F1705です

PIC16F1シリーズで秋月電子で安価(\100)で入手できる、(2017年5月現在)
コスパの良いと思われる14ピン8ビットマイコンです。
これをアッセンブラ・プログラミングで楽しみます。
C言語でプログラミングではXC8を使用します。
XC8の使用では、参考文献①を熟読される事をお勧めします。

さて、このPICを選んだ理由は、高機能なのに安価てある事。
アナログ機能が強化され、8bitDACやオペアンプが内蔵されています。
また、その他の機能もてんこ盛りです。
プログラムメモリやデータメモリが多く搭載され、アッセンブラでは容量不足等無縁です。
ピン数は最低限この程度ないと無線工作には不向き、等の理由があります。

当初は日本語マニュアルのある16F1823をモチーフにして記述していたのですが、
価格が同じ割に、メモリも少なく、その他・・・ 
等の理由で、16F1705の魅力にひれ伏してしまいました・・・
初めて弄るPICとしては敷居が高そうですが、乗り越えれば結果オーライです。
ここではPICキット基板を作製し、超簡単な実験を紹介ていきたいと思います。

内容進行はPIC16F1823日本語マニュアルを補足する形で独自解釈していきます。
さらに参考としてPIC16F1705/1709の英文マニュアルも使用します
この純正日本語マニュアルがこのコーナーの基本教科書となります。(PDFファイルです)
しかし、PICの全機能の解説と応用は当局レベルではできません。
基本的な利用のみとなる事をご了承ください。 m(__)m

その後は、超簡単な実験用CPU基板、接続する各種モジュールの製作、
接続コード類の変更とプログラムの更新で各種基本機能を実現・実験します。
遥か昔の「エレキット」のPIC版?な感じを目指します・・・ シッテイマスカ?

おすすめ参考書は「PIC16F1ファミリ活用ガイドブック」です。
この本はアッセンブラの解説がありませんが、各内蔵モジュールの解説
ツールである、MPLAB X IDE」の導入等があります。
PICへの書込みはPICKIT3と言う赤いケースの機器を使用します。

参考文献
①「PIC16F1ファミリ活用ガイドブック」 後閑 哲也 著  技術評論社
②「電子工作のためのPIC16F活用ハンドブック」 後閑 哲也 著 技術評論社
③PIC16F1822/1823日本語データシート MICROCHIP
  コード番号 [DS41413C_JP] 必ず入手してください
③PIC16F1705/1709英文データシート MICROCHIP
  コード番号 [DS40001729A]
④MPLAB X IDE 日本語マニュアル MICROCHIP
⑤PicKit3ライター マニュアル MICROCHIP
8ビット・マイクロコンピュータ PIC16F1シリーズの内部ソフトウエア的空間イメージ


アッセンブラ・プログラミングは、そのコンピュータシステムに密着しており、ハードウエアを理解しないとうまくいかない事が多いです。
逆に言うなら、ハードウエアに密着している分、高級言語の様な「文法」が無いので、1行のコードがシンプルで理解し易いです。
さらに、PICのCPUの命令コードの種類が少ないので、紙1枚に書いて壁にでも貼っておけばOK!と、抵抗カラーコード並です。
後述となりますが、デバッガで1行の命令コードを実行しながら、結果としてのレジスタ等の変化を目で追えますので、 (注1)
命令コードによる動作をビジュアルに理解可能です。
しかし実際はハードウエアを完全に理解していなくとも、ある程度イメージ理解すれば、概ね大丈夫と個人的には考えています。
と言うより、普通の?アマチュアにとってその辺が理解の限界点、あるいは落とし所だと思っています。

ここでは実際のハードウエアは、アッセンブラ・ブログラミングに必要なソフトウエア側から見える「ハードウエア・イメージ」として、
当局なりに今まで経験した事に基づき、まとめて行きたいと思います。
よって、プロの技術者(或いはプロ級アマチュア)様から見れば、おかしな記述が多々あると思います。
突っ込み所満載なのは十分承知しているますが、その辺はご容赦をお願いします・・・ m(__)m
日本語マニュアルには必要な事は概ね記載されていますが、読み手が必要な基礎知識がある事を前提に解説されています。
また記載量も半端ないですので、これを一気に理解しようとすると大変です。(多分)
必要な時に必要な所を読むのが吉と思いますが、最低限必要と思われる所を中心に補足して行く形にします。
日本語マニュアルを使用するのは、図や画像の作成を省略出来る点も大きいです。

注1)
実機やライタ(Pickit3等)が無くても、エミュレータでデバッグ動作できるので、その際の表示される挙動は面白いです。
アッセンブラのマクロを使うと解りづらくなるので、当初は使わない方が良いかも

1.CPUを中心にメモリやレジスタ等が存在する (マニュアル P12 図1-1参照)

  PICはIC内部にハードウエアとしてのCPUやメモリ等コンピュータシステムがICパッケージ内に完結しているのが特徴です。
  そして、アッセンブラ・プログラミングに必要なPIC内部のイメージを自分なりに持つと、プログラム作業をやり易くなります。
  まず、PICの内部にある、CPU部分の基本動作からイメージ理解をします。

 ①CPUがプログラムカウンタが指定する「プログラムメモリアドレス」から命令コードを読込、解釈します。(補足01)
 ②CPUが「レジスタアドレス」で指定されるRAMレジスタや機能レジスタのデータをアキュムレータ(演算等をする特殊なレジスタ)取り込みます。
 ③このアキュムレータ(Wレジスタです)とRAMレジスタを利用して、そのデータを演算や加工をします。
 ④加工したデータを、適切な「アドレス」のRAMレジスタや機能レジスタに転送します。

  この4ステップが基本的なCPUの動作手順で、一見とてもシンプルです。
  プログラマがそれらのCPU動作を直接指示する「命令コード」に、直接対応した命令記載様式が「アッセンブラ ソースコード」です。
  完成したアッセンブラ・ソースファイルはPIC専用「アッセンブラ」で「機械語」である「命令コード」に変換します。
  「レジスタ」とは、自由にデータを保管したり、アキュムレータ(Wレジスタ)と演算したりできる、RAMレジスタ領域、
  そして特殊な機能を持つレジスタ領域で、各種内蔵モジュール・レジスタや、I/O(入出力)レジスタ等があります。
  RAMレジスタも機能レジスタも同じレジスタメモリアドレス空間で指定される領域に存在します。(補足02)
  その他にアドレスがない(アドレスを意識しない)レジスタも存在します。(プログラムカウンタ、スタックポインタ等)
  レジスタのイメージは追って解説します。

補足01)
CPU命令コードが格納されている「プログラムメモリアドレス」と演算やI/Oを行う「レジスタアドレス」は別の空間にあります。
よって、同じアドレス値でも格納場所が違います。

補足02)
レジスタメモリ領域は、6809CPUの様なメモリマップドI/Oを構成しています。
しかし、この領域に命令コードは存在しません、「データメモリ」領域と「プログラムメモリ」領域は完全に分かれています。
PICは、そのアーキテクチャとして、バスを「プログラム バス」と「データバス」とに物理的に分かれています。
そして、データバスに接続されているメモリ領域は8ビット構成、プログラムバスに接続されている1メモリアドレスは14ビット構成です。
それぞれの領域に「アドレス」が別に存在している事になり、同じアドレスでも対応領域は違います。
そして、データメモリにはデータしか置けませんが、プログラムメモリにはプログラムとデータの両方置けます(間接アクセス)
ただし、プログラム領域の「データ」は直接演算対象にならず、単純な「データ」で8bitアクセスとなります。(上位6bitは使えない)
この辺はZ80等とは大きく違う所で、Z80はプログラムもデータも同じアドレス領域にあり、すべて8ビット構成です。
よって、Z80は命令コードが複数バイトの事も多々あります。
2.CPUおよびプログラマから見える、「アドレス空間」とは何ぞや

  CPUはメモリから命令コードを引出して、その命令を実行しますが、(補足03)
  その命令動作の基本が上記1-①、②、③、④となります。
  CPUが特定のメモリと、やり取りするには、多数のメモリの中から1つだけを選択しなければなりません。
  その多数のメモリの1つ1つは整然と区分けされた領域に存在していなければならず、「アドレス」で識別します。
  その、「アドレス」で整然と区分けされた連続領域を1つの「アドレス空間」とイメージします。
  さて、PICはそのアドレス空間は、1つとは限らず複数存在する事になります。
  つまり複数のアドレス空間を分別しなければならず、アドレス空間Aとアドレス空間Bの2つがあったとすれば、
  Aの50番地とBの50番地と言う感じで、同じアドレス番号が存在する事となります。
  それらによって、複数のアドレス空間にある、1つのメモリを特定できることになります。
  その「A」とか「B」を「バンク」と言いい、プログラム上ではバンク切替えを頻繁に行いながらメモリアクセスする事となります。
  
  PICのアドレス空間は大別すると、同じ物理的領域を2種類のアドレス空間で識別されます。
  1つは、CPUが直接アクセスできる直接アドレス空間と、特殊なレジスタを介してアクセスする、間接アドレス空間があります。
  直接アドレス空間は旧PICと上位互換性のあるアドレス空間群で、ちょっと変態的です。
  所が、これが本来のPICの姿で、かつてZ80等で遊んだOM諸氏にとってPICの直接アドレス空間群を理解するのは面倒です。
  F1シリーズ最大の特徴でもある、旧PICから拡張された「仮想アドレス空間」すなわち間接アドレス空間はイメージし易いです。
  これは一見直線的に綺麗に配置されていて、Z80等の古いCPUと同じ感じで判り易いですが・・・
  まずは変態な方(直接アドレッシング)の必要最低限をイメージ理解してから、綺麗な?方の必要部分を解説していきます・・・ (^_^;)


補足03)
CPUは最初の起動時やリセット時に読み出すメモリアドレスが決まっています。(PICはプログラム領域の0000H番地)
このメモリから読み出す情報は「命令コード」でなくてはなりません。
これらの動作は「プログラムカウンタ(PC)」と呼ばれる特殊なレジスタが指定するアドレスからのメモリ情報をCPUは読み取ります。
その情報はCPUにとって、「命令コード」と解釈され、その命令を即座に実行しようとします。
CPUにとって「プログラムカウンタ」で指定されるメモリの情報は、単なる「データ」なのか「命令コード」なのかを判別できません。
プログラムカウンタは、何も無ければ1アドレスずつ加算されて行き、CPUは順次命令コードを解釈・実行していきます。
ただし、ジャンプ系命令があると、その新アドレスがPCにセットされ、ジャンプ先の命令コードを実行し始めます。

3.直接アドレス空間について

  これはCPUが実行時に見えるアドレス空間で、基本的にはプログラムROMエリアとレジスタRAMエリアに大別されます。
  因みにZ80等はメモリ空間とI/O空間が分離しており、メモリ空間にデータもプログラムも混在しています。
  そしてI/O空間に特殊レジスタ等が、大概はマッピングされます。
  前項で、PICはメモリマップドI/Oだと言いましたが、これではI/OマップドI/Oじゃないかと言われれば、そうも見えます・・・
  これはPICのアーキテクチャの問題で、プログラムメモリとデータメモリとはアドレス空間が分離しているためです。
  PICはZ80の様なI/O空間は無いが、データ空間が目的によって分離しているので、それがI/O空間と間違えてしまいます。
  一応データメモリ空間にI/Oがマッピングされているので、メモリマップドI/Oと言う事になると思われます。

  何だかんだと言っても、この直接アドレッシングを理解しないとアッセンブラ・プログラミングができません・・・
  それにはPIC CPUの「命令コード」の構造を理解するのが先決です。
  そして、直接アドレッシングの動作は、後述の「間接アドレッシング」のすっきりとしたアドレスエリアの、どこの部分を、
  こちゃこちゃと、うごめいているのかがイメージできれば、全体イメージもまとまってくると思います・・・ 多分・・・

 (1)アドレッシング用命令コードについて(マニュアル P328 図29-1)
   まず、テキストの図25-1をざっと眺めてみてください。
   命令コードが1バイト~数バイトで構成されていたZ80アッセンブラで遊んだOM諸氏は、ここで大きな違和感があると思います。
   PIC(8ビットPIC16Fシリーズ)の機械語である「命令コード」は、すべて14ビットの1ワードで構成されています。

  1)プログラムメモリエリアで使用する命令(BRA、GOTO、CALL等)(マニュアル P330 表29-3)
   GOTO   PUTL   命令コード構成(ビット列)  [10 1kkk kkkk kkkk]
   CALL   PUTL   命令コード構成(ビット列)  [10 0kkk kkkk kkkk]

   上記の場合、[101]の3ビット部分が「GOTO」の、[100]の3ビット部分が「CALL]のオペコードです。
   オペランドであるサブルーチンアドレス、ジャンプアドレスビット[ kkk kkkk kkkk ]は11ビットで指定されます。
   つまり、プログラムエリアの0000H~07FFHまでの2Kワードをアドレッシングします。
   すなわち、1つの命令コードでは、0000H~7FFHまでの範疇しかプログラムエリアを直接にはジャンプ出来ません
   よって、プログラムエリアのアドレス[0800H]を超えたアドレスに存在するルーチンに移動時は、
   オペランドアドレスに上位4ビット分のアドレスを追加しなければなりません。
   ここで、プログラムカウンタ(PC)とスタックポインタは15ビットで構成されており、ちゃんと32Kバイト分を指定できます。
   つまり、ジャンプ開始時はPC(プログラムカウンタ)に上位アドレス4ビット分を追加してやる必要がありますが、
   ジャンプ前の場所に戻る時は、何もしなくて大丈夫、と言う事になります。
   勿論、プログラム全体が07FFHまでの2Kワードに収まっている分には、何もしなくても大丈夫です。

  2)レジスタメモリエリアをアクセスする命令 (マニュアル P25 図3-2)
   さて、このアドレスエリアは特殊です・・・プログラムエリアとアドレス絶対値がかぶっているし・・・
   アドレスは0000H~0FFFHの12bitすなわち4Kバイトもの広さがあります・・・ 
   しかし、1命令コードでは7bitすなわち128バイトのメモリ空間しかアクセスできず、5bit分足りません
   そして、「プログラムアドレス空間」とは別のアドレス空間です。
   PICは命令コードの取得にはプログラムカウンタの指定するプログラムメモリエリアをアクセスし、その命令コードを実行します。
   命令の実行の際の、データ移動や演算処理等では、このレジスタメモリエリアを自動的にアクセスします。
   よって、プログラム実行中のアクセス対象は、このレジスタRAMエリアであり、
   大別すると下記に分類され、実際は②と③のレジスタアドレスを意識してプログラミングします。(補足04)
   言い換えると、①と④は通常のプログラミングにおいて、アドレスを意識する必要は無いです。
   ①コアレジスタ
   ②特殊機能レジスタ(SFR)
   ③RAMレジスタ(データレジスタ)
   ④超特殊レジスタ?

   MOVF   PORTA,W   命令コード構成(ビット列)  [00 1000 dfff ffff] = [00 1000 0000 1100]
   MOVWF   TMR0   命令コード構成(ビット列)  [00 0000 1fff ffff] = [00 0000 0000 1111]

   上記1行目の場合、「MOVF」のオペコードは[00 1000]の6ビットで、転送先はWレジスタなので、[d} = [0]
   転送元「PORTA」のアドレスは00CH、よって レジスタアドレスビットは[fff ffff] = [000 1100]の7ビットで指定
   上記2行目の場合、「MOVWF」のオペコードは[00 0000 1]の7ビットで
   転送先は「TMR0」のアドレスは015H、よってアドレスビットは[000 1111]の7ビットで指定

   MOVLW   0FH    命令コード構成(ビット列)  [11 0000 kkkk kkkk] = [11 0000 0000 1111]
   MOVLB    03H    命令コード構成(ビット列)  [00 0000 001k kkkk] = [00 0000 0010 0011]
   MOVWF   ANSELA   命令コード構成(ビット列)  [00 0000 1kkk kkkk] = [00 0000 1000 1100]

   上記1行目の場合、Wレジスタへの数値書込みで「MOVLW」のオペコードは[11 0000]の6ビット、
   オペランドの数値は、リテラルデータビット[kkkk kkkk]の8ビット指定で、0FHなので[0000 1111]
   2行目は「BSR」レジスタへの数値書込みで、オペコードは[00 0000 001]の9ビット
   オペランドの書込み数値は03Hですが、8ビットの内の下位ビット[0 0011]の5ビットで指定
   3行目はWレジスタの内容を「ANSELA」レジスタへ転送しますので、オペコードは[00 0000 1]の7ビット
   「ANSELA」レジスタのアドレスは018CHで、オペコード域には下位7ビットが指定され、[000 1100]
   このアドレスはBSRレジスタ内の下位5ビットが「MOVF」命令コードのオペランドビットの上位に追加され
   計12ビット指定となり、レジスタアドレス018CH=[0001 1000 1100]が無事指定されます。
   この方法で、全4Kバイト分のレジスタアドレス(0000H~0FFFH)がアクセスされます。

   「MOVF」命令等のレジスタアクセスが絡む命令は、間接アドレッシング(リニア・アドレス空間)で言う所の、
   「0000H」~「0FFFH」をアクセスしている事になります。(アドレス絶対値は同じでそのままです)
   そして、プログラムの動作中、プログラムカウンタやスタックポインタは、間接アドレッシングで言う所の、
   「8000H~FFFFH」を「0000H」~「7FFFH」と見なして動作しているように見えます。
   ただし、FSRレジスタのアドレス指定は間接アドレッシングそのもので、INDFレジスタから取得する、「MOVF」命令は
   間接アドレッシングで指定された領域からのデータ取得となります。


 (2)直接アドレス空間イメージ(CPU実行時に直接CPUが見えるアドレス空間)
  1)プログラムROMエリア(0000H~7FFFH)
   0000H ~ 07FFH  プログラムROM領域、2Kワード(1ワード=14ビット) ここが基本プログラムアドレス空間となる。
                  ジャンプ系命令コード内のオペランドで指定できる11ビットがこのアドレス空間
                  すべてのPICに実装されているプログラム領域、これ以後の領域は実装されているとは限らない。
   0800H ~ 0FFFH  プログラムROM領域、2Kワード・2ページ目(実装されているとは限らない)
   1000H ~ 7FFFH  拡張プログラムROM空間、30Kワード(実装されているとは限らない)
                   全部で、2KW×16(ページ)=32KWのアドレス空間となり、15ビットのアドレス指定、
                   PCLATHによるアドレスビットの追加、すなわちページ切替が必要
   8000H ~ 8008H  デバイスコンフィギュレーション領域、ライタで書込み時に設定され、通常時は使用しない
                   その内、コンフィギュレーションワードの設定はソースコードの最初に記述する
  2)レジスタRAMエリア(0000H~0FFFH)
    000H ~ 07FH   レジスタアドレス領域で、7ビット128バイトの領域、プログラムROM空間とは別のアドレス空間に存在する
                  レジスタアクセス系命令コード内のオペランドで指定できる7ビットがこのアドレス空間
    080H ~ FFFH   拡張レジスタアドレス領域、最初の領域を含めて全部で32バンク存在する
                  アクセスにはBSRレジスタの下位4ビットを併用し、全12ビット4Kバイトのアドレス空間となる

 (3)直接アドレス空間詳細
  1)プログラムROMエリア 0000H~07FFH (BANK0)
   ここに収まっている限り何も意識せずジャンプ系命令のプログラミングできます。

  2)プログラROMエリア 0800H~ (BANK1~) (マニュアル P42 3-3 PCLとPCLATH)
   この領域までプログラムが大きくなってきた場合、いくつかの注意点があります。
   その内PCLは下位8ビット、PCHは上位7ビット(最上位ビットは無効)となっています。
   CALL命令の14ビットの内、オペランドの11ビットの下位8ビットはPCLに、上位3ビットはPCHの下位3ビットにロードされます。
   PCHの残り4ビットはPCLATHレジスタの下位4ビットからロードされます。
   つまり2Kワードを超えるアドレッシングではPCLATHレジスタにあらかじめ不足の上位アドレス4ビットを設定しておく事になります。
   この場合、PCLATHの6-3ビット目の4ビットが適応されます。(下位4ビットでは無いので注意)
   ただし、スタックポインタは15ビットで構成されており、ちゃんと戻って来れます。
   2Kワードの範疇に収まっていれば、普通にCALLやGOTO命令を使用して問題ありません。(補足04)
   また、趣味のアッセンブラプログラミングでは、2Kワードは結構広い領域で、困る事はあんまり無いです。

  3)レジスタRAMエリア (マニュアル P26~ 表3-3~)
   a)コアレジスタ (マニュアル、P31 表3-8)
    レジスタと呼ばれる、読み書きできる8ビットの領域で、どのBANKからでも切替無でアクセスできます。
    PICが動作するにあたり、基本的かつ重要な機能を制御・反映します。
    これらは12個のレジスタはその動作をすべてを理解する必要があります。
   b)SFR(特殊機能レジスタ)
    機能レジスタと呼ばれる、読み書きできる8ビットの領域で、レジスタによってはBANK切り替えが必要です。(補足05)
    特殊な機能をもつ、PICの内蔵モジュール等を制御・反映します。
    I/Oポートとしての機能もあります。
    これらはすべてを理解する必要はありませんし、全てを使用する訳でもありません。
   c)GPR(汎用データRAMとして使用するレジスタ)
    これはデータRAM領域で高速に自由に読み書きでき、Wレジスタと直接演算できますが、BANK切り替えが必要なアドレスもあります。
    1BANKあたり80バイトまでですが、別アドレスでは連続展開しています。(後述)
   d)共通データRAM
    データ用RAMなのですが、コアレジスタ同様に、どのBANKからでも切替無でアクセスでき、16バイトあります。

  4)EEPROM領域、その他
    これは基本的に8ビットのデータROM領域で自由に読み書きできますが、制限があります。
    アドレス指定もこれ専用のレジスタを使用した間接アクセスのみで、上記とは別アドレス空間です。
    あまり使用しないので、その他を含めて詳細は割愛します。

補足04)
レジスタアクセス命令とジャンプ・コール命令では命令コード内のアドレス指定に使用するビット数が違います
レジスタアクセスの場合は7ビット(128バイト)、ジャンプ関連命令では11ビット(2Kワード)となります。

補足05)
いつでも直接16ビットアドレス空間を指定可能なZ80等のマイコンに慣れた各局様は不思議に思うかもしれませんが、
PICは命令コードそのものに、アクセスするアドレスも含まれています。
それは7ビット(128バイト)の指定までで、上位ビット不足分をBSRレジスタが補う形となります。
レジスタメモリは128バイト間隔でブロック的に32分散しており、CPUはストレートに全アドレス指定できません。
BSRレジスタに上位ビット(各ブロック)を指定してからアクセスします。(要はBSRによるバンク切替)
ただし、FSRとINDFレジスタによる間接アクセスは16ビットアドレス指定なので、64Kバイトを直接アドレス指定可能です

4.間接アドレス空間 マニュアル P46 図3-8参照

   ここでは16ビットのアドレス空間に存在する領域を示す番地をイメージします。
   各領域は0000H番地からFFFFH番地のアドレス番号で区別され、全アドレス指定に16ビットが必要です。
   よって、最大65536個の領域(メモリ等)を分別します。
   このアドレス空間は領域が直線的に配置されており、判り易いので、直感的に操作できます。
   しかし実際は全ての番地にメモリ等の領域が存在する訳では無く、存在する領域と存在しない領域があります。
   これらのアドレス空間は専用レジスタを仲介してアクセスします。(後述)
   よって、これによりアクセスされた情報は、CPUはデータとして処理し、命令コードとしては解釈しません。

 (1)1つの番地(1つの領域、すなわちメモリ等)
   1つのアドレスで指定される、1つの領域で、8ビット(1バイト)の領域と14ビット(1ワード)の領域が存在します。
   しかし、14bitの領域へのアクセスでは、下位8bitしか使え(見え)ません。
   そして、操作性向上のため、1つの物理的領域が複数のアドレスで指定される事があります。(後述)
   基本的には、この(1)と(2)がプログラマあるいはCPUから見える大局的なイメージです。

 (2)1つの番地の領域を分別すると、8ビットの領域と14ビットの領域がある
  1)8ビットの領域 0000H~7FFFH
   a)実アドレスレジスタメモリ領域 0000H~0FFFH
    直接アドレス空間と同じで、実際に存在する領域です。
   b)リニアGPR領域 2000H~29AFH
    実アドレスではバンクに分散しているGPRを、扱いやすい様にリニアマッピングした仮想アドレス領域です。
    大きな配列データ領域を確保するのに便利そうです。
    
  2)14ビットの領域 8000H~FFFFH
   a)プログラムROM領域
    1アドレスあたり14ビットの領域で、基本的には書込みはPICKIT3ライター等で行い、動作中では読み込みのみです。
    動作中に書き込みできる方法もありますが、ここでは扱いません。
    プログラム本体実行中アドレス、0000H~7FFFHと同じ領域ですがFSRレジスタに指定するアドレスが違います。(重要)
    これらの領域はプログラムの本体(命令コード)が格納されてますが、データを格納する事もできます。
    ただしデータ領域として使用する場合、事実上、下位8ビットしか使えませんし、見えません。
    よって、実質8ビットのデータ領域とは変わりませんが、アッセンブラ疑似命令でデータを記述する際は注意が必要です。(補足06)


 (3)間接アドレスマップ まとめ

   間接アドレス空間 大局的領域イメージ(CPUはINDFxレジスタを経由して間接的に見える)

   0000H ~ 0FFFH   旧PIC上位互換レジスタおよびデータRAM領域
   1000H ~ 1FFFH   予約(現在使用されていない領域)
   2000H ~ 29AFH   リニアライズ マッピングされた、汎用データRAM(GPR)領域
   29B0H ~ 7FFFH   予約
   8000H ~ FFFFH   プログラム用フラッシュROM領域

  1)レジスタ領域
   0000H ~ 0FFFH   旧PIC上位互換レジスタ・データRAM領域
   ここはBANKと呼ばれる、128バイトの1つのアドレスブロックが32個集合して構成されている。
   連続したアドレスなのに何故BANKと言うのかは、PICの命令コードの基本構成に起因する(補足07)

   16ビットアドレス       機能 
   0000H ~ 0012H   コアレジスタ 

   0000H   INDF0    間接アクセス窓口0
   0001H   INDF1    間接アクセス窓口1
   0002H   PCL     プログラムカウンタ下位8ビット
   0003H   STATUS  ステータスレジスタ
   0004H   FSR0L   間接アクセス0用アドレス下位8ビット
   0005H   FSR0H   間接アクセス0用アドレス上位8ビット
   0006H   FSR1L
   0007H   FSR1H
   0008H   BSR     機能レジスタ群アクセス用上位4ビット
   0009H   WREG    アキュムレータ的レジスタ、論理演算等行います
   000AH   PCLATH  プログラムカウンタ上位7ビット「PCH」の間接指定レジスタ
   000BH   INTCON  割り込み制御用レジスタ

   000CH ~ 001FH  機能レジスタ群(BANK0)

   0020H ~ 006FH  GPR領域(汎用RAM)
   0070H ~ 007FH  共通RAM領域(どのバンクでも同じ領域内容、アドレス違えど共通RAM)

   0080H ~ 00FFH  上記、コアレジスタ・機能レジスタ・GPR・共通RAM、と同様の構成(BANK1)
         ~ 0F7FH  さらに繰り返し(BANK2-BANK30)
   0F80H ~ 0FFFH  BANK31 機能レジスタ群が、特殊なシャドウレジスタとなる。


補足06) 間接アクセスでプログラム領域を使う際の注意点
プログラム領域に8bitデータを格納するには、アッセンブラ疑似命令を使用します
その際のイメージとしては、14bitの領域(1ワード)に8bitのデータを格納する、と言う事です。
ただ8bitのデータを連続格納しようとすると、1ワードが14bitのため、2バイト目の上位2bitが欠けます。
さらにかけた上位bitは間接アクセス不可能と、何とも情けない結果が来ています・・・

補足07)Z80とPICの命令コードの構成比較
当局と同じ様な年代の各局様は、8ビットZ80CPUは、馴染み深いと思います。
独身貴族の若き頃、パソコンの創成期、MZ80やX1、PC8001、PC8801等に採用されていたCPUです。
その時代、無線交信を忘れて?、Z80のアッセンブラで遊んだ事と思いますが・・・  (^。^)y-.。o○ 

Z80アッセンブリ・ソース例

OBJ      ニーモニック   オペランド
3A3250   LD         A,(HEX0)  ・・・①
CD3412   CALL       PUTL     ・・・②

上記の様にZ80では、8ビット単位で命令が構成され、1つの命令が数バイトで構成される事も可能です。
①ではオペランドのラベルで示されるアドレスから、アキュムレータレジスタに8ビットデータが格納されます。
②のサブルーチンコールではニーモニックが1バイト、オペランドで示されるサブルーチンアドレスが2バイト、計3バイトで構成されます。
このように、Z80では命令コードのサイズが、その命令によって、8ビット単位で変化します。

さて、PICでは1つの命令コード(機械語)内に、ニーモニック部分(オペコード)とオペランドが収納されており、
それは合計14ビットの1ワードで、全てが構成されています。
これは64Kバイト(16ビット)のアドレス空間の隅々までCPUは見渡せない事を意味します。
そこで、不足するアドレッシングビットを補完するレジスタ群が存在します。
ここはアッセンブラ・プログラミングにとって、重要なポイントとなりますので、常に意識する必要があります。

 PICソース例
①に対応したロード命令例
レジスタ領域(GPR)に定義されたラベル、「HEX0」(アドレス0020H)からデータをWレジスタに読み込む場合、

 MOVF  HEX0,W   命令コード構成(ビット列)  00 1000 dfff ffff

上記の場合、格納先がWレジスタなので、d=0、HEX0のアドレス[ fff ffff ]は20Hなので、dfff ffff = 0010 0000
さて、ここで問題なのはラベル番地へのアクセスに7ビットしかないと言う事です。
つまり、000H~007FHまでしかアドレッシングできない事になります。
これを解消するために、コアレジスタの1つであるBSRレジスタ(8ビット)を使用します。
BSRの下位5ビットと命令コード内の7ビット、計12ビットで0000H~0FFFHまでの4Kバイトをアドレッシングします。
これはすなわち、BSRレジスタによるバンク切替と言い換える事ができます。

例えば、008CH番地のTRISAにアクセスする場合、

 MOVLB  02h      ・・・ BSRレジスタに02Hを書き込む(BANK02に切り替える)
 MOVF   TRISA,W  ・・・ TRISAレジスタの内容をWレジスタに読み込む
 CLRF   BSR      ・・・ BSRレジスタを0Hにする(BANK0に戻す)


② サブルーチンコールの場合

 CALL   PUTL    命令コード構成(ビット列)  10 0kkk kkkk kkkk

上記の場合、オペランドであるサブルーチンアドレス[ kkk kkkk kkkk ]は11ビットで指定されます。
つまり、0000H~07FFHまでの2Kワードをアドレッシングします。
プログラムエリアは間接アドレッシングでは8000H~FFFFHですが、実行時のCPUには0000H~7FFHと見えます。
すなわち、CPUはプログラムエリア0000H~7FFHまでしか直接にジャンプ関連はできない事になります。
プログラムカウンタ(PC)は15ビットで構成され、その内PCLは下位8ビット、PCHは上位7ビット(最上位ビットは無効)となっています。
CALL命令の14ビットの内、オペランドの11ビットの下位8ビットはPCLに、上位3ビットはPCHの下位3ビットにロードされます。
PCHの残り4ビットはPCLATHレジスタのbit3~bit6の4ビットからロードされます。
つまり2Kワードを超えるアドレッシングではPCLATHレジスタにあらかじめ不足の上位アドレス4ビットを設定しておく事になります。
この場合、PCLATHの6ビット目~3ビット目の4ビットが適応されます。(下位4ビットでは無いので注意)
ただし、スタックポインタは15ビットで構成されており、ちゃんと戻って来れます。
2Kワードの範疇に収まっていれば、普通にCALLやGOTO命令を使用して問題ありません。
また、アマチュア無線家のアッセンブラプログラミングでは、2Kワードは結構広い領域で、困る事はほとんどありません。
戻る  実験・製作の記録TOPへ戻る