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

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


半固定抵抗とLEDを配線し、半固定抵抗の値からLEDの明るさを可変させます。
LEDはPWMを利用して明るさを可変させますが、16F1705にはPWMを出力する機能としてCCP機能
PULSE-WIDTH MODULATION(PWM)専用出力機能の二つが有ります。

こちらのHPサイト「合同会社パレットソフト」さんのページにLEDとPWM制御について 解りやすく書いて有ります、”LEDの輝度調整”の項を参考にして下さい。

《CCP機能でPWM出力》

CCP機能はPWM出力の他に、外部イベントの継続時間を計測する"キャプチャー機能"と
あらかじめ設定した時間が経過した時点で外部イベントをトリガする"コンペア機能"が有ります。

PICピン構成1

使用するピン番号は1番(VDD)と14番(VSS)と8番(CCP1)と7番(AN7)です。
7番ピンがアナログ入力で8番ピンがアナログ出力(PWM)です。
16F1705はCCP1を他のピン(RA3以外)にも変更が可能ですがここでは8番(RC2)に割り当てています。
尚、CCP1の他にCCP2も出力可能です。

実態回路図  @まずは、左図画面の様に配線しましょう。
  PICの1番ピンに電源+5V、14番ピンに電源GND(-)側、
  8番ピンにLEDの足が長い方(アノード)を接続します。
  又、7番ピンに半固定抵抗の中央の足を接続します。

  半固定抵抗は10KΩを使用で、だいたい60〜530位で
  読み込まれます。
  ツマミを右に回せばLEDの明るさは暗くなり、
  左に回せば明るくなります。

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


B下記がプログラムソースです、
 MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。
 MPLAB Xにてプロジェクトを作成して新規ファイルにコピーペーストして貼り付けて下さい。
 プログラムソースをダウンロードしてプロジェクトに取込む事も出来ます。
---------------------------------------------------------------------
#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      // 外部リセット信号は使用せずにデジタル入力(RA3)ピンとする(OFF)
#pragma config CP       = OFF      // プログラムメモリーを保護しない(OFF)
#pragma config BOREN    = ON       // 電源電圧降下常時監視機能ON(ON)
#pragma config CLKOUTEN = OFF      // CLKOUTピンをRA4ピンで使用する(OFF)
#pragma config IESO     = OFF      // 外部・内部クロックの切替えでの起動はなし(OFF)
#pragma config FCMEN    = OFF      // 外部クロック監視しない(OFF)
// コンフィギュレーション2の設定
#pragma config WRT      = OFF      // Flashメモリーを保護しない(OFF)
#pragma config PPS1WAY  = OFF      // ロック解除シーケンスを実行すれば何度でもPPSLOCKをセット/クリアできる
#pragma config ZCDDIS   = ON       // ゼロクロス検出回路は無効とする(ON)
#pragma config PLLEN    = OFF      // 動作クロックを32MHzでは動作させない(OFF)
#pragma config STVREN   = ON       // スタックがオーバフローやアンダーフローしたらリセットをする(ON)
#pragma config BORV     = HI       // 電源電圧降下常時監視電圧(2.5V)設定(HI)
#pragma config LPBOR    = OFF      // 低消費電力ブラウンアウトリセット(LPBOR_OFF)
#pragma config LVP      = OFF      // 低電圧プログラミング機能使用しない(OFF)

