PICをフリーのC言語で (MPLAB IDE)

MPLAB IDE は、マイクロチップ社のPIC開発環境です。プログラムを開発する過程で必要となる文字列の検索、置換、無効用語の警告、文法エラーの検出などを厳格にチェックしてくれるだけでなく、アセンブラ、リンカ、コンパイラなどの処理を自動的に呼び出してくれます。このため、SDCCのようなバッチ処理に比べると 開発作業がずいぶん楽になります。なお、MPLABは既にメンテナンスが終了しているため、現在はフリーで使うことができます。同じくフリーのHI-TECH C と組み合わせて使うことで、C言語による開発が可能になります。アセンブラ、あるいはSDCCによるプログラム開発の実用化は厳しいものがありましたが、これによって高いレベルでの開発が無償でできることになったとも言えます。

なお、MPLAB は現在 MPLAB X シリーズとして、8ビット系のXC8、16ビット系のXC16,32ビット系のXC32の各コンパイラが出されています。限定版はフリーですが上位版は有償となっています。Xシリーズに切り替えられた主な理由はマイクロチップ社側の事情のようで、アトメル社等を吸収して開発環境を統合してゆく戦略上の理由があったのではないかと思われます。従って、今までのユーザーから見れば、Xにすれば各段に便利になるとかいう訳ではありません。ともかく、従来の高機能コンパイラが無償で使えるようになったのはありがたいことです。


MPLAB IDE のインストール

MPLAB IDEのPC環境は 32bit MS Windows system (2000 SP4/XP SP2/Vista/7/8)とされています。Win10の場合はVMware workstationなどの仮想XPにインストールした方がよいでしょう。

マイクロチップのライブラリMicrochip Archives
または
http://www.ne.jp/asahi/air/variable/picmel/install/mplab/index.html
の中から、 HiTech PICC Pro Lite 9.83 が同梱されているMPLAB IDE 8.76 (for Windows32) ダウンロードして解凍します。この版のコンパイラは、ほとんどのミッドレンジ系のPICデバイスをサポートし、強力な最適化機能があり、メモリ容量にも制限がありません。



setup.exe を実行します。

MPLABのインストールが開始されるので、必要に応じ Next と I accept,, を進めます。

続いて自動的にHI-TECH C社のPIC C Lite のインストールが始まります。
Next と I accept,,で進みますが、途中、"Add to environment path"のチェックが促されますのでチェックを入れてFinishまで進みます。

PIC C Liteで使用できる変数は
データ型   ビット数  値の範囲
bit          2       0〜1
char        8       -128〜127
unsigned char  8       0〜255
short       16      -32768〜32767
unsigned short 16      0〜65535
int         16      -32768〜3276
unsigned int   16      0〜65535
long        32    -2147483648〜2147483647
unsigned long  32    0〜4294967295
float        24  -3.4×1038〜3.4×1038
double       24  -3.4×1038〜3.4×1038


MPLAB IDE の基本的な操作

@ MPLAB IDE をスタートすると次のような画面が現れます。





新しいプロジェクトを起こすには Project →Project Wizard で
次に Step1でDevice を▼で選択します(例えばPIC16F887)
Step2で、 HI-TECH Universal ToolSuiteを指定するとHI-Tech C Compilerが表示されます。
次のStep3のBrowsを押してプロジェクトを格納するフォルダを指定し、プロジェクト名を入力します。
Step4を次に進め、完了します。

A準備ができたので、次にソースファイルの元を作ります。
MPLABとは別に、添付したテストプログラム1.cを使うか、または、メモ帳などのエディターで、元になる簡単なcソースファイルを作り。作成したプロジェクトのフォルダに ファイル名.c で保存しておきます。

ソースファイルの元となるファイルは、次のような中身の無い空っぽなファイルでも構いません。

"file_name.c"

void main(void)
{

}

Bcファイルを組み込む
MPLABのmcw窓の Source Files を右クリックして Add Files で、用意しておいたcファイルを指定します。これでワークスペースにcファイルが組み込まれまれます。

Cコンパイル実行
Project → Build を指定するとコンパイルが開始され結果がOutputに表示されます。
エラーが無ければ "Buid successful!" と表示されます。
エラーが発生した場合は、エラーの行をクリックして対応するソースを表示させ修正します。
エラーとならないワーニングは発生しても通常OKです。
これで hex ファイルができている筈です。

プログラミングのコツは、一気に書いてしまわないことです。
少しずつ、少しずつ、コンパイルでエラーが発生しないことを確認しながら進め、装置の動作に関わる関数も一つ一つ確認します。


PICへの書き込み

programmer→Select programmer  で書き込み器を選択します。
PICプログラマーv4の場合は None を選択しますが、MPLAB IDEを使う以上、書き込みはPICKIT3を使う方が圧倒的に早くなります。

