可変抵抗のツマミを回してLEDの明るさを可変します(2/2)

〔PICの動かせ方入門に戻る〕


前の頁では16F1827の標準CCP機能で、CCP3とCCP4を使ってPWM出力を行いました。
16F1827には他に拡張型CCP機能でECCP(ECCP1/ECCP2)が有ります。
このECCPのPWMモードには、シングルPWM・ハーフブリッジPWM・フルブリッジPWMが有り、
ハーフブリッジ/フルブリッジ機能はモータ等を回すのに使います、 ここではシングルPWMを利用して、
LEDの明るさを可変させてみたいと思います。

VRtoLED14
 シングルPWM機能とは、
 PICの内部で生成された
 PWM(CCP1/CCP2)信号はピンの
 P1A/P1B/P1C/P1D(P2A/P2B)に
 それぞれ接続されています、
 なので、同じPWMを同時に4つのピンに
 出力が出来ますが、
 PSTRxCONレジスターにてそれぞれの
 ピン出力をON/OFF出来ます。
 これをPWMステアリング制御と言います

CCP1(P1A/P1B/P1C/P1D)をフルブリッジ
PWMと言い、CCP2(P2A/P2B)をハーフブリッジPWMと言います。


この記事ではCCP2からPWM信号を作りP2A/CCP2の12番ピンから出力をしてみます。
(P2Bからは出力しません、OFFです、デジタル端子として使用可能です。)

VRtoLED11

今回使用するピン番号は14番(VDD)と5番(VSS)と12番(CCP2)と9番(AN9)です。
9番ピンがアナログ入力で12番ピンがアナログ出力(PWM)です。

@まずは、下記図画面の様に配線しましょう。
 PICの14番ピンに電源+5V、5番ピンに電源GND(-)側、12番ピンにLEDの足が長い方を接続します。
 また、9番ピンに半固定抵抗の中央の足を接続します。

VRtoLED12 VRtoLED13

AMPLAB X(v2.15)を起動させます。

B下記がプログラムソースです、
  MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。
  プロジェクトを作成して新規ファイルにコピーペーストして貼り付けて下さい。
  プログラムソースをダウンロードしてプロジェクトに取込む事も出来ます。 *2)
---------------------------------------------------------------------
#include <xc.h>

#define _XTAL_FREQ 8000000    //  delay用に必要(クロック8MHzを指定)

// コンフィギュレーション1の設定
#pragma config FOSC = INTOSC    // 内部クロックを使用する(INTOSC)
#pragma config WDTE = OFF       // ウオッチドッグタイマー無し(OFF)
#pragma config PWRTE = ON       // 電源ONから64ms後にプログラムを開始する(ON)
#pragma config MCLRE = OFF      // 外部リセット信号は使用せずにデジタル入力(RA5)ピンとする(OFF)
#pragma config CP = OFF         // プログラムメモリーを保護しない(OFF)
#pragma config CPD = OFF        // データメモリーを保護しない(OFF)
#pragma config BOREN = ON       // 電源電圧降下常時監視機能ON(ON)
#pragma config CLKOUTEN = OFF   // CLKOUTピンをRA6ピンで使用する(OFF)
#pragma config IESO = OFF       // 外部・内部クロックの切替えでの起動はなし(OFF)
#pragma config FCMEN = OFF      // 外部クロック監視しない(FCMEN_OFF)

// コンフィギュレーション2の設定
#pragma config WRT = OFF        // Flashメモリーを保護しない(OFF)
#pragma config PLLEN = OFF      // 動作クロックを32MHzでは動作させない(OFF)
#pragma config STVREN = ON      // スタックがオーバフローやアンダーフローしたらリセットをする(ON)
#pragma config BORV = HI        // 電源電圧降下常時監視電圧(2.5V)設定(HI)
#pragma config LVP = OFF        // 低電圧プログラミング機能使用しない(OFF)


