目次

周波数カウンタA

 無線関係のハードウエアをテストする場合には、周波数カウンタを利用します。

 マルチメータに周波数カウンタがついていますが、複数の周波数が混在している
 場合、同時に2カ所を測定したいことがあります。

 2MHz程度までの周波数を測定できればよいので、手持ちのマイコンとLCDを
 利用して、自作しました。



 回路図は、以下です。



 ファームウエアは、Cで簡便に作りました。

#include <avr/io.h>
#include <avr/io8515.h>
#include <avr/interrupt.h>

#define OFF 0
#define ON  OFF+1

typedef unsigned char  UBYTE ;
typedef unsigned short UWORD ;
typedef unsigned long  ULONG ;
typedef   signed char  SBYTE ;
typedef   signed short SWORD ;

typedef union {
  struct {
    unsigned char B0:1;
    unsigned char B1:1;
    unsigned char B2:1;
    unsigned char B3:1;
    unsigned char B4:1;
    unsigned char B5:1;
    unsigned char B6:1;
    unsigned char B7:1;
  } BIT ;
  unsigned char DR ;
} FLAGSP ;

volatile FLAGSP x_flags ;

#define SFLAG x_flags.BIT.B0
#define TFLAG x_flags.BIT.B1
#define DFLAG x_flags.BIT.B7

#define NO  0
#define YES NO+1

volatile UWORD cnt ;
volatile UBYTE stcnt1 ;
volatile UBYTE s[8] ; 
volatile UBYTE lcdx[13] ;

#define LCD_E  2
#define LCD_RW 1
#define LCD_RS 0

#define MASK80 0x80

/*--------------------------------*/
/* Insert user functions protoype */
/*--------------------------------*/
void  user_initialize(void);
void  lcd_out(void);
void  start_timers(void);
void  stop_timers(void);
void  delay_ms(UWORD x);
void  put_lcd_primitive(UBYTE which,UBYTE dat);
void  init_lcd(void);
void  put_lcd_str(UBYTE r,UBYTE c,UBYTE *ptr);

/*------*/
/* main */
/*------*/
int main(void)
{
  ULONG scount ;
  UWORD uscnt ;
  UWORD lscnt ;
  UBYTE i ;
  /* disable interrupt */
  cli();
  user_initialize();
  /* enable interrupt */
  sei();
  /* initialize LCD */
  init_lcd();
  /* start timers */
  start_timers();
  /* loop */
  while ( ON ) {
    /* watch flag */
    if ( TFLAG ) {
      TFLAG = OFF ;
      /* stop timers */
      stop_timers();
      /* concatenate counter */
      scount = TCNT1 + stcnt1 * 65536 ;
      /* separate */
      uscnt = scount / 10000 ;
      lscnt = scount % 10000 ;
      /* calculate digits */
      *(s+0) = uscnt / 1000 ; uscnt %= 1000 ;
      *(s+1) = uscnt / 100  ; uscnt %= 100  ;
      *(s+2) = uscnt / 10   ;
      *(s+3) = uscnt % 10   ;
      *(s+4) = lscnt / 1000 ; lscnt %= 1000 ;
      *(s+5) = lscnt / 100  ; lscnt %= 100  ;
      *(s+6) = lscnt / 10   ;
      *(s+7) = lscnt % 10   ;
      /* convert ascii */
      for ( i = 0 ; i < 8 ; i++ ) { *(s+i) += '0' ; }
      /* copy */
      *(lcdx+0) = *(s+0) ;
      *(lcdx+1) = *(s+1) ;
      *(lcdx+3) = *(s+2) ;
      *(lcdx+4) = *(s+3) ;
      *(lcdx+5) = *(s+4) ;
      *(lcdx+7) = *(s+5) ;
      *(lcdx+8) = *(s+6) ;
      *(lcdx+9) = *(s+7) ;
      /* LCD out */
      lcd_out();
      /* start timers */
      start_timers();
    }
  }
  /* dummy */
  return 0 ;
}

