ちょっとTea Time!? 【備忘録】CCS-Cコンパイラの憂鬱(UARTの設定) 2025.8.17

PICを動かすためにCコンパイラを使いだして、もう10年以上たちます。
使いだしたきっかけは電子ボリュームのコントロールです。

PIC用のC言語は、当時でも純正品とかあったと思うけれど、本屋で手にした
書籍の内容がそのまま使えると思って、CCS社のコンパイラを使っています。


PICのC言語はこれで勉強させてもらいました。


CCS社のPIC用のCコンパイラを使っています。

コンパイラは3回購入
 コンパイラはWindows上でつかえるものと、コマンドラインで使うものの2種類があったのですが、
安い方のコマンドラインで使うコンパイラを購入しています。PICが新機種がでたり、プログラム容量が
大きくなるのにあわせて、都合いままでで3回ほどCCSのコンパイラを購入です。

1回目 PIC 12F,16F用 ver 4.114
 始めての購入です。当時にメインでつかっていたPICはPIC16F819で2kBの小さいものです。
 これでも電子ボリュームなどの組み込みには十分でした。PIC16F1938(32kB)にも対応していたので、
 かなりのことができましたが、液晶表示などを使うようになると文字表示でどんどんプログラム容量が
 大きくなり、限界になってきました。

2回目 PIC 18F用 v.5.062
  さらに容量の大きなPIC18Fシリーズが使えるようにと購入です。このコンパイラで一番よくつかったのが
 PIC18F26K20でROMは64kBあります。さらに64MHzでの動作なので、これで十分かなあ〜と思っていましたが、
 チャンネルデバイダの開発ではROM容量が98%くらいまで圧迫するようになりました。
 最新のPICだとROM容量が128kBまであるのですが、このコンパイラではサポートしていません。
 そろそろ買い替えかなあ〜。

3回目 PIC 18F用 v.5.105
 現在よくつかうPIC18F27Q43(128kB)をサポートしています。いまのところ、これで事足りています。
 さらに上位PICのPIC24Fが32シリーズにも触手がのびそうになった時期がありましたが、RaspberryPiや
 PICOもあるので、我慢しています。


問題はPIC18F用のv5.062とv5.105との違い

以前のv5.062のソースファイルが、v5.105では通らないことが多いです。いや、まず100%通りません。
修正が必要なところは、プログラムの書き出しの部分です。PICの新しい機能に対応している修正なので、
とくに問題ではないのですが、同じ機能でもバージョン違いで書き方が変ったと思われる箇所があります。
コンパイラの取説にはそういったことが全然記載されていないので、結構トライアンドエラーになりますが、
この連休中の半日ほど、下記でトラブりました。

UART(シリアル通信)がつかえない?

