I2C接続6桁数字表示

  1. I2C接続7桁数字表示


    1. I2C接続

      I2Cインタフェースの詳細については、別項を参照してください。このインタフェースは2本のバスラインで複数の回路を接続できます。ここでは、6桁の数字と8個のLEDをI2C経由で点灯する回路を紹介します。

    2. 回路構成

       回路基板は wsnak さんの市販ボードを利用します。下図は 引用です。PICに16F873を利用し、プログラム書き込み用のICSP端子と、I2Cおよび電源接続用の共通インタフェースがあります。


       7素子数字表示器は、C-551タイプで「秋月電子」などで、入手できます。カソードコモン型ですから、アノードコモン型と間違えないよう注意してください。赤色と青色のタイプがあります。ここでは、C-551UB(青色)を利用しました。

    3. 回路図

       回路図も wsnak さんのHPより引用させていただきます。7素子とDP(小数点)を、RB7〜RB0 で点灯しています。6個の7素子LEDと8個のLEDを動的に切り替えて点灯しています。切り替えのドライバに、TD62003を利用しています。シリアル(RS232C)の端子もありますから、こちらから点灯することも可能です、ここでは利用していません。
       I2Cアドレス設定用の 端子もありますが、ここでは利用しません。

  2. プログラム


    1. I2Cコマンド

       I2Cコマンドは、上位4ビットに桁数、下位4ビットで数字(0〜9)を指定することにします。したがって、すべての桁とLEDを表示するには、7回のコマンド送出が必要です。ただし、LEDの場合は桁数を0とし、下位4ビットを点灯パタンにします(現在のソースでは、下位4ビットのみ表示可能です)。
       例えば、0x0A は 個別LEDの 0x0A を点灯します。 0x15 の場合、1桁目に数字5を表示します。
      I2Cのデバイスアドレスは0x62としました。

    2. マスタ側テスト用ソース

      マスタ側の回路は、C4 に SDA、C5にSCL、を接続し、Bポートに動作チェック用のLEDを4個接続しています。0〜9の数字を順に送りつけているだけですが、val で1回送るごとに基底の数字を変更しています。

      //////////////////////////////////////////////////
      // I2Cマスターテストプログラム      //  
      //7SEG*6 をI2Cで制御
      //I2Cデバイスアドレスは0x62
      //コマンド (num,val)、num,valは4bit
      //num:桁番号、val:値
      //num=0はLEDで2進表示、他は0~9で数字表示
      
      //マスタの回路は、C4,C3をI2C接続
      //ポートB、A0 をLED表示(動作確認用)
      
      #include <16f873a.h>
      #fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT
      #use delay(clock = 20000000)      
      #use i2c(MASTER,sda=PIN_C4,scl=PIN_C3,FORCE_HW)
      
      //メイン関数/////////////////////////////////////////
      #define seg6dva 0x62
      
      int i,val;
      int tm,num;
      
      void main(){
      
          val=0;
          tm=0;
          //set_tris_c(0x99);          //RB 7-4:IN 3-0:OUT
           
          output_float(PIN_C3);       //I2C pin float
          output_float(PIN_C4);       //I2C pin float 
          //Cポートに出力する場合、set_tris_c()が必要  
          
          delay_ms(100); //wait for Client up  
             
          while(1){
      
               output_bit(PIN_A0,tm);//動作確認
               tm = ~tm;
                               
                  i2c_start();       //スタートコンディション
                  i2c_write(seg6dva);
                      
                  for(i=0;i<7;i++){
                        num=i;
                        i2c_write(num<<4 | (num + val) %10 );
                   }
               
                   i2c_stop();
                      
                   output_b(~val);
                   val++;
                                                         
               delay_ms(2000);
      
           }         
      }

    3. 7素子表示スレーブソース

       I2Cのスレーブ側のプログラムです。main() で、segv[] 配列の値を動的表示しています。 seg_data[] に数字用点灯パターンを設定しています。I2Cの受信割り込みで、
        val2=i2c_read(0); 
       segv[val2>>4]=val2 & 0xF;
       I2Cからデータを受け取り、上位4ビットで桁数、下位4ビットで表示する値としています。このままでは、8こあるLEDの上位4個が利用できません。8桁目でLEDの上位4ビットにする、などの変更が必要です。
       この回路はかなり電気を食います。電池駆動する場合、点燈時間を短くして低電力モードに設定できると便利かもしれません。

      //I2C Slave
      //set 7segLED
      //7seg:a-pic:B0,7seg:g-pic:B6,7seg:dp-pic:B7
      //set_tris_c(0xF8);をしないと、C4,C3が0になりI2Cが動作しない
      //I2C割込みで、segv[]を設定
      
      #include <16F873A.h>
      
      #fuses HS,NOWDT,NOLVP,NOBROWNOUT
      #use delay(clock = 20000000)      
      #use I2c(slave,sda=PIN_C4,scl=PIN_C3,address=0x62,FORCE_HW)//address must be EvenNumber
      #use fast_io(c)
      #use fast_io(a)
      
      int val2;
      int state;
      
      int seg_data[]={0x3f,0x06,0x5B,0x4f,0x66,0x6d,0x7d,0x7,0x7f,0x67};
              
      //表示する値0−9
      int segv[7]={0,1,2,3,4,5,6};
      int seg,loop;
      
              
      #INT_SSP
      void ssp_interupt (){
          
         state=i2c_isr_state();
         //printf("state:%x\r\n",state);
         
         if(state>=0x80){//addrs match with master read         
                i2c_write(0);//return sw value
          }
          else if(state >0){//adrs match with master write
                 val2=i2c_read(0);
                 segv[val2>>4]=val2 & 0xF;
          }
          
      }
      
      void main (){
          
          //output_c(0);
          output_a(0);
          set_tris_c(0xF8);
          set_tris_a(0xF0);
                   
          output_float(PIN_C4);  //I2C pin float
          output_float(PIN_C3);  //I2C pin float
          
           set_tris_c(0xF8);//ここで設定がないとC3〜C0が出力にならない
           enable_interrupts(INT_SSP);     //SSP割り込みを許可
           enable_interrupts(GLOBAL);      //全ての割り込みを許可
         
           while (1) {
                                   
                   for(loop=0;loop<100;loop++){
                                 
                      for(seg=0;seg<7;seg++){
                                output_c(0);
                      output_a(0);
                       
                      output_b(seg_data[segv[seg]]);
                      
                                switch (seg){
                                         
                                case 0:output_b(segv[seg]);
                                        output_bit(PIN_C2,1);
                                        break;
                                case 1:output_bit(PIN_C1,1);
                                        break;
                                case 2:output_bit(PIN_C0,1);
                                        break;
                                case 3:output_bit(PIN_A3,1);
                                        break;
                                case 4:output_bit(PIN_A2,1);
                                        break;
                                case 5:output_bit(PIN_A1,1);
                                        break;
                                case 6:output_bit(PIN_A0,1);
                                        break;
      
                                }                                                         
                    delay_ms(2);
                  }
                }
                
         }     
      }