void user_initialize(void)
{
  /* PORT B */
  PORTB = 0b00000000 ; /* 00000000 */
  DDRB  = 0b11111101 ; /* ooooooio */
  /* PORT D */
  PORTD = 0b00000000 ; /* 00000000 */
  DDRD  = 0b11111111 ; /* oooooooo */
  /* PORT A */
  PORTA = 0b00000000 ; /* 00000000 */
  DDRA  = 0b11111111 ; /* oooooooo */
  /* PORT C */
  PORTC = 0b00000100 ; /* 00000000 */
  DDRC  = 0b11111111 ; /* oooooooo */
  /* clear flags */
  x_flags.DR = 0 ;
  /* initialize timer0 */
  {
    TCNT0 = 6 ;
    TCCR0 = 0 ;
  }
  /* initialize timer1 */
  {
    TCNT1 = 0 ;
    TCCR1A = 0 ;
    TCCR1B = (1 << ICNC1) | (1 << ICES1) ;
  }
  /* enable timer interrupts */
  TIMSK = (1 << TOIE1) | (1 << TOIE0) ;
  /* */
  *(lcdx+2) = ',' ;
  *(lcdx+6) = ',' ;
  *(lcdx+10) = 'H' ;
  *(lcdx+11) = 'z' ;
  *(lcdx+12) = '\0' ;
  /* */
  cnt = 0 ;
  stcnt1 = 0 ;
}

void  lcd_out(void)
{
  put_lcd_str(0,0,(UBYTE *)lcdx);
}

void  delay_ms(UWORD x)
{
  UWORD loop ;

  while ( x ) {
    /* 1000 us */
    for ( loop = 0 ; loop < 1000 ; loop++ ) ;
    /* decrement */
    x-- ;
  }
}

/* timer0 interrupt */
ISR(TIMER0_OVF_vect)
{
  /* set counter */
  TCNT0 = 6 ;
  /* increment */
  cnt++ ;
  /* judge */
  if ( cnt == 400 ) {
    cnt = 0 ;
    TFLAG = ON ;
  }
}

/* timer1 interrupt */
ISR(TIMER1_OVF_vect)
{
  /* increment */
  stcnt1++ ;
}

void  start_timers(void)
{
  /* prepare */
  cnt = 0 ;
  stcnt1 = 0 ;
  /* */
  TCNT0 = 6 ;
  TCNT1 = 0 ;
  TCCR0  |= (1 << CS00) ;
  TCCR1B |= (7 << CS10) ;
}

void  stop_timers(void)
{
  TCCR0 = 0 ;
  TCCR1B &= ~0x07 ;
}

void put_lcd_primitive(UBYTE which,UBYTE dat)
{
  /* 0 -> E */
  PORTC &= ~(1 << LCD_E) ;
  /* RS */
  PORTC &= ~(1 << LCD_RS) ;
  if ( which ) { PORTC |= (1 << LCD_E) ; }
  /* data */
  PORTA = dat ;
  /* 1 -> E */
  PORTC |=  (1 << LCD_E) ;
  /* 0 -> E */
  PORTC &= ~(1 << LCD_E) ;
}

void init_lcd(void)
{
  /* initialize hardware */
  delay_ms(15) ; /* 25ms */
  put_lcd_primitive(OFF,0x30);
  delay_ms(5) ; /* 5ms */
  put_lcd_primitive(OFF,0x30);
  delay_ms(1); /* 1ms */
  put_lcd_primitive(OFF,0x30);
  delay_ms(1); /* 1ms */
  put_lcd_primitive(OFF,0x20);
  delay_ms(1); /* 1ms */
  /* set function */
  put_lcd_primitive(OFF,0x28);
  put_lcd_primitive(OFF,0x08);
  put_lcd_primitive(OFF,0x01);
  delay_ms(2); /* 2ms */
  put_lcd_primitive(OFF,0x06);
  delay_ms(2); /* 2ms */
  put_lcd_primitive(OFF,0x0c);
  put_lcd_primitive(OFF,0x02);
  put_lcd_primitive(OFF,0x80);
}

void  put_lcd_str(UBYTE r,UBYTE c,UBYTE *ptr)
{
  UBYTE adr ;
  /* check range */
  if ( r >  1 ) return ;
  if ( c > 15 ) return ;
  /* set address */
  switch ( r ) {
    case  1 : adr = 0x40 ; break ;
    case  2 : adr = 0x14 ; break ;
    case  3 : adr = 0x54 ; break ;
    default : adr = 0x00 ; break ;
  }
  adr += c ;
  adr |= MASK80 ;
  put_lcd_primitive(OFF,adr);
  while ( *ptr != '\0' ) {
    put_lcd_primitive(ON,*ptr);
    ptr++ ;
  }
}


目次

inserted by FC2 system