PIC16F18313の基本動作から応用プログラムまでを学びます。

ホーム
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
    
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
CCP PWM (Pulse Width Modulation)
2021-12-20

Capture/Compare/PWM(CCP)モジュールは、さまざまなイベントの時間を計測制御し、パルス幅変調(PWM)信号を生成する周辺機器です。ここではこのモジュールのPWM機能について説明します。

PWMモードでは、さまざまな周波数とデューティサイクルのパルス幅変調信号を生成できます。このデバイスには、2つの標準CCPモジュール(CCP1、CCP2)が搭載されています。

1 CCP/PWMクロック

PIC16F18313デバイスでは、各CCPモジュールが使用するタイマーソースは、8ビットタイマー(Timer2)になります。

*注意*
複数のCCPモジュールを備えたプログラムする時は、使用するレジスタ名に細心の注意を払うことが重要です。モジュールの頭字語の後に付けられた番号は、個別のモジュールを区別するために使用されます。たとえば、CCP1CONとCCP2CONは、2つの異なるCCPモジュールの同じ動作を制御します。
一般的に参照は、指定子「x」を使用して、モジュールを区別します。

2 PWMの概要

パルス幅変調(PWM)は、完全にオンの状態と完全にオフの状態をすばやく切り替えることにより、負荷に電力を供給する方式です。PWM信号は方形波で、信号の高い部分がオン状態、信号の低い部分がオフ状態です。パルス幅とも呼ばれる高い部分は、時間とともに変化し、ステップ数と定義されます。パルス幅を長くするステップ数が多いほど、負荷により多くの電力が供給されます。ステップ数を減らすと、パルス幅が短くなり、供給される電力が少なくなります。PWM周期は、1サイクルの持続時間、またはオン時間とオフ時間の合計として定義されます。

PWM分解能は、単一のPWM周期に存在できる最大ステップ数と定義します。より高い分解能により、パルス幅時間のより正確な制御が可能になり、負荷に適用される電力がさらに正確に制御されます。

デューティサイクルという用語は、オン時間とオフ時間の比率を表し、パーセンテージで表されます。ここで、0%は完全にオフで、100%は完全にオンです。低いデューティサイクルは、適用される電力が少ないことに対応し、高いデューティサイクルは、適用される電力が多いことを意味します。

図13a-3に、PWM信号の代表的な波形を示します。

3 標準PWM動作

標準のPWMモードは、最大10ビットの分解能でCCPxピンにパルス幅変調(PWM)信号を生成します。周期、デューティサイクル、および分解能は、次のレジスタによって制御されます。

図13a-4に、PWM動作の簡略化したブロック図を示します。

PPS機能で、出力をどのpinにするか指定します。
CCP1をRA4に指定するなら、
RA4PPS = 12;
      ↑CCP1 を示す

PWM 信号を出力するピンは、TRIS ビットを"0"出力に設定する必要があります。

PWM output PPS表記
CCP1 12
CCP2 13

*注意*
1. CCPRレジスタからの10ビットのアラインメントは、CCPxFMTビットによって決定されます。
2. 8ビットタイマーは、Foscによって生成された2ビットまたは内部プリスケーラーの2ビットと連結され、
 10ビットのタイムベースを作成します。

4 PWM動作の設定

標準PWM動作にCCPモジュールを構成する場合は、次の手順を実行します。

  1. 目的の出力ピンRxyPPSコントロールを使用して、信号源にCCPxを選択し、関連するTRISビットをセットしてCCPxピン出力ドライバーを無効にします。
  2. PR2にPWM周期値を書き込みます。
  3. CCPxCONに適切な値を書き込み、CCPモジュールをPWMモードに設定します。
  4. CCPRxLとCCPRxHビットにPWMデューティサイクル値を書き込み、CCPxCONのCCPxFMTビットを設定して適切なレジスタアライメントにします。
  5. Timer2を設定して起動します。
  6. PWM出力ピンを有効にします。

