目次

シフトレジスタ実験

 デジタル回路でスイッチを扱うときは、チャタリングを
 避けて通れません。

 デジタル回路でクロックを使っているとき、スイッチのチャタリングを
 除去するには、エッジを利用するのが定石と教わりました。

 エッジを補足するには、クロックがあれば、スイッチのオン、オフ
 情報をシフトレジスタに格納するのが、最も簡単でしょう。

 シフトレジスタの回路は、以下。




 2つのレジスタで、状態値に変化があれば、組み合わせが
 2ビットで01となるので、Dフリップフロップの出力の
 論理積で、変化があったときに、論理値の'1'が得られます。

 チャタリングは、10msから30ms以内でおさまるので、クロック
 の周波数を100Hzにすれば、オン、オフの状態確定の情報を得る
 ことが可能。

 タイミングチャートでは、次のような動作になります。




 2チャネル分のスイッチ入力で、チャタリングを除去して
 オルタネート動作を扱えるようにできます。

 74HC175を2ビットのシフトレジスタを2セット用意して
 オルタネート動作を実現する回路は、以下。




 74HC74(Dフリップフロップ)をトグル動作で使い
 74HC74のトリガーを、シフトレジスタによるエッジ
 検出回路で生成しています。

 ユニバーサル基板に半田付けすると、以下。




 シフトレジスタは、Dフリップフロップを並べても
 構成できます。4あるいは8ビットを1パッケージ
 にしたICがあるので、それを使う方が楽なことも
 あります。

 シフトレジスタに接続している論理積のゲートは、
 ダイオードと抵抗による論理積回路にすると実装
 面積を減らせます。



 シフトレジスタ、Dフリップフロップ等をマイコンで
 エミュレートすると、実装面積を大幅に縮小できます。

 PIC12F1501で実現した回路は、以下。



 プログラムは、次のように記述してみました。

/* redefine data type */
typedef unsigned char UBYTE ;

#define OFF 0
#define ON  OFF+1

#define AOUT   PORTA.F0
#define BOUT   PORTA.F1
#define XPOUT  PORTA.F2

#define ITMR   6
#define MASK30 0x30
#define MASK03 0x03
#define MASK33 0x33

volatile UBYTE tflag ;
volatile UBYTE atmp ;
volatile UBYTE btmp ;
volatile UBYTE sft ;
volatile UBYTE astate ;
volatile UBYTE bstate ;
volatile UBYTE inp  ;
volatile UBYTE xcnt ;

/* function prototype */
void init_usr(void);

/* interrupt handler */
void interrupt(void)
{
  /* generate 1ms */
  if ( INTCON.TMR0IF == ON ) {
    /* clear flag */
    INTCON.TMR0IF = OFF ;
    /* 256 - 250 = 6 */
    TMR0 = ITMR ;
    /* set flag */
    tflag = ON ;
    /* increment */
    xcnt++ ;
    /* monitor */
    XPOUT = 0 ;
    if ( xcnt & ON ) { XPOUT = 1 ; }
  }
}

void main(void)
{
  /* initialize */
  init_usr();
  /* endless loop */
  while ( ON ) {
    /* timer handling (1ms) */
    if ( tflag == ON ) {
      /* clear flag */
      tflag = OFF ;
      /* get switch state */
      inp = PORTA ;
      inp &= MASK30 ;
      /* set current switch state */
      atmp = inp & 0x20 ;
      btmp = inp & 0x10 ;
      /* shift register */
      sft <<= 1 ;
      /* mask */
      sft &= MASK33 ;
      /* update */
      if ( atmp == 0 ) { sft |= 0x01 ; }
      if ( btmp == 0 ) { sft |= 0x10 ; }
      /* get current state */
      atmp = sft & MASK03 ;
      btmp = sft & MASK30 ;
      /* judge */
      if ( atmp == 0x01 ) {
        astate++ ;
        astate &= ON ;
      }
      if ( btmp == 0x10 ) {
        bstate++ ;
        bstate &= ON ;
      }
    }
    /* state handling */
    {
      AOUT = astate & ON ;
      BOUT = bstate & ON ;
    }
  }
}

/* define function body */
void init_usr(void)
{
  /* select 4MHz */
  OSCCON = (0x0d << 3) | 0x03 ;
  /* disable A/D converter */
  ADCON0.ADON = OFF ;
  ADCON2      = 0 ;
  ANSELA      = 0 ;
  /* disable D/A converter */
  DACCON0 = 0 ;
  DACCON1 = 0 ;
  /* disable compare module */
  CM1CON0.C1ON = OFF ;
  CM1CON0.C1OE = OFF ;
  /* I/O state */
  PORTA = 0x00 ;
  LATA  = 0x00 ;
  /* I/O directions */
  TRISA = 0x38 ; /* bit0,1,2 as output , others as input */
  /* pull up */
  WPUA = 0x30 ;
  /* initialize timer 0 */
  {
    /*
       4MHz (Fosc)
       Fosc/4 = 1MHz
       1MHz/4 = 250kHz prescaler = 1:4
    */
    OPTION_REG = 0x01 ;
    /* 256 - 250 = 6 */
    TMR0 = ITMR ;
    /* enable timer0 overflow interrupt (1kHz) */
    INTCON.TMR0IE = ON ;
  }
  /* enable general interrupt */
  INTCON.GIE = ON ;
  /* clear */
  tflag = 0 ;
  /* initialize variables */
  sft = 0 ;
  atmp = 0 ;
  btmp = 0 ;
  astate = 0 ;
  bstate = 0 ;
  xcnt = 0 ;
}

 半田付けすると、スカスカ状態になります。



 電源入力にはダイオードを入れて、逆挿しによる
 回路破壊を回避します。




 ダイオードは、10E1相当であれば
 何でもよいです。


目次

inserted by FC2 system