// アナログ値の入力処理
unsigned int adconv()
{
     unsigned int temp;

     GO_nDONE = 1 ;         // PICにアナログ値読取り開始を指示
     while(GO_nDONE) ;      // PICが読取り完了するまで待つ
     temp = ADRESH ;        // PICは読取った値をADRESHとADRESLのレジスターにセットする
     temp = ( temp << 8 ) | ADRESL ;  // 10ビットの分解能力です

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

     OSCCON = 0b01110010 ;  // 内部クロックは8MHzとする
     ANSELA = 0b00000000 ;  // AN0-AN3は使用しない全てデジタルI/Oとする
     ANSELC = 0b00001000 ;  // アナログはAN7を使用し、AN4-AN6は使用しないデジタルI/Oとする
     TRISA  = 0b00000000 ;  // ピン(RA)は全て出力に割当てる(RA3は入力専用)
     TRISC  = 0b00001000 ;  // RC3(AN7)だけ入力その他のピンは出力に割当てる
     PORTA  = 0b00000000 ;  // RA出力ピンの初期化(全てLOWにする)
     PORTC  = 0b00000000 ;  // RC出力ピンの初期化(全てLOWにする)

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

     // CCP1の設定
     RC2PPS  = 0b00001100 ; // RC2(8)ピンをCCP1出力に割り当てる
     CCP1CON = 0b00001100 ; // PWM機能を使用する
     T2CON   = 0b00000010 ; // TMR2プリスケーラ値を16倍に設定
     CCPR1L  = 0 ;          // デューティ値は0で初期化
     CCPR1H  = 0 ;
     TMR2    = 0 ;          // タイマー2カウンターを初期化
     PR2     = 124 ;        // PWMの周期を設定(1000Hzで設定)
     TMR2ON  = 1 ;          // TMR2(PWM)スタート

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

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

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

プログラムについて

adconv( )
 アナログ(半固定抵抗)の値を読み取ります、値は0〜1023(60-530)の範囲です。

アナログI/O
 アナログピンの設定は下記のレジスターにて設定します。
 ANSELA = 0b00000000 ; アナログ入力を行うピンの指定をします
               赤数字右からAN0(13ピン),AN1(12ピン),AN2(11ピン),AN3(3ピン)の順
               1でアナログ、0でデジタル、この設定例は全てデジタルで使用です。

 ANSELC = 0b00001000 ; アナログ入力を行うピンの指定をします
               赤数字右からAN4(10ピン),AN5(9ピン),AN6(8ピン),AN7(7ピン)の順
               この設定例はAN7をアナログで使用、その他はデジタルで使用です。

 指定したAN7のアナログピンを入力に指定するには下記のレジスターにて設定します。
 TRISC = 0b00001000 ; この設定はAN7(RC3)のみ入力に設定するです。
               1で入力、0で出力、右からAN4,AN5,AN6,AN7

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

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

CCP1機能設定
 CCPのPWMを使用する為には以下の設定が必要です、
 この設定は1KHzの周波数で、PWMで制御する設定です。
 少し詳しい設定等の説明は、16F1827(CCP3)での記述ですがこちらを参考にして下さい。
 RC2PPS  = 0b00001100 ;    // RC2(8)ピンをCCP1出力に割り当てる
 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 ; この行でPWMのデューティ値を変更しています。
 CCP2を利用する場合は、レジスター"CCP1"の文字を"CCP2"に書き換えます。
 又、ここではTimer2を利用していますがTimer4/6も利用出来ます。(下記参照)
 

《PULSE-WIDTH MODULATION(PWM)》

今度はPWM専用のモジュールが16F1705には有るのでそれを使って見ます。
CCP機能からPWMのモジュールを取り出した様なものです。
PWMはPWM3OUTとPWM4OUTから出力出来ます。

PICピン構成2  左図はピン構成ですが、実験回路は上記と同じです。

 上記では8番ピンRC2をCCP1に割り当てていましたが、
 今度はPWM3OUTに割り付けます。
 PWM3OUTも他のピン(RA3以外)に変更が可能です


下記がプログラムソースです。
 MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。
 MPLAB Xにてプロジェクトを作成して新規ファイルにコピーペーストして貼り付けて下さい。
 プログラムソースをダウンロードしてプロジェクトに取込む事も出来ます。
---------------------------------------------------------------------
#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      // 外部リセット信号は使用せずにデジタル入力(RA3)ピンとする(OFF)
#pragma config CP       = OFF      // プログラムメモリーを保護しない(OFF)
#pragma config BOREN    = ON       // 電源電圧降下常時監視機能ON(ON)
#pragma config CLKOUTEN = OFF      // CLKOUTピンをRA4ピンで使用する(OFF)
#pragma config IESO     = OFF      // 外部・内部クロックの切替えでの起動はなし(OFF)
#pragma config FCMEN    = OFF      // 外部クロック監視しない(OFF)
// コンフィギュレーション2の設定
#pragma config WRT      = OFF      // Flashメモリーを保護しない(OFF)
#pragma config PPS1WAY  = OFF      // ロック解除シーケンスを実行すれば何度でもPPSLOCKをセット/クリアできる
#pragma config ZCDDIS   = ON       // ゼロクロス検出回路は無効とする(ON)
#pragma config PLLEN    = OFF      // 動作クロックを32MHzでは動作させない(OFF)
#pragma config STVREN   = ON       // スタックがオーバフローやアンダーフローしたらリセットをする(ON)
#pragma config BORV     = HI       // 電源電圧降下常時監視電圧(2.5V)設定(HI)
#pragma config LPBOR    = OFF      // 低消費電力ブラウンアウトリセット(LPBOR_OFF)
#pragma config LVP      = OFF      // 低電圧プログラミング機能使用しない(OFF)

// アナログ値の入力処理
unsigned int adconv()
{
     unsigned int temp;

     GO_nDONE = 1 ;         // PICにアナログ値読取り開始を指示
     while(GO_nDONE) ;      // PICが読取り完了するまで待つ
     temp = ADRESH ;        // PICは読取った値をADRESHとADRESLのレジスターにセットする
     temp = ( temp << 8 ) | ADRESL ;  // 10ビットの分解能力です

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

     OSCCON = 0b01110010 ;  // 内部クロックは8MHzとする
     ANSELA = 0b00000000 ;  // AN0-AN3は使用しない全てデジタルI/Oとする
     ANSELC = 0b00001000 ;  // アナログはAN7を使用し、AN4-AN6は使用しないデジタルI/Oとする
     TRISA  = 0b00000000 ;  // ピン(RA)は全て出力に割当てる(RA3は入力専用)
     TRISC  = 0b00001000 ;  // RC3(AN7)だけ入力その他のピンは出力に割当てる
     PORTA  = 0b00000000 ;  // RA出力ピンの初期化(全てLOWにする)
     PORTC  = 0b00000000 ;  // RC出力ピンの初期化(全てLOWにする)

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

     // PWM3の設定
     RC2PPS  = 0b00001110 ; // RC2(8)ピンをPWM3OUT出力に割り当てる
     PWM3CON = 0b11000000 ; // PWM3機能を使用する(output is active-high)
     PWM3DCH = 0 ;          // デューティ値は0で初期化
     PWM3DCL = 0 ;
     T2CON   = 0b00000010 ; // TMR2プリスケーラ値を16倍に設定
     TMR2    = 0 ;          // タイマー2カウンターを初期化
     PR2     = 124 ;        // PWMの周期を設定(1000Hzで設定)
     TMR2ON  = 1 ;          // TMR2(PWM)スタート

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

PWM3機能設定
 PWMを使用する為には以下の設定が必要です、
 この設定は1KHzの周波数で、PWM制御する設定です。
 少し詳しい設定等の説明は、12F1501(PWM1OUT)での記述ですがこちらを参考にして下さい。
 RC2PPS  = 0b00001110 ;    // RC2(8)ピンをPWM3OUT出力に割り当てる
 PWM3CON = 0b11000000 ;    // PWM3機能を使用する(output is active-high)
 PWM3DCL = 0 ;             // デューティ値は0で初期化
 PWM3DCH = 0 ;
 T2CON   = 0b00000010 ;    // TMR2プリスケーラ値を16倍に設定
 TMR2    = 0 ;             // タイマー2カウンターを初期化
 PR2     = 124 ;           // PWMの周期を設定(1000Hzで設定)
 TMR2ON  = 1 ;             // TMR2(PWM)スタート

 PWM3DCH = num/4 ; この行でPWMのデューティ値を変更しています。
 PWM4を利用する場合は、レジスター"PWM3"の文字を"PWM4"に書き換えます。
 又、ここではTimer2を利用していますがTimer4/6も利用出来ます。(下記参照)

 
PWMタイマーの選択設定
 CCPTMRS = 0b00000000 ; この設定がデフォルトTimer2を使うです
               赤色部分でPWM4、緑色部分でPWM3、青色部分でCCP2、黄色部分でCCP1
               とそれぞれの設定に割り当てられています。
               10:Timer6 01:Timer4 00:Timer2
               例えば、"00100000"ならPWM3でTimer6を使い他はTimer2となります。

 ハーフブリッジ/フルブリッジ機能やステアリング制御(相補PWM出力)機能等は、
   相補出力ジェネレータ(COG)モジュールで行うようです。

《その他》

今回は7番ピン(RC3)のAN7、8番ピン(RC2)にCCP1とPWM3OUTを割り当てて実験を行いましたが
他のピンを使用する場合は下記の表を参照して下さい。
ポートA
ピン番号 11 12 13
デジタル入出力ビット名 RA5 RA4 RA3 RA2 RA1 RA0
アナログ入力ピン名 AN3 AN2 AN1 AN0
CCP/PWM割付レジスタ名 RA5PPS RA4PPS RA2PPS RA1PPS RA0PPS

ポートC
ピン番号 10
デジタル入出力ビット名 RC5 RC4 RC3 RC2 RC1 RC0
アナログ入力ピン名 AN7 AN6 AN5 AN4
CCP/PWM割付レジスタ名 RC5PPS RC4PPS RC3PPS RC2PPS RC1PPS RC0PPS

 CCP1とPWM3OUTを他のピンに割り当てる場合は、プログラム中のRC2PPS名を他のピンの
   割り付けレジスタ名に変更して下さい。




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