ソースブースト C コンパイラの使い方・覚え書き

最終更新  2016.10.03


◆◆ 日本語の表示 ◆◆

「設定」→「エディタ」でフォントを「MS ゴシック」などにする。
デフォルトは Courier New になっており、日本語が化ける。


◆◆ 新規にプロジェクトを作成する ◆◆

プロジェクト用のフォルダをあらかじめ作成しておく。

「プロジェクト」→「新規プロジェクト」と操作すると
「ファイルを開く」というウィンドウが開く。

前回にオープンしていたプロジェクト名が表示されたりして、
新規作成するという雰囲気ではないが、ファイル名の
部分に

   プロジェクト名.__c


と入れて「開く」を押すと、プロジェクトファイルが
新規に作成される。

次に、「デフォルトのソースファイルを作成する」
を選ぶと、プロジェクト用のフォルダの中に

   プロジェクト名.c

という名前のソースファイルが自動生成される。


◆◆ 最初にやるべきこと ◆◆

「設定」→「対象デバイス」で PIC の型番を選ぶ


◆◆ インクルードファイル ◆◆

#include <system.h>
#include <PIC16F886.h>

のように、system.h と型番固有のインクルードファイルの 2 つを
インクルードする。

「設定」→「対象デバイス」で PIC の型番を選ぶことは、
上記の 2 行目を書いたのと同じ効果がある。

従って、型番固有のインクルード宣言は不要だが、
以下の理由により、宣言した方がよい。

1. ソースファイルがどの型番の PIC に対するコードか明示できる。

2. 「設定」→「対象デバイス」で PIC の型番を選ぶのを忘れた結果、
   異なった PIC が選ばれてしまっている状態を考える。
   コンパイルの結果、「duplicate defined」あるいは
  「Illegal redefinition of symbol」あるいは
  「variable '   ' already exists」のエラーが出る。
   すなわち、PIC の型番の指定忘れを検出することが出来る。

インクルードファイルは C:\Program Files\SourceBoost\include にある。


◆◆ 既存のプロジェクトを利用して新しいプロジェクトを作成する ◆◆

既存のプロジェクトのフォルダの中を全てコピーして
新しいプロジェクトを作成してはならない。

プロジェクトファイルの中にディレクトリの情報などが書き込まれている
ため、コンパイルするとコピー元の hex ファイルが更新されたりする。

新規にプロジェクトを作成し、.c ファイルをコピーしてくること。


◆◆ Pragma 命令 ◆◆

コンフィギュレーションレジスタの設定法

#Pragma DATA addr, _HS_OSC & _WDT_OFF & .......

アドレスはインクルードファイルの中で定義されている。
コンフィギュレーションレジスタが 1 バイトの PIC の場合は _CONFIG
2 バイトの場合は _CONFIG1, _CONFIG2 と定義されている。

コンフィギュレーションレジスタの詳細は PIC のデータシートの
Special features of the CPU の節に書いてある。

(例 1)  PIC16F88

#pragma DATA _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF
                     & _WRT_PROTECT_OFF
                     & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_OFF
                     & _PWRTE_ON & _WDT_OFF
                     & _INTRC_IO

(例 2)  PIC16F819

#pragma DATA _CONFIG, _CP_OFF & _DEBUG_OFF
                     & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_OFF
                     & _PWRTE_ON & _WDT_OFF
                     & _INTRC_IO

(例 3)  PIC16F886

#pragma DATA _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF
                     & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON
                     & _PWRTE_ON & _WDT_OFF & _HS_OSC

クロックの設定

#Pragma CLOCK_FREQ 20000000    // 20MHz

delay_ms(), delay_us() 関数などに影響するらしい。


◆◆ 変数の型 ◆◆

 1 bit        bool, bit
 8 bit        char, unsigned char, signed char
16 bit        short, unsigned short, signed short
            int, unsigned int, signed int
32 bit        long, unsigned long

マニュアルには char が signed か unsigned か明記されていない。
char は unsigned char であり、普通の C とは異なるので
unsigned か signed かは必ず明示した方が良い。

次のようなミスが起こりがちである。

関数の返り値を char 型にして、エラー発生時は -1 を入れて
リターンすることにした。この返り値を整数型定数 -1 と比較するとき、
char は unsigned char なので 255 != -1 となり、等しくならない。


◆◆ 変数の割り当て ◆◆

変数を特定のアドレスに割り当てる

char var@0x0008;

ビット変数を特定のアドレスの特定のビットに割り当てる

bit b1@0x0040.1;    0x40 番地の bit 1 に変数 b1 を割り当てる


◆◆ ビットのアクセス ◆◆

char var;
var.2 = 1;

変数 var のビット 2 を 1 にする。

clear_bit(var,2);
set_bit(var,2);
toggle_bit(var,2);

という形式もある。どちらを使っても良い。
clear_bit などはマクロなので、結局同じになる。


◆◆ ポートへの出力 ◆◆

C:\Program Files\SourceBoost\include\16F886.h の中を
見ると以下のように定義されている。

#define PORTB 0x0006
volatile char portb@PORTB;

PORTB への出力

portb = var;

portb.1 = 1;
set_bit(portb,1)

PORTB から入力

portb_buf = portb;

16F886 で PORTB を出力用に設定する場合、入力モードをデジタルモードに
設定しておく必要がある。詳細は「PIC アセンブラ 早見表」の「16F886
PORTB に対する注意」の項目を参照すること。


◆◆ ディレイ ◆◆

delay_us(100);     100 μs
delay_ms(100);     100 ms
delay_s(2);        2 s

引数は unsigned char なので、最大 255 である。
それ以上の値を入れると、256 で割った余りとなる。