PICKIT3とPIC16F887の接続は以下のようにします。

        PICKIT3                 PIC

VPP/MCLR  1  ---    1  VPP/MCLR
VDD     2  ---   11  VDD (+5V)
VSS (GND)  3   ---  12  VSS (GND)
ICSPDAT   4  ---   40   PB7/ICSPDAT
ICSPCLK   5  ---   39   PB6/ICSPCLK

 --      6





写真は正規品ではないAmazonのPICKIT3互換品ですが、今のところMPLAB IDEとの接続に問題は無いようです。ただし、おまけに付いてくるゼロプレッシャー40Pソケット基板は説明書通りに使うとID認識でエラーになってしまう。DIP40,28,18,8なども接続できる如く書かれているが無理なのでは? 結局、ターゲット基板に6Pコネクタを設けてPICKIT3を接続してOK 


PIC16F887LCD表示とUSARTシリアル通信

●回路
下図の回路は別項「PICをC言語で(SDCC)」の回路と同じです。 LCDは16桁2行表示のキャラクタ・ディスプレイならほとんどの機種が使えますが、機種によってバックライトのピンが付いたもや、1pinが5Vで2pinがGNDになっているものもあるので要注意です。





プログラム
 USARTテストプログラム
テストプログラムには簡単なEEPROMの書き込みと読み出し、LCDの表示、カウントアップする2バイト数などが含まれています。PORTA bit0,1 にタイマー割り込みによる信号も出力しています。
EEPROMの読み書きはテストプログラムのmainの中で実行しているような関数を使ってもいいのですが、HI-TECH Cの組み込み関数
EEPROM_write(unsigned int, unsigned char);
unsigned char EEPROM_read(unsigned int);
を呼び出して使うこともできます。

C言語によるPIC16Fのシリアル通信のしかたは意外に厄介です。関連するSFR(特殊機能レジスタ)を詳しく説明してある資料は多いのですが、詳しすぎて逆に理解しにくいようです。

ここでは、一般的に使う 【シリアル調歩同期、8ビット長、パリティ無し、8Mクロックで9600bps】の設定をする方法を取り上げてみます。
このテストプログラムは、pin25(TX)-PIN26(RX)を直接ループバックさせて自己テストすることができます。
望むボーレートが出ているかは、0x55を連続送信してオシロでビット長を測定します。
9600bpsなら 1/9600≒0.104ms
設定などの簡単な説明はプログラムの中に記入してあります。ループ以外の回路はテスト1と同じです。

@コンフィグでシステムクロックの速度を定めます。
内蔵の8MHzクロックを使う場合は
__CONFIG(FOSC_INTRC_CLKOUT & WDTE_OFF & PWRTE_ON & CP_OFF);
上例の回路のように、OSC1とOSC2に水晶を接続して高速クロックを使う場合は
__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & CP_OFF);


AUSARTのモードを設定してから
OSCCON = 0x70;    // 内蔵clockを8MHzに措定
SPBRG = 51;        // 9600bpsの時定数 (clk=8M 、クロック=clk/16 で)
TXSTA = 0b00100100; // 送信モード設定,、clk分周比16、 非同期
RCSTA = 0b10010000; // 受信モード 8bit長,受信許可
 20MHz水晶を使い9600bpsにする場合は
SPBRG = 32;        // 9600bpsの時定数 (clk=20M 、クロック=clk/64 で)
TXSTA = 0b00100000; // 送信モード設定,、clk分周比64、 非同期
RCSTA = 0b10010000; // 受信モード 8bit長,受信許可


B割り込みを許可して

CTRMT(送信バッファ空)または、RCIF(受信バッファ空)を確認してから送受信します。


pin25=TX、pin26=RX にMAX232などのRS232C ドライバを介してPCとの通信もできますが、PICやAVRなど、コントローラーとコントローラー間の近距離通信の場合は、直接信号線のクロス接続でも可能です。

RC内部発振の周波数はあまり正確ではありませんから、正確なボーレートが必要な場合は、水晶発振を使うか、共通の外部発振クロックと、プルアップしたオープンコレクタを並列に接続すれば、複数のコントローラーの通信ネットワークができます。

マスターコントローラーを決め、アドレスを割り当てればネットワーク間のデータを自在に転送できます。こうした使い方が本来のマルチ・コントローラーの使い方といえます(ステッピングモーター連動制御)参照
通信システムを構築する上で注意することは、2バイト以上のデータ長を転送する場合は、そのデータが確定したものか否か知らせるフラグが必要です。転送データ数が多い場合は個々にフラグを設けるのではなく、総合割り込みフラグと同様にまとめて管理する方法もあります。



