今回は・・・再び7セグメントディスプレイ(3桁)です。以前作成したバージョンでは、表示する内容を外部から送ることができませんでした。そこで今回はシリアル通信を利用し、外部からデータを受け取り表示するようにします。
以前の回路はI2Cにて通信を行う予定だったので、そのような配線になっています。しかし今回はシリアル通信なので、回路図および使用するピンが変わるので注意してください。・・・と思っていたのですが、シリアル通信も受信だけならば回路を変えずに済むということに気が付いたので、変更しないことにしました。なので、今回の回路を使用するとシリアル通信での送信はできません。
回路図およびプログラムに関する各種詳細は、以下の記事を参考にしてください。
1.仕様
1.1 ハード仕様
- PIC:PIC16F1829
- 以前作成した7セグメントディスプレイの回路を使用する
- シリアル通信を行う
- シリアル通信は受信のみとする
1.2 ソフト仕様
- 通信速度:9600bps
- 1バイトの受信タイムアウト時間:3.2[msec]
- チェックサムなし
- データの有効性チェックなし
- 7セグメントディスプレイ表示は0、1、2、3、4、5、6、7、8、9とする
- 7セグメントディスプレイのドットは数字とは別に制御する
- 無効な0は表示しない
(012の場合、12だけを点灯させる。ただし、0.01のような場合は0を点灯させる)
注:返信するすべがないので、間違っていてもどうしようもないです。なので、間違えていたらそれを表示したほうが問題に気づけると考え、そのまま表示させています。(エラーと表示させると、何がどうエラーなのかわからないため)
本来はきちんと異常を確認し、問題があれば返信するようにするべきだとは思います。なので、実際に作成する場合はそれらを考慮することをお勧めします。
1.3 通信伝文
- 1伝文のサイズ:3バイト
- 伝文の中身は以下のとおりとする
データ位置 | 説明 |
---|---|
1バイト目 | ドットの位置 0x01:1の位 0x02:10の位 0x04:100の位 対象の位置を0にすると消灯、1にすると点灯 |
2バイト目 | 上位4ビット:使用しない 下位4ビット:100の位 |
3バイト目 | 上位4ビット:10の位 下位4ビット:1の位 |
1.3.1 「12.3」を点灯させたい場合
12.3を点灯させたい場合、データは以下の表のとおりです。
データ位置 | データ |
---|---|
1バイト目 | 0x02 |
2バイト目 | 0x01 |
3バイト目 | 0x23 |
2.回路図
2.1 電子回路図
2.2 電子回路の写真
2.3 回路説明
基本的にセグメントディスプレイ(3桁)と同様です。違いはシリアル通信用に「RB5」をコネクタに接続しているところです。
3.プログラム
プログラムの基本的な部分は以下の記事を参考にしてください。
3.1 ざっくりとした説明
プログラムを見ながら以下の説明を見てください。ソースコードは次の節にあるので、そちらを参照してください。
3.1.1 シリアル通信の受信処理
// シリアル受信 if( RCIF ) { if( FREE == 0 && OERR == 0 ) { // 受信データをバッファヘ保存 uart_rx_buf[uart_rx_cnt] = RCREG; uart_rx_cnt++; // 最後のシリアルデータを受け取った時 if( uart_rx_cnt >= UART_RX_SIZE ) { // タイムアウト停止 TMR0 = TIMER0_INIT_CNT; TMR0IE = 0; for(i=0 ;i<3; i++) uart_rx_dat[i] = uart_rx_buf[i]; uart_rx_cnt = 0; uart_rx_flg = true; } else { // タイマのカウントを開始 TMR0 = TIMER0_INIT_CNT; TMR0IE = 1; } } else { RCSTA = 0; RCSTA = 0x90; } RCIF = 0; }
シリアル通信で受信したデータの処理を行っています。
- シリアル通信で1バイト受信する毎に割り込みが発生
- 受信したデータをバッファに保存
- 受信したデータが3バイトになった際、uart_rx_flgをtrueにする
補足1:1バイト受信するたびにタイムアウト時間を更新しています
補足2:タイムアウトした場合、受信位置を先頭に戻します
3.1.2 受信データの変換処理
// 新しいデータを受信 if( uart_rx_flg ) { // 7seg の制御へ渡す seven_seg_data[0] = 0x0f & uart_rx_dat[2]; seven_seg_data[1] = 0x0f & (uart_rx_dat[2]>>4); seven_seg_data[2] = 0x0f & uart_rx_dat[1]; seven_seg_flg = uart_rx_dat[0]; uart_rx_flg = false; }
シリアル通信で受信したデータを7セグメントディスプレイ用に変換しています。
- シリアル通信で3バイトデータを受信(uart_rx_flg == true の場合)
- 受信したデータを分解しそれぞれの変数に代入
- 内部データの更新が完了したので、uart_rx_flgをfalseにする
3.1.3 7セグメントディスプレイの表示
// 7seg 表示制御 seven_seg_ctrl();
7セグメントディスプレイの制御関数呼び出し
3.1.4 7セグメントディスプレイの表示処理
7セグメントディスプレイの表示処理を行っています。5[ms]毎に表示する桁を切り変えています。
void seven_seg_ctrl( void ) { static unsigned char seq_digi = 0; unsigned char out; bool enable; switch( seq_digi ) { case 0: // 100の位 out = seg_led[seven_seg_data[2]]; // DP if( (seven_seg_flg & 0b00000100) != 0 ) out |= 0b10000000; // 表示か非表示か判定する enable = false; if( seven_seg_data[2] != 0 ) enable = true; if( (seven_seg_flg & 0b00000100) != 0 ) enable = true; if( !enable ) out = 0; break; case 1: // 10の位 out = seg_led[seven_seg_data[1]]; // DP if( (seven_seg_flg & 0b00000010) != 0 ) out |= 0b10000000; // 表示か非表示か判定する enable = false; if( seven_seg_data[2] != 0 ) enable = true; if( seven_seg_data[1] != 0 ) enable = true; if( (seven_seg_flg & 0b00000110) != 0 ) enable = true; if( !enable ) out = 0; break; case 2: // 1の位 out = seg_led[seven_seg_data[0]]; // DP if( (seven_seg_flg & 0b00000001) != 0 ) out |= 0b10000000; break; default: seq_digi = 0; out = 0; break; } out_seven_seg( out, seq_digi ); __delay_ms(5); seq_digi++; if( seq_digi > 2 ) seq_digi = 0; }
220 ~ 228行目および239 ~ 249行目
不要な0を表示しないようにする処理です。001の場合、1の位に1だけを表示、0.01の場合、0.01を表示するようにしています。
3.2 ソースコード
プログラムの全文を掲載します。
<注意>
ファイル名は必要に応じて変更し利用してください。
本サイトの注意事項を確認してください。
ソースコードや回路図などを使用する場合、上記注意とともに、自己責任でお願いします。
4.動作確認
仕様通りのデータを受信した場合、その通りに表示されます。今後、この7セグメントディスプレイを使用し、色々なものを表示させていく予定です。
<更新履歴>
新規作成:2015年7月2日
第2版:2016年10月7日:フォーマット変更(内容の変更はなし)