6-3. まずは、LEDの点滅から試してみたい



<6-3-1> 簡単なLED点滅

 まずは簡単なプログラム。基板上のLEDを1秒間隔で点滅させるものである。

#procfreq 2097				// System Clock = 2.097MHz

#procfreqは、kHzの単位で使用しているクリスタルの発振周波数を指定する。

#include <delays.h>
#include <datalib.h>
#include <P16F873.H>
#include <Strings.h>
# define BIT1 0x2


#includeでは、ヘッダーファイルなどをインクルードしている。この例では、全部は必要ないのだが、あっても毒にはならないので、いつもオマジナイとして全てを書いている。#defineの行では、BIT1に16進数で2という意味を持たせている。BIT1は変数ではなく、定数となる。プログラム中では書き換えられない。

 I/Oポートの初期化では、最低限設定必要な部分を書いてある。ポートの設定は、PICを動かす上で基礎中の基礎である。これを間違えると、絶対動かない。文献3および詳細は文献4を見ながら、気をつけて設定する必要がある。後閑さんのPIC活用ガイドブックは読みやすく、ポイントが上手に押さえてあるので、一冊手元におくことをお勧めする。ただし、PICの機能を使いこなすには、やはりメーカー発行の仕様書(文献4)のお世話になることとなる。本GMカウンターのプログラムについても、最終的には文献4まで目を通さないと完成できないこととなった。幸い、文献4に関しては日本語版もあるので、こちらを入手した方が効率があがると思われる。日本語の説明書は、IPI社からFED-Cを購入すると、CD-ROMに入っているハズである。

プログラムソ−スの転用・転記不可。および個人の趣味を超えた使用を禁止する。性能は一切保証しない。
// Test Program 1.0 //

#procfreq 2097				// System Clock = 2.097MHz
#include <delays.h>
#include <datalib.h>
#include <P16F873.H>
#include <Strings.h>
# define BIT1 0x2
//
//----------------------------------------------------------------//
//
void  init_port()		// Init I/O Ports
{
  TRISA = 0x17 ;		// Port A xxOI OIII
  TRISB = 0x01 ;		// Port B OOOO OOOI
  TRISC = 0x89 ;		// Port C IOOO IOOI
  OPTION_REG = 0xc7 ;		// Pullup = off, T0 = OSC, PS -> TMR0
  INTCON = 0x00 ;		// All IRQ  OFF
}
//
// ------------------------------------------------------------------
//
void main()
{
  unsigned int i ;

  init_port() ;

  while(1)
  {
    PORTC |= BIT1 ;			// LED ON
    Wait (1000) ;			// wait 1sec
    PORTC &= ~BIT1 ;			// LED OFF
    Wait (1000) ;			// wait 1sec
  }	// End of while loop
}	// End of main program

 このソースをFED-CのVer7.0でコンパイルし、HEXファイルをライターでPIC16F873に焼きこみ(コンフィグワード3F71)、テスト基板に挿して通電する。すると、PICの12ピンに接続されているLEDが1秒間隔で点滅する。ちなみに、mainルーチンを下のように書いても同じ結果が得られる。これは構造体を使用した例である。このあたりの解説は、文献2の4-12を参照するとよい。

プログラムソ−スの転用・転記不可。および個人の趣味を超えた使用を禁止する。性能は一切保証しない。
//----------------------------------------------------------------//
void main()
{
  unsigned int i ;

  init_port() ;

  while(1)
  {
    PC.B1 = 1 ;			// LED ON
    Wait (1000) ;
    PC.B1 = 0 ;			// LED OFF
    Wait (1000) ;
  }	// End of while loop
} 	// End of main program


<6-3-2> LEDの明るさをコントロール


 さて、LEDの単純な点滅は実現できた。しかし、単なる「点滅」であった。次は、LEDの明るさを変えてみたい。デジタルなのだから、本来信号は1か0である。LEDなら点灯しているか消灯しているかのどちらかのはずだ。しかし、PIC16F873に内蔵されているPWM(puls width modulation)機能を使うと、擬似的に明るさのコントロールが可能となる。詳細なメカニズムについては文献3のp213「パルス幅変調の原理」を参考にするとよい。少し詳しい設定方法はココ。なお、このプログラムはまだ最適化ができるが、「なにをやっているか?」を追うには、最適化したものよりはわかりやすいと思う。

void set_duty(unsigned int duty, char ch)