Hi-Tech Cのコンフィグ

プログラムメモリとは別なconfigメモリはPICの動作を設定するヒューズとも言えるものです。
16F887のconfig1のビットの定義は下のようになっています。




Hi-Tech C の config 定義は Program Files\Hi-TECH Software\PICC\9.82\include
の中にPIC型番毎のヘッダーファイルに記載されています。
16F887は

PIC_config

これを

  __CONFIG(FOSC_HS & WDTE_OFF & ,,,,,);

のように、マクロで 論理積 & を取ることでconfigを記述することができます。
なお、このヘッダーファイルには

// Register: PORTA
volatile unsigned char PORTA @ 0x005;
// bit and bitfield definitions
volatile bit RA0 @ ((unsigned)&PORTA*8)+0;
volatile bit RA1 @ ((unsigned)&PORTA*8)+1;
volatile bit RA2 @ ((unsigned)&PORTA*8)+2;
volatile bit RA3 @ ((unsigned)&PORTA*8)+3;
volatile bit RA4 @ ((unsigned)&PORTA*8)+4;
volatile bit RA5 @ ((unsigned)&PORTA*8)+5;
volatile bit RA6 @ ((unsigned)&PORTA*8)+6;
volatile bit RA7 @ ((unsigned)&PORTA*8)+7;
、、、、、、

のようにHi-Tech cで使えるポートおよびピット定義もされています。


PIC16Fのクロック
は、次の@/A何れかを選択して使います。

@OSC1/OSC2端子に外部発振(水晶HS、RC等)を接続してconfigで指定

APIC内部の8MHz発振信号INTOSCをOSCCONレジスタで分周率を指定

その仕組みは次の図を見ると解かってきます。








Hi-Tech C のインラインアセンブラ

Cの中に記述するアセンブラ命令は #asm と #endasm で挟み、1命令が1行
例えば、

#asm
nop
movwf  0x00
#endasm

#define ABC \
{              \
#asm          \
movwf  0x00 \
nop           \
#endasm      \
}
注)行末の\(英キーのバックスラッシュ)は、行を連結して処理



EEPROM データの作成

マクロ __EEPROM_DATA を使いデータは8バイト区切り

__EEPROM_DATA(0x01,0x04,0x08,0x00,0xfc,0xfd,0xfe,0xff);

2進表現は何故かBを後部に付ける(?)

__EEPROM_DATA(
00000000B,
11110000B,
10101010B,
10000000B,
00101100B,
00000000B,
11111111B,
00000000B
);


PIC16F88LED点滅

PIC16F88は16F887と同じシリーズのコントローラーですが、 18ピンの小型で低価格なコントローラーです。ポートが少ないので欲張った使い方はできませんが、特定の用途には十分でしょう。
同じく、MPLABとHi-Tech c で開発することができます。下はLED点滅の例





PIC16F88 プログラム_

内部クロックを使う場合、configは FOSC_INTOSCIO を使います。



PIC16F88AD変換

超高速という訳にはいきませんが、PICでもAD変換が可能です。
アナログ値で得られる測定値など各種データを、表示、記録、伝送することが可能となります。






注)上の回路のLCD接続は、本サイトの他のLCD回路の1番ピンと2番ピンの接続が逆になっています。秋月で入手できる台湾製LCDの多くは上のピン配列になっているようです。

下は、Hi-Tech C 用のプログラムです。

 PIC_AD.c

このプログラムは、AN_IN の入力電圧(0〜5V)を10ビット値に変換して、その値を10進値(0〜1023)でLCDに表示します。動作テストは、10k程度のボリュームを、Vcc--AN_IN--GND に接続して確認することができます。変換時間は1ms程度のようです。

PIC16F88のAD変換に関連するレジスタは下記のようになっています。





ADCS の各ビットでAD変換のためのクロック速度を設定
ADFM のビットで値のビットを左右何れに詰めるか
VCFG で測定のための基準電圧をセレクトしています。
変換は adconv() 関数で実行しています。

AD変換は手続きが複雑なので解かり難いのですが、動作実例をもとにアレンジしていく方が解かりやすいと思います。
PICによるADサンプリング速度はせいぜい1k sps程度ですから、これを超えるにはAD変換専用のデバイスを使う必要があるでしょう。



PIC16F88PWM

PWM(パルス幅変調)はパルスのON/OFF比を変えることで、モーターなどに流れる電流値を変化させる技術です。スイッチング電源の出力電圧の安定化にも使われています。

下図の回路とプログラムは、AN0に入力したアナログ電圧をADRESレジスタにAD変換して読み込み、このデータをPMW機能でパルス幅変調してLEDの明るさを変化させています。