*注意*
最初のPWM出力で完全なデューティサイクルと周期を送信するには、上記の手順を設定シーケンスに含める必要があります。最初の出力で完全なPWM信号から開始することが重要でない場合は、ステップ6を無視できます。

5 PWM周期

PWM周期は、Timer2のPR2によって決定され、式13a-1の式を使用して計算できます。

式13a-1: PWM周期

  PWM周期 = (PR2 + 1) x 4 x Tosc

   PR2 : TMR2プリスケラー値
   Tosc : 1/Fosc

TMR2がPR2と一致すると、次の3つのイベントが次の増分クロックサイクルで発生します。

  • TMR2がクリア
  • CCPxピンがセット(例外:PWMデューティサイクル= 0%の場合、ピンはセットされません。)
  • PWMデューティサイクルが、CCPRxL/Hペアから10ビットバッファに転送
  • *注意*
    タイマーポストスケーラは、PWM周波数の決定には使用されません。

    6 PWMデューティサイクル

    PWMデューティサイクルは、CCPRxH:CCPRxLペアに10ビット値を書き込むことで指定します。10ビット値のアラインメントは、CCPxCONのCCPRxFMTビットによって決定します(図13a-5を参照)。デューティサイクル値は、CCPRxH:CCPRxLペアに、いつ書き込んでも構いませんが、PR2とTMR2が一致するまで、10ビットバッファに転送されません。

    図13a-5:PWM10ビットアライメントブロック図

    式13a-2: パルス幅

      パルス幅 = (CCPRxH:CCPRxLペア) x Tosc x(TMR2プリスケール値)

    式13a-3: デューティサイクル比

    デューティサイクル比 =  (CCPRxH:CCPRxLペア)
    4 x (PR2 + 1)

    CCPRxH:CCPRxLペアと2ビットの内部ラッチは、PWMデューティサイクルをダブルバッファリングするために使用されます。このダブルバッファリングは、グリッチのないPWM動作を提供します。

    8ビットタイマーTMR2は、2ビット内部システムクロック(Fosc)またはプリスケーラの2ビットのいずれかと連結されて、10ビットタイムベースを作成します。Timer2プリスケーラが1:1に設定されている場合は、システムクロックが使用されます。

    10ビットのタイムベースがCCPRxH:CCPRxLペアと一致すると、CCPxピンがクリアされます(図13a-4を参照)。

    6 PWM分解能

    ビット数で表されるPWM分解能は、単一のPWM周期に存在できるステップの最大数をで定義されます。たとえば、10ビットの解像度では1024個のステップになりますが、8ビットの解像度では256個のステップになります。PR2が255の場合、最大PWM分解能は10ビットです。分解能は、式13a-4に示すように、PR2レジスタ値の関数です。

    式13a-4: PWM分解能

    分解能 =  log {4(PRx + 1)}  bits
    log(2)

    *注意*
    パルス幅の値が周期よりも大きい場合、割り当てられたPWMピンは変更されません。

    PWM周波数と分解能の例
    Fosc = 20 MHz
    PWM周波数1.22 kHz4.88 kHz19.53 kHz78.12 kHz156.3 kHz208.3 kHz
    プリスケラ値1641111
    PR2値0xFF0xFF0xFF0x3F0x1F0x17
    最大解像度(bits)101010876.6
    Fosc = 8 MHz
    PWM周波数1.22 kHz4.90 kHz19.61 kHz76.92 kHz153.85 kHz200.0 kHz
    プリスケラ値1641111
    PR2値0x650x650x650x190x0C0x09
    最大解像度(bits)888655

    7 スリープモードでの操作

    スリープモードでは、TMR2はインクリメントせず、モジュールの状態は変化しません。CCPxピンの値も変化しません。デバイスがウェイクアップすると、TMR2は以前の状態から続行します。

    8 システムクロック周波数の変更

    PWM周波数は、システムクロック周波数をもとにしています。システムクロック周波数を変更すると、PWM周波数も変更されます。

    9 リセットの影響

    リセットを行うと、すべてのポートが強制的に入力モードになり、CCPレジスタがリセット状態になります。

    10 関連レジスタ

    レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
    CCPxCON CCPxEN - CCPxOUT CCPxFMT CCPxMODE<3:0>
    CCPRxL CCPRx<7:0>
    CCPRxH CCPRx<7:0>
    CCPTMRS C4TSEL<1:0> C3TSEL<1:0> C2TSEL<1:0> C1TSEL<1:0>
    RxyPPS - - - RxyPPS<4:0>
    レジスタ BIT 説明 1 0
    CCPxCON 7 CCPxEN CCPx モジュール ON/OFF ON OFF
    5 CCPxOUT CCPx 出力値 (Read only) 1 0
    4 CCPxFMT CCPx デュティーサイクル位置アライメント 上位 下位
    <3:0> CCPxMODE PWMモード : 1111
    CCPRxL <7:0> CCPRxL CCPRx デュティサイクル 下位 8 bit
    CCPRxH <7:0> CCPRxH CCPRx デュティサイクル 上位 8 bit
    CCPTMRS <7:6> C4TSEL CCPR4 連携タイマー   00 - 01 : TMR2, 10 : TMR4, 11 : TMR6
    <5:4> C3TSEL CCPR3 連携タイマー   00 - 01 : TMR2, 10 : TMR4, 11 : TMR6
    <3:2> C2TSEL CCPR2 連携タイマー   00 - 01 : TMR2, 10 : TMR4, 11 : TMR6
    <1:0> C1TSEL CCPR1 連携タイマー   00 - 01 : TMR2, 10 : TMR4, 11 : TMR6

    11 PWMのプログラム例

    <回路図>

    PushSWを押続けている間、PWMのデューティサイクルを連続的に変化させるプログラムです。 デューティサイクルの変化をLEDの明るさで確認することができます。

    <プログラム>

    /*************************************
     * File: PWM sample
     * System ClockはConfigで内部1MHzに設定
     * PushSWを押続けている間、PWMのデューティサイクルを連続的に+1し、
     *  LEDの明るさを連続的に変化させる。
     *  PushSWの接続される RA5は、Week Pull Upされている。
     *        LED RA4
     *        PushSW RA5
     *
     * PIC16F18313
     * Created on 2021-12-20
     **************************************/
    
    #include <xc.h>
    #define _XTAL_FREQ 1000000      // delay_ms(x) のための定義
    
    #define PushSW RA5
    
    #pragma config FEXTOSC = OFF,RSTOSC = HFINT1  // HFINTOSC (1MHz)
    #pragma config CLKOUTEN = OFF,CSWEN = OFF,FCMEN = OFF
    #pragma config MCLRE = ON,PWRTE = OFF,WDTE = OFF,LPBOREN = OFF
    #pragma config BOREN = OFF,BORV = LOW,PPS1WAY = OFF,STVREN = ON
    #pragma config DEBUG = OFF
    #pragma config WRT = OFF,LVP = ON,CP = OFF,CPD = OFF
    
    // ******************* main *************************************
    void main() {
        TRISA  = 0b101111;          // RA4 出力
        ANSELA = 0;                 // すべてデジタル
        WPUA   = 0b111111;          // 弱プルアップ
        RA4PPS = 12;                // CCP1をRA4に出力
    //------------ Initialize PWM ----------------------------------
        T2CON  = 0b00000100;         // Timer 2 PS1/1設定
        PR2    = 0xFF;               // Timer2 Period Register設定
        CCP1CON= 0b10011111;         // Duty 上位 PWM
        CCPR1H = 0x80;               // デュティサイクルを設定
        while(1){                    // 繰り返しループ
            if(!PushSW){             // PushSWが押されれば
                CCPR1H += 1;         // デュティサイクルを+1し更新
                __delay_ms(5);       // 遅延(更新の速度)
            }
        }
    }