◆◆ 定数 ◆◆

 2 進数        0b00001111
10 進数        12 (普通に書く)
16 進数        0x3e


◆◆ ビットシフト命令 ◆◆

a = a << 3;    左へ 3 bit シフト
b = b >> 2;    右へ 2 bit シフト

うっかり b >> 2; と書いて、b を 2 ビット分右へ
シフトしたつもりになってはいけない。この場合

warning: expression was optimized out

というワーニングが出るがコンパイルは通る。

コードウィンドウを見ると、b >> 2; の部分は
対応するアセンブラコードが全くなく、
無視されている。


◆◆ 論理演算 ◆◆

&    and
|    or
^    xor
~    not

上記の演算子は == などより低いことに注意。

○ if ( ( a & 0b00010000 ) == 0 )
× if (   a & 0b00010000   == 0 )


◆◆ エラーメッセージ ◆◆

SourceBoostC コンパイラのエラーメッセージは非常に分かりにくい。
C がある程度使える人にとっては何とかなると思うが、
C 言語に慣れてない人にとっては、エラーが解消できず、
長時間悩むことになるかも知れない。

(例)

エラーの内容 :  general error (一般的なエラー)

関数の定義場所でこのエラーが出たときは、一つ手前の関数において
閉じ括弧が不足している、あるいは当該関数の終了を示す閉じ括弧が
存在しない。if, for, while などで使用する括弧が正しく
対応しているかチェックすること。

エラーの内容 : missing right paren (右括弧 ')' がない)

誤  if ( a => 0 && a <= 3 ) { ( <=  の順序が逆)
正  if ( a <= 0 && a <= 3 ) {

エラーの内容 : missing semicolon (セミコロンがない)

誤  unsighed char ch;  (unsighed の綴りが間違っている)
正  unsigned char ch;


◆◆ C のソースコードとアセンブラコードの対応を見る ◆◆

「表示」→「コードウィンドウ」と操作するとコードウィンドウが
開く。ここで、C のソースコードとコンパイル後のアセンブラの
1 対 1 の関係を見ることが出来る。

思い通りにコードが動かない場合、アセンブラのコードを見て解決
出来ることも多い。


◆◆ 精度の高いディレイ ◆◆

正確なディレイが必要な場合、delay_us(0〜255) では不十分である。
ディレイ関数をアセンブラで書く必要がある。

あらかじめ、必要なディレイのために何サイクル必要かを計算しておく。
PIC は「1 サイクル = 4 クロック」で、大抵の命令は 1 サイクルで実行する。
2 サイクル必要な命令には call, goto, return などがある。
decfsz は条件が成立したとき、次の命令(大抵は goto)を nop に
置き換える(nop は 1 サイクル)。

ディレイ関数は次のように書く

void delay_27cycle()
{
    unsigned char count;
    asm{
        movlw 7
        movwf _count  //  C の変数を利用するときは _ をつける
        nop
      LOOP:
        decfsz  _count,F
        goto LOOP
    }
}

上記の関数をコンパイルすると、ちょうど 27 サイクルになる。
その内訳は

   _count のバンク切り替え  2
   movlw 7                  1
   movwf _count             1
   nop                      1

   ループ部分 3 × 7 - 1 = 20 (ループを抜けるときだけ goto が nop になる)

   return                   2

   合計                    27

上位のルーチンがディレイ関数を呼ぶときは次のように
プログラムを組む。for 文を使うと余分な命令が沢山入る
ので、while の無限ループで組むのが分かりやすい。

void mother_routine()
{
    unsigned char count;

    count = 100;
    while(1){
        処理1
        delay_1();
        処理2
        delay_2();
        count--;
        if ( count == 0 ) break;
        goto LOOP
    }
}

上記のループ部分のアセンブラは以下のようになる

  LABEL
    処理1            x1
    call delay_1      2
    処理2            x2
    call delay_2      2
    decf _count       1
    dtfss STATUS,Z    1
    goto LABEL        2

delay_1, delay_2 のサイクル数をそれぞれ y1, y2 とすると、
ループ 1 回あたりのサイクル数は

    x1 + x2 + y1 + y2 + 8

となる。


◆◆ PICkit2 謎のエラー 16F88 & 16F819 ◆◆

16F88 において次の現象が発生した。

SourceBoost コンパイラを用いて作成したある特定の HEX ファイル
を PICkit2 に付属していた書き込みソフト PICkit 2 Programmer で
書き込んだところ、書き込み後の Verify において

   Verification of configuration failed.

というエラーが発生し、これが起こった後は、「Read」としても
No Device Error となり、その PIC に対して読み書きが出来なくなった。

「Tools」→「Check Communication」と操作すると、再び読み書きできる
ようになった。

問題が発生する HEX ファイルを書き込むと、必ず上記のエラーが発生し、
再現性がある。

16F819 においては以下の現象が発生した

ある特定の HEX ファイル(SourceBoost コンパイラで作成)
を PICkit2 に付属していた書き込みソフト PICkit 2 Programmer で
書き込んだところ、書き込み後の Verify において

   Verification of configuration failed.

というエラーが発生し、これが起こった後は、「Read」としても
No Device Error となり、その PIC に対して読み書きが出来なくなった。

「Tools」→「Check Communication」と操作すると、

   PICkit2 found and connected.
   PIC Device Found.

と表示されるが、依然として読み書きできない。

しかし、アドウィン社の PIC Programmer A と付属ソフト
PICpro.exe を使うと、上記の 16F819 は問題なく読み書きできる。

PICpro.exe を使って何回(1 回ではダメ)か書き込みを行った
16F819 は再び PICkit2 から読み書きできるようになった。

謎である。