LEDに替え、DCモーターの制御回路にすれば回転速度を連続的に変化させることができます。






PIC_PWM.c

 PWM動作
@ タイマーカウンタ TMR2 はシステムクロックの1/4周期で+1される。
A TMR2と、レジスタPR2 の値が一致するとTMR2は0にクリヤされ
  CCP1
の出力ピンはHになる。この動作の周期はレジスタPR2にセットする値で決まる。
  なお、TMR2がクリヤされる時、レジスタADRES(HとL計10ビット)の値が
  CCPR1にコピーされる。
B CCPR1TMR2の値は常に比較され、一致するとCCP1ピンがLになる。

出力パルスの周期はレジスタPR2にセットする値で決まり、パルスのデュティー比はレジスタADRESにセットする値で決まります。

出力のCCP1ピンへの割り当ては下のようにコンフィグで設定でき、

// CCP1 function on RB0
#define CCPMX_RB0 0xFFFF
// CCP1 function on RB3
#define CCPMX_RB3

デフォルトでRB0ですがRB3にもできます。


PMW制御の利用例としては下のようなサーボがあります。

【秋月電子カタログより】






上のサーボの場合は、B型ボリュームの中央でPMWパルス周期が20msとなるPR2の値を決め、VRを端から端まで回転させた時にパルス幅が0.5ms〜2.4msに変化するADRESの値を探します。
GND、RB0、5V の3本をサーボに接続することで動作させることができます。


PICの割込み

PIC16F88の割り込みに制御に関係するレジスタフラグ類はかなり複雑で、マイクロチップのマニュアルでその関係を確認すると下図のようになっています。(なお、同じPIC16F系でもコントローラーによってフラグレジスタの名称等が異なっているので要注意です)




全ての割り込みの許可不許可を制御するのが GIE であり、
ピン変化、INTピン、タイマ0以外の周辺割り込みを制御するのが PEIE となってます。

割り込み条件は上の論理図を見ると分かってきます。関係がORになっている割り込みは何れかの論理条件を1にすることで割り込みが発生します。AND条件の場合は双方の条件が1になることで 割り込みが発生します。

基本的には末尾の文字の
 Eは
  1: ENABLE (1で割り込みを可にするレジスタフラグ)
  0: NOT ENABLE (0で割り込みを不可にするレジスタフラグ)
 F は
  1: FLAG (割り込み発生で1になるレジスタフラグ)
  0: NOT_FLAG (割り込みを確認したら0にするレジスタフラグ)

という機能を表しています。

割込みの種類によって異なった割込みベクターが用意されているAVRと異なり、PICの割り込みは

static void interrupt int_tm(void)
{

}

のように、interrupt 専用の関数を宣言しますが関数名は自由です。
どんな割込みも同じアドレス(4番地)が呼び出されますから、複数の割り込みをENABLEにした場合、どの要因で割り込みが発生したかを知るためには、割込みが発生してからFLAGで判断する必用があります。
PICの割り込みはなるべくシンプルな使い方にとどめた方が良いでしょう。

メインと割り込み間でやりとりする変数は、スタック領域ではなく固定アドレスのRAM領域に確保されなければならないため、 関数の外で volatile を宣言します。

割り込みとメインの双方で同じ変数を使う場合に注意しなければならないことは、メインでその変数を操作している瞬間に割り込みが入っても問題が発生しないようにしなければなりません。例えば、変数が複数バイトで処理の途中にオーバーフローを挟むようなことが発生すると予期しない誤動作を招くことになるからです。メイン側で処理の前後に割り込みを禁止するか、メインで操作途中を示すフラグを立てて、この間は、割り込み側で変数操作を禁止する等の処置をする必要があります。
こうした点にミスがあると、コンパイルエラーに上がってこないばかりか、再現性の無いトラブルを引き起こすため、ノイズによる暴走と見分けがつかないなど厄介なことになります。


 PIC16F88でタイマー割り込み

タイマー割り込みにも複数の方法がありますが、システムクロックで動作するタイマー0のオーバーフロー割り込みは、一定の時間間隔で繰り返し実行したい処理や、所定時間後に開始したい処理、あるいはマルチタスクのようにメインルーチンの背景で実行する処理に使います。タイマー割り込みの方法自体は単純ですが、その使い方は奥深いものがあります。

ここで使う回路は、上の「PIC16F88でPMW」の回路と同じ回路を使います。

タイマー割り込みプログラム

タイマー0オーバーフロー割り込みは、8ビットタイマー0がオーバーフローすることで発生し、"interrupt" ルーチンが実行されます。この例では、メインでBポートをONして icnt カウンタに数値をセットすることでカウンタがダウンカウントを開始し、タイムアウトでBポートがOFFされます。











Top page
inserted by FC2 system