// アナログ値の変換と読込み処理
unsigned int adconv()
{
     unsigned int temp;

     GO_nDONE = 1 ;	      // アナログ値読取り開始指示
     while(GO_nDONE) ;        // 読取り完了まで待つ
     temp = ADRESH ;
     temp = ( temp << 8 ) | ADRESL ;

     return temp ;
}
// メインの処理関数
void main()
{
     unsigned int num ;

     OSCCON = 0b01110010 ;    // 内部クロックは8MHzとする
     ANSELA = 0b00000000 ;    // AN0-AN4は使用しない全てデジタルI/Oとする
     ANSELB = 0b00001000 ;    // AN5-AN11はAN9のみアナログで使用し他はデジタルI/Oとする
     TRISA  = 0b00000000 ;    // ピン(RA)は全て出力に割当てる(RA5は入力のみとなる)
     TRISB  = 0b00001000 ;    // ピン(RB)はRB3(AN9)のみ入力で他は出力に割当てる
     PORTA  = 0b00000000 ;    // RA出力ピンの初期化(全てLOWにする)
     PORTB  = 0b00000000 ;    // RB出力ピンの初期化(全てLOWにする)

     ADCON1 = 0b10010000 ;    // 読取値は右寄せ、A/D変換クロックはFOSC/8、VDDをリファレンスとする
     ADCON0 = 0b00100101 ;    // アナログ変換情報設定(AN9から読込む)
     __delay_us(5) ;          // アナログ変換情報が設定されるまでとりあえず待つ

     CCP2CON = 0b00001100 ;   // PWM機能(シングル出力)を使用する
     CCP2SEL = 0 ;            // CCP2ピンは12番ピンのRB6を使用する
     PSTR2CON= 0b00000001 ;   // P2Aの12番ピンのみPWM出力する、P2BはOFF
     CCPTMRS = 0b00000100 ;   // ECCP2機能はTimer4を使用する
     T4CON   = 0b00000010 ;   // TMR4プリスケーラ値を16倍に設定
     CCPR2L  = 0 ;            // デューティ値は0で初期化
     CCPR2H  = 0 ;
     TMR4    = 0 ;            // タイマー4カウンターを初期化
     PR4     = 124 ;          // PWMの周期を設定(1000Hzで設定)
     TMR4ON  = 1 ;            // TMR4(PWM)スタート

     while(1) {
          num = adconv() ;    // 9番ピン(AN9)から半固定抵抗の値を読み込む
          CCPR2L = num/4 ;    // アナログ値からのデータでデューティ値を設定
     }
}
---------------------------------------------------------------------

CコンパイルPIC書き込みを実行して下さい。

DPICをブレッドボードに取付けて、抵抗のツマミを回して下さいLEDの明るさが変わると思います。

《やさしく解説》

LEDについて

VRtoLED4

LEDには極性が有ります、
足の長いアノード側を2番ピンの方に、足の短いカソード側を電流制限抵抗の方に接続します。
また、LEDには流せる電圧と電流が決まっています、必ず電流制限抵抗を付けましょう。

電流制限抵抗
 LEDの順方向電流(IF)と順方向電圧(VF)がデータシート等に書いてあると思います、
 例えばIFが10mAで、VFが2.5Vで、picのアナログ出力が5Vとすると、
 (pic出力−順方向電圧)÷ 順方向電流 = 電流制限抵抗値
 よって、(5V - 2.5V) ÷ 0.010A = 250Ω(250Ωは無いので240Ωか270Ωを使います)
 10mAは0.010AというふうにAに変換して計算します。

 だいたい120Ω〜680Ωのあたりだと思います。
 LEDは5mAくらいで使った方が目に優しいでしょう、で470Ω?
 また、抵抗はLEDのアノード側とカソード側のどちら側に接続してもOKです。

 注意) PICの出力は20mA程しか流せません、これ以上のLED電流を流す場合は
     PICの出力をトランジスタで一旦受けてからLEDをつながないといけません。
     マイコン出力をトランジスタで一旦受ける場合はこちらを参考にして下さい。

半固定抵抗について

アナログ入力は電圧の0〜5Vを0〜1023の値に変換して読み込みます。
半固定抵抗は今回10kΩを使用で、だいたい60〜530位で読み込まれます。

ツマミを右に回せばLEDの明るさは暗くなり、左に回せば明るくなります。
また、半固定抵抗の配線を5V(赤線)とGND(黒線)で入れ替えると、
右に回しでLEDの明るさは明るくなり逆になります。
半固定抵抗の20kΩ辺りを取付ければもっとハッキリ変化が解るでしょう。

プログラムについて

プログラムソースのコメントを読んでもらえば大体何をしているのか分かると思います。

while(1)
 main()の中の処理は1回実行すると終了します、
 だからwhile(1)の、{ }の中に処理を書き込めば無限に繰り返します。
 もしwhile(1)を記述しないとプログラムはすぐ終了し、ツマミを回してもLEDは変化しません。