これは、PWM用のサブルーチンである。dutyには、0〜1023の値がセットできる。これが、デューティ比を決める値となる。chは2つあるPWMモジュールのどちらを使うかを指定するものである。値としては1か2である。この例では、0の時はLEDは完全に消えている。1になると時間比にして1/1023だけ点灯する。511を指定すると、約半分の時間点灯することになる。ただし、目には見えない速さでの点滅なので、あたかも「明るさが変わった」ように見えます。これがPWMで明るさをかえるカラクリです。ちなみに1023を指定すると、つきっぱなしになるので、最も明るい状態となりますね。

  CCP2CON = 0x0c ;		// CCP2 is PWM mode
  set_duty(0,2) ;		// Duty2 = 0
  PR2 = 0xff ;			// 
  T2CON = 0x7d ;		// PoS = 1:16, PreS = 1:4, ON


これはPWMを使うにあたり必要な初期設定です。CCP2CONを使って、「PWMを使うよー」ということをPICに知らせます。ちなみに、CCP1CONにも同じ値を設定すると、もう1つのPWMも使用可能になります。PWM時の周波数自体はタイマー2関連のレジスター設定で決定されますので、タイマー2周辺の初期化もしておきます。これを忘れますと、PWM機能は使えません。・・・ここでハタと・・・・そうです。PWMを使うと、タイマー2は他の用途に使えなくなります。回路の設計時にはここのところを注意しなければなりません。このあたりの設定値の考え方は、文献3の214ページから詳しく書いてあります。

プログラムソ−スの転用・転記不可。および個人の趣味を超えた使用を禁止する。性能は一切保証しない。
// Test Program 6-3-2 //

#procfreq 2097				// System Clock = 2.097MHz
#include <delays.h>
#include <datalib.h>
#include <P16F873.H>
#include <Strings.h>
//
# define BIT1 0x2
void  init_port();		// Init I/O Ports
void set_duty(unsigned int duty, char ch);
//
//------ init I/O-------------------------------------------------//
//
void  init_port()		// Init I/O Ports
{
  TRISA = 0x17 ;		// Port A xxOI OIII
  TRISB = 0x01 ;		// Port B OOOO OOOI
  TRISC = 0x89 ;		// Port C IOOO IOOI
  OPTION_REG = 0xc7 ;		// Pullup = off, T0 = OSC, PS -> TMR0
  INTCON = 0x00 ;		// All IRQ  OFF

  CCP2CON = 0x0c ;		// CCP2 is PWM mode
  set_duty(0,2) ;		// Duty2 = 0
  PR2 = 0xff ;			// 
  T2CON = 0x7d ;		// PoS = 1:16, PreS = 1:4, ON
}
//
//--- PWM subroutine --------------------------------------------//
//
void set_duty(unsigned int duty, char ch)
{
unsigned int temp1 ;
unsigned char temp2 ;

  temp1 = duty ;
  temp1 >>= 2 ;
  temp2 = temp1 & 0xff;
  if (ch == 1) 
    CCPR1L = temp2 ;
  else
    CCPR2L = temp2 ;

  temp1 = duty ;
  temp1 <<= 4 ;
  temp2 = temp1 | 0x0c ;
  if (ch == 1)
    CCP1CON = temp2 ;
  else
    CCP2CON = temp2 ;
}
//
//--- END of PWM subroutine---------------------------------------//
//
// ------------------------------------------------------------------
//
void main()
{
  unsigned int i ;

  init_port() ;

  while(1)
  {
    for (i=0; i<1024; i++) {
        set_duty(i, 2) ;		// Set Duty for Unit 2 
        Wait (1) ;
    }
  }	// End of while loop
}	// End of main program

 このソースをFED-CのVer7.0でコンパイルし、HEXファイルをライターでPIC16F873に焼きこみ(コンフィグワード3F71)、テスト基板に挿して通電する。すると、PICの12ピンに接続されているLEDがポンワァポンワァと明滅する。緑のLEDを使って蛍を真似ても面白いし、クリスマスツリー用のライトを作っても面白いと思う。ちなみに、このPWMの機能は、GMカウンターでは高圧用パルスの発生に使う予定である。

注意:これらのプログラムはあくまでも、ココの回路図どおりの配線がされている場合に使うことができます。

<参考資料>

1.Forest Electronic Developments PIC C Compiler Manual for Version 6.99x and 7 -April 2001
2. フォレスト エレクトリック デベロップメンツ PIC C コンパイラ Manual for version 2.0 -December 1999
3. 後閑哲也、PIC活用ガイドブック
4. PIC16F877のPDF説明資料(マイクロチップス社のホームページのもの)



Return