Pi:Co Classic Ver3 改造例(2)からだいぶ経ってしまいましたが、まだ完結していないので続きます。
今回の改造例(3)では、7セグを制御するPICとそのプログラムについて語ります。
なぜPICにしたのか?それは、サンプルプログラムがインターネット上にいろいろあり、それを参考に組み合わせれば、さくさくとプログラムが完成し、開発時間を短縮できるという理由でPICを使おうと考えました。
PICの型番の選定ですが、Pi:Co Classic Ver3 改造例(1)にも書きましたが、Pi:Co Classic Ver3の残りの端子で7セグにデータを送る手段としてUART(SCI)を選択しています。少なくともUART機能があるPICを選ぶ必要があります。その次に、7セグを制御する端子として、アノードの制御として3端子、カソードの制御して8端子の合計11端子とUARTの制御に2端子必要になります。それと電源(VDDとGND)の2端子を合わせると合計15端子が最低必要端子数になります。そのほかにPICにプログラムを書き込む端子があり、その端子は7セグの制御の端子と兼用にしない方が無難なので、PICにプログラムを書き込む3端子(ICSPCLK、ICSPDAT、VPP)を別にしました。合計18端子以上のPICを選定すればよいことになります。あとは、型番探しです。
近くに秋月電子通商があるので、秋月電子通商で売っているPICから選択しました。PICのカテゴリーの中で価格でソートし、18端子以上てUART機能ありを探すと16F687にたどり着きました。価格でソートしているのは、今回の7セグの制御では、周辺機能(A/DやSPIなど)はUART以外使用しないので、高性能なPICにする必要がないため、価格が低いものから選んでいます。
プログラミングに入る前に、ご存じ方もいらっしゃると思いますが、PICはバンクという機能があり、バンクを切り替えてレジスタの設定をする必要があります。たとえば、PortAの入出力の設定レジスタはBankB、PortAのデータの入出力はBankAといった具合です。アセンブラでは、Bankを切り替えて、レジスタにアクセスする必要がありますが、MPLAB X IDE V3.20とXC8のC言語コンパイラを使用するとバンクの切り替えはコンパイラが勝手にやってくれて便利なので、この環境で開発しています。
さて、本題のPICのプログラムですが、Pi:Co Classic Ver3 改造例(2)からUARTを使い、7セグ3個を切り替えて表示するところまでは何となくわかると思います。しかし、実際、プログラムを書こうとすると何から書けばよいのかわからないと思います。わからない時は、順番に整理していくと いつの間にか形になっています。
まず、最初に仕様を決めます。その次にフローチャートを書いてみます。最後にプログラミングし、実行して確認します。間違っていたら修正します。これは、PDCA(Plan Do Check Action)サイクルそのものです。つまり、最初に何をするかわからない人は、Plan(仕様)ができていないという事になります。
最初の仕様は、こんな感じでざっくりと決めました。最初は間違っていてもよいです。あとのActionの工程からのフィードバックで修正すれば、より良いものになりますので。
・UARTは割り込みを使用し、割り込みが入ったらデータを更新をする。
・7セグのデータはシフトレジスタ形式にする。
・7セグの繰り替えは、3msごとに切り替える。main文の中でwhileでまわす。
今回の仕様では、条件分岐がないのてフローチャートを省略しています。条件分岐がある場合、ある条件のときの処理を忘れていた~というのがあるので書いた方が良いです。
最初に、UARTを使用せずに7セグの点灯の確認をしました。(すべて書いた後で動作しない時に、切り分けが必要になるため、可能ならば、ブロック毎に確認した方が開発の効率が上がります。)
以下が最初に書いたプログラムです。
#include <xc.h> #define _XTAL_FREQ 8000000 unsigned char data[3]; __CONFIG( CPD_OFF & WDTE_OFF & PWRTE_ON & BOREN_OFF & MCLRE_ON & CP_OFF ); #pragma config FOSC = 0x04; void main(void) { OSCCON = 0x71;//8MHz SCS:SYSTEM Clock internal oscillator PORTA = 0; PORTB = 0; PORTC = 0; ANSEL = 0; ANSELH = 0; //outout =0; input=1(default) TRISA = 0xcb;//1100 1011 TRISB = 0x7f; TRISC = 0x00; data[0]=0xeb;//1を表示 data[1]=0x1a;//2を表示 data[2]=0x8a;//3を表示 while(1){ PORTA = 0xfb; PORTC = data[0]; __delay_ms(3); PORTA = 0xef; PORTC = data[1]; __delay_ms(3); PORTA = 0xdf; PORTC = data[2]; __delay_ms(3); } }
以下の様に1,2,3と点灯すれば成功です。
プログラムの解説をしますと、
1行目:レジスタ名が設定されているヘッダをインクルードしています。
2行目:クロックの周波数を定義しています。_XTAL_FREQはこの環境で決められた変数なので変更はできません。この設定がないと__delay_ms()関数が使えません。
4行目:7セグのカソードの端子の制御データを格納する変数を配列で定義しています。
6、7行目:Configuration Word register(CONFIG)を設定しています。(設定内容の詳細はPICのマニュアルを見てください)
10行目:クロックをデフォルトの4Mから8MHzに変更しています。少しでも早くしてシリアル通信の設定値によるエラー率を軽減させています。
11~20行目:PORTA、B、Cを出力に設定しています。PortAは7セグのアノードの制御、PortCは7セグのカソード制御です。PIC16F687はA/Dの機能があります。デフォルトでA/Dが選択されているため、汎用ポートを使うには、ANSEL、ANSELHレジスタで汎用ポートに切り替える必要があります。
22~24行目:7セグのカソード制御の初期データを入れています。7セグは、LEDなので、カソード側を”0″、アノード側を”1″にすると点灯します。今回アノード側にはPchFETを使用しているため、7セグのアノード側を”1″にするにはPICの出力を”0″にする必要があります。
26行目:whileを使用しないと一回だけ点灯して終了になるため、3つの7セグがすべて点灯したようになりません。
27行目:7セグの右側のアノードに”1″、他の7セグのアノードに”0″が入るようにしています。
28行目:7セグのカソード側に点灯データを送信しています。この行では1のデータを転送しています。
29行目:3msWait。これがないとLEDの点灯時間が短すぎて暗くなってしまうため少し点灯させてから次の7セグに移ります。
31行目:7セグの真ん中のアノードに”1″、他の7セグのアノードに”0″が入るようにしています。
32行目:7セグのカソード側に点灯データを送信しています。この行では2のデータを転送しています。
35行目:7セグの左側のアノードに”1″、他の7セグのアノードに”0″が入るようにしています。
36行目:7セグのカソード側に点灯データを送信しています。この行では3のデータを転送しています。
続きは、Pi:Co Classic Ver3 改造例(4)のUART通信編で説明します。