__delay_us(value)
 プログラムを指定した時間だけ一時停止します。
 value:停止したい時間を指定します、単位はマイクロ秒です。
 クロック8MHz動作では98560us25231232usまでしか指定出来ません。
 __delay_msなら98ms25231msまでです。 *2)

adconv()
 アナログの値を読み取ります、値は0〜1023の範囲です。

アナログI/O
 アナログピンの設定は下記のレジスターにて設定します。
 ANSELA = 0b00000000 ; アナログ入力を行うピンA(RA0-RA4)の指定をします
               赤数字右からAN0(17ピン),AN1(18ピン),AN2(1ピン),AN3(2ピン),AN4(3ピン)の順
               1でアナログ、0でデジタル、この設定はAN0-AN4を全てデジタルI/Oに割当
 ANSELB = 0b00001000 ; アナログ入力を行うピンB(RB1-RB7)の指定をします
               赤数字右からAN11(7ピン),AN10(8ピン),AN9(9ピン),AN8(10ピン),AN7(11ピン),
               AN5(12ピン),AN6(13ピン)の順
               1でアナログ、0でデジタル、この設定はAN9をアナログにするです

 次にピンの入出力を設定します。
 TRISA = 0b00000000 ; この設定はAN0-AN4全て出力に設定するです
               1で入力、0で出力、右からAN0,AN1,AN2,AN3,AN4、残りはデジタルです。
 TRISB = 0b00001000 ; この設定はAN9のみ入力に設定するです
               右からAN11,AN10,AN9,AN8,AN7,AN5,AN6、残りはデジタルです。

アナログ変換情報設定
 ADCON0 = 0b00100101 ; この設定でAN9から読込めと指示しています
               他のAN9以外から読込みたい場合は、赤数字の部分を変更します。
               AN0=00000,AN1=00001,AN2=00010,AN3=00011,AN4=00100,AN5=00101,
               AN6=00110,AN7=00111,AN8=01000,AN9=01001,AN10=01010,AN11=01011
               と変更して下さい。
               赤数字の部分以外の設定は今回このまま使用して下さい。
               また、ADCON0の設定には5usほどかかります、delayを入れておきましょう。

 ADCON1 = 0b10010000 ;
               緑数字部分でA/D変換時のリファレンス電圧をどうするかの設定です。
               00:VDDのPIC電圧を使用する 10:2番ピン接続の外部VREFを使用する。
               11:PIC内蔵の固定電圧を使用する。
               赤数字部分でA/D変換を行う速度のクロックを設定します。
               000:FOSC/2 001:FOSC/8  010:FOSC/32
               100:FOSC/4 101:FOSC/16 110:FOSC/64
               また、それ以外の数字部分の設定は今回このまま使用して下さい。

PWM機能設定
 PWMを使用する為には以下の設定が必要です、
 この設定は1KHzの周波数で、PWM制御する設定です。
 LEDならこの位で良かろうと、適当なんですが、
 少し詳しい説明はこちら(標準CCP機能での記述ですが基本は同じです)を参照して下さい。

 出力ピンを決める
 CCP2の出力ピンは12番と16番ピンが有ります。
 CCP2SEL = 0 ;  0:12番ピン 1:16番ピン
 尚、CCP1の出力ピンはCCP1SELを使い、0:9番ピン 1:6番ピン となります。

 PSTR2CON = 0b00000001 ; この設定でCCP2のPWM出力はP2Aのみ出力、P2BはOFF。
                 1:ON 0:OFF
                 右からそれぞれP2A/P2Bの順です。
 尚、CCP1のPSTR1CONのばあいは
 PSTR1CON = 0b00000000 ; 右からP1A/P1B/P1C/P1Dの順です。
 (また、P2B/P1C/P1Dのピン選択は下記の表を参照下さい。)

 標準CCPと同じように、ECCP1とECCP2もそれぞれにTimer2/4/6の何れかを使用します。
 その設定はCCPTMRSレジスターにて行います。
 CCPTMRS = 0b00000100 ;
                赤数字部分がCCP2用設定で緑数字部分がCCP1用設定の場所です。
                Timer2=00 , Timer4=01 , Timer6=10 この設定でCCP2はTimer4を使用です。

 次の記述はCCP2でTimer4を使用する場合です。
 CCP2CON = 0b00001100 ;    // PWM機能(シングル出力)を使用する
 T4CON   = 0b00000010 ;    // TMR4プリスケーラ値を16倍に設定
 CCPR2L  = 0 ;             // デューティ値は0で初期化
 CCPR2H  = 0 ;
 TMR4    = 0 ;             // タイマー4カウンターを初期化
 PR4     = 124 ;           // PWMの周期を設定(1000Hzで設定)
 TMR4ON  = 1 ;             // TMR4(PWM)スタート

  CCPR2L = num/4 ;   // アナログ値からのデータでデューティ値を設定
 尚、CCP1でTimer2を使用する場合は
 CCPTMRS = 0b00000000 ;    // CCP1機能はTimer2を使用する
 CCP1CON = 0b00001100 ;    // PWM機能(シングル出力)を使用する
 T2CON   = 0b00000010 ;    // TMR2プリスケーラ値を16倍に設定
 CCPR1L  = 0 ;             // デューティ値は0で初期化
 CCPR1H  = 0 ;
 TMR2    = 0 ;             // タイマー2カウンターを初期化
 PR2     = 124 ;           // PWMの周期を設定(1000Hzで設定)
 TMR2ON  = 1 ;             // TMR2(PWM)スタート

  CCPR1L = num/4 ;   // アナログ値からのデータでデューティ値を設定
 なのでぇ、タイマー2/4/6が有るのでECCP1/ECCP2/CCP3/CCP4から最高3個まで同時にPWMを
 出力可能ですね。

