端くれプログラマの備忘録 PIC,PICBASIC PRO [PIC] パルスジェネレータを作る

[PIC] パルスジェネレータを作る

開発中のボードを評価するために60~600Hzのパルスが必要になったので、PIC評価ボード「LAB-X1」でパルスを生成してみる。

パルス生成にハードウェアPWMを使う

パルス生成にはPICに搭載されているPWMを使う。手持ちのPIC16F877Aの場合、CCP1(PORTC.2)とCCP2(PORTC.1)の2チャンネルのPWMが利用可能。PBPのマニュアルによると、周波数の上限はクロックに関わらず32767Hz、下限はクロックに依存して下図の通り。

OSC 14-bit Enhanced 14-bit PIC18
4MHz 245Hz 62Hz 245Hz
8MHz 489Hz 123Hz 489Hz
10MHz 611Hz 153Hz 611Hz
12MHz 733Hz 184Hz 733Hz
16MHz 977Hz 245Hz 977Hz
20MHz 1221z 306Hz 1221Hz

この表によると、命令長14ビットのPIC16F877Aだと4MHzクロックでも下限は245Hzである。必要としている周波数は60~600Hzだけど、ハードの制限ならば仕方ない。245~600Hzのパルスを発生できるように要件を変更する。

サンプルコード

以下のサンプルコードでは、LAB-X1上のポテンショメータ(POT1)で周波数を245Hzから600Hzまで可変させて、チャンネル1のPWMで50%デューティのパルスを生成している。

' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
define LOADER_USED 1

' Define LCD pins
define LCD_DREG		PORTD
define LCD_DBIT		4
define LCD_RSREG	PORTE
define LCD_RSBIT	0
define LCD_EREG		PORTE
define LCD_EBIT		1

' Define ADCIN parameters
define ADC_BITS		8	' Set number of bits in result
define ADC_CLOCK	3	' Set clock source (3=rc)
define ADC_SAMPLEUS	50	' Set sampling time in uS

adval	var byte
freq	var word
curr	var word

wh      var word
wl      var word

init:
    TRISA = %11111111	' Set PORTA to all input
    ADCON1 = %00000100	' Set PORTA analog
    pause 500		' Wait .5 second

main:
    freq = 0
    do
        adcin 0, adval	' Read the first ADC channel (0-255)
        curr = adval
        curr = 245 + (curr * 14) / 10

        if (curr != freq) then		' If frequency updated
            freq = curr			' Set new frequency
            lcdout $fe, 1		' Clear the LCD
            lcdout "freq=", #freq	' Display new frequency
            hpwm 2, 127, freq		' Apply new frequency
        endif

        ' FOR DEBUG
        ' Measure pulse width for sure (jumper C1-B6)
        ' Pulse width is returned in 10us increments if 4MHz OSC

        pulsin PORTB.6, 1, wh		' Read pulse width (H)'
        pulsin PORTB.6, 0, wl		' Read pulse width (L)
        lcdout $fe, $c0, "H=", #wh, " L=", #wl

        pause 200
    loop

end

動作確認のため、生成したパルス(PORTC.1)を別ポート(PORTB.6)に入力してパルス幅を測定してLCDに表示させてみた。パルス幅測定用の組み込みルーチンPULSINは、4MHz OSCだと10マイクロ秒単位のパルス幅を読み取って返す。読み取ったパルス幅から逆算すれば、指定した周波数のパルスが生成できているかどうか確認できるはず。