以前に作ったCPM80のPICは少し古いPIC18F46K22(64kB)ですが、それを最近のPIC18F47Q43(128kB)の
交換にトライです。PIC18F46K22のときはコンパイラv5.062で作成しました。
それをPIC18F27Q43に切り替えるにあたり、v5.105で再コンパイルを試みますが、なかなか通りません。
 問題になったのは、UARTに関する部分です。
 v5.062では、下記のような書き出し(#USE)でUARTが問題なく使えました。

#use RS232(UART1,BAUD=115200)

void main()
{
   printf("HELLO!");

}

しかし、v5.105ではエラーがでてきます。どうやら、もうちっと丁寧に書かないといけないようです。
ということで、下記のように書き換えです。

#use RS232(STREAM=UART1,BAUD=115200)

これで、コンパイラは通りましたが、バイナリをPICに書き込みますがうんともすんともいいません。
まったくUARTが反応していません。
UARTはPIC内蔵の機能をつかうことになるのですが、どうやらTX(送信)とRX(受信)ピンを
宣言しないといけないようです。ということで、下記のように修正です。
送信ピンをPIN_C6に、受信ピンをPIN_C7に割り当てです。これは、PICで指定されたUARTピンです。

#use RS232(STREAM=UART1,BAUD=115200,xmit=PIN_C6, rcv=PIN_C7)

これで、コンパイラは通りましたし、バイナリを書き込んだPICで動いたのですが、
なにか動作がおかしい。中でkbhit関数(受信したデータがあるかどうかの確認)が
が上手く動いていません。そのため、制御をCPM80に移行したときに文字が受信できません。

色々と調べているとkbhit関数は、UARTがハードウエアで動いている場合のみ有効なようです。
しかし、下記のように受信ピンと送信ピンを指定すると、どうやらCCSコンパイラがソフトウエア制御
でUARTの機能を実現させるように動くようです。

#use RS232(STREAM=UART1,BAUD=115200,xmit=PIN_C6, rcv=PIN_C7)
→この書き方だけだと、UARTがソフト動作になるようです。

UARTをソフトで動かすということは、受信ならびに送信ピンは任意に割り当てすることができますが、
そんなことは要らないから、まずはUARTをハードで動かしてほしいものです。そうしないと、
kbhit関数がつかえなくてCPM80が動きません。

UARTがソフトで動いていることを確認するために、下記のようなプログラムを実行です。
一文字送信のputc関数の実行前後でI/Oピンのレベルを変えてやります。

#use RS232(STREAM=UART1,BAUD=115200,xmit=PIN_C6, rcv=PIN_C7)
void main()
{
   for(;;){
    output_high(PIN_D1);
    putc('a');
    output_low(PIN_D1);
    delay_us(100);
   }

その結果、見事にputc関数の実行に、まるまる時間がとられていることがわかります。


上側がPIN_D1。下が通信データ。putc関数を出す間は
それにかかりっきりになっていて、ソフトで動いていることがわかります。


UARTをソフトで行うと、受信データの取りこぼしがでてしまう点と、
受信時の割り込みをかけることができないために、プログラムを大きく書き換える必要がでて
きます。
 さてさて、どうやったらUARTをハードで動かすことができるだろうか?

#PIN_SELECTを使う?

コンパイラの取説で関係しそうなところを読み漁って、関係しそうなところを何度も試してみました。
で、ようやく問題が解決しそうです。
 どうやら、使用するピンをハードでつかうことを宣言する必要がありそうです。
#PIN_SELECTという宣言をつかって、UART1のハードを使うことを明示です。
しかし、#USE宣言でのxmit=PIN_C6, rcv=PIN_C7との重複感がものすごくあります。
かといって、これを省略するとコンパイラが通りません。
不思議だあ〜。


#PIN_SELECT U1TX = PIN_C6
#PIN_SELECT U1RX = PIN_C7

#use RS232(STREAM=UART1,BAUD=115200,xmit=PIN_C6, rcv=PIN_C7)

void main()
{
   for(;;){
    output_high(PIN_D1);
    putc('a');
    output_low(PIN_D1);
    delay_us(100);
   }

とりあえず、上記のようなプログラムにするとputc関数に時間がとられることはありません。
データをputcでPICに引き渡せば、あとはハードが通信処理をしてくれます。


上側がPIN_D1。putc関数の実行は一瞬で、通信はハードが
やってくれている様子がわかります。


とりあえず、これでUARTをハードで動かすことができました。
無事にCPM80のPICを差し替えることができました。
しかし、結構時間を喰いました。連休中の半日はこれにつかったなあ〜。

後のバージョンでは改善されている?
 どうやら、今回判明した宣言の重複感ですが、一つあとのバージョンでは解消されているポイです。
持っているバージョンがv5.105ですが、どうやらv5.106ではこれが修正されているようです。
まあ、購入したタイミングが悪かったのか、それとも、そのお蔭で色々と調べられたのか。
まあ、ここはポジティブに後者と思いましょう!


購入した直後のバージョンでは、修正されているポイなあ〜。

(おしまい)