相補PWM出力制御 *1)
memo3  左図の様にP2AピンがHIGH時はP2BピンはLOWを
 出力する様に反転させます(差動出力)、これを
 相補PWM出力制御と言います。

 下がP2AからPWMを出力する場合でしたが、
 CCP2CON = 0b00001100 ;   // PWM機能(シングル出力)を使用する
 CCP2SEL = 0 ;            // CCP2ピンは12番ピンのRB6を使用する
 PSTR2CON= 0b00000001 ;   // P2Aの12番ピンのみPWM出力する、P2BはOFF

 P2A(アクティブHIGH)とP2B(アクティブLOW)から相補PWMを出力する場合は、
 CCP2CON = 0b00001101 ;   // PWM機能(シングル出力:相補を行う)を使用する
 CCP2SEL = 0 ;            // CCP2(P2A)ピンは12番ピンのRB6を使用する
 P2BSEL  = 0 ;            // P2Bは13番ピンのRB7を使用する
 PSTR2CON= 0b00000011 ;   // P2AをPWM出力する、P2Bは反転出力
 CCP2CON = 0b00001101;
               赤色部分でPWMの出力パターンを設定します。
               1100:P1A、P1C をアクティブHigh、P1B、P1D をアクティブHigh
               1101:P1A、P1C をアクティブHigh、P1B、P1D をアクティブLow
               1110:P1A、P1C をアクティブLow、P1B、P1D をアクティブHigh
               1111:P1A、P1C をアクティブLow、P1B、P1D をアクティブLow

 ※ 但し、ECCP1/ECCP2の拡張型CCP機能のみ相補PWMを出力可能です。

《その他》

今回は9番・12番ピンを使用しましたが他のピンを使用する場合は下記の表を参照して下さい。
また、4番ピンRA5は入力しか出来ません、出力不可です。
ポートA
ピン番号 16 15 18 17
デジタル入出力ビット名 RA7 RA6 RA5 RA4 RA3 RA2 RA1 RA0
アナログ入力ピン名 AN4 AN3 AN2 AN1 AN0
PWM 出力ピン名 CCP2
P1C/P2A P1D/P2B

ポートB
ピン番号 13 12 11 10
デジタル入出力ビット名 RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
アナログ入力ピン名 AN6 AN5 AN7 AN8 AN9 AN10 AN11
PWM 出力ピン名 CCP2 CCP1 CCP1
P1D/P2B P1C/ P2A P1B P1A P1A
P2Bの切替えは、P2BSEL=0:13番ピン 1:15番ピン
P1Dの切替えは、P1DSEL=0:13番ピン 1:15番ピン
P1Cの切替えは、P1CSEL=0:12番ピン 1:16番ピン



MPLAB X用に記事変更(*2) 2015/10/07
一部追記(*1) 2014/11/24


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2015 Shigehiro Kimura All Rights Reserved.