meideru blog

家電メーカーで働いているmeideruのブログです。主に技術系・ガジェット系の話を書いています。

PICマイコン(12F683)でLEDをPWM制御

      2018/10/20

PICマイコンの12F683を使ってLEDをPWM制御してみたので、備忘録も兼ねてこのブログに書きたいと思います(^O^)/

方法

【12F683のデータシート】
データシート

【12F683の各レジスタを解説しているサイト(紹介させていただきます・・・)】
PIC12F683のピン配置とメモリ構造

時折出てくる具体例は全てXC8で記してあります。

使用するレジスタ

12F683でPWM制御するために使うレジスタは以下の通り。

  • PR2レジスタ
  • T2CONレジスタ
  • CCP1CONレジスタ
  • CCPR1Lレジスタ

@CCP PWM OUTPUT(データシートより)
CCP PWM OUTPUT

以下でそれぞれ4つのレジスタについて説明します。各レジスタのビットの解説は省略してあるので、上でリンクしてあるサイトを参考にしてください。

PR2レジスタ

PR2レジスタはPWMの周期(データシートのCCP PWM OUTPUTのPeriod)を決定するレジスタです。

@PWM PERIOD(データシートより)
PWM PERIOD

Toscは周期のことでPICのクロック数の逆数で求められます。

MR2 Prescale Valueはプリスケーラのことです。プリスケールとは簡単に説明するとタイマのカウントを増やすためのものです。あとで説明するT2CONレジスタで設定します。

PWMの周期はPR2を代入するだけで決定できます。例えば、クロック数4MHz、PR2 = 200、プリスケーラは1として計算してみましょう。
PWM Period = (200 + 1) * 4 * 1 / (4 * 10^6) * 1 = 2.01 * 10^-4 となります。

T2CONレジスタ

T2CONレジスタはTMR2のポストスケール、TMR2の有効無効、TMR2のプリスケールを決定するレジスタです。(T2CONレジスタの各ビットについては上のサイトを参考にしてください。)

TMR2はタイマのことで、PWMを実行するためには使う必要があります。

例えば、ポストスケールを1:1、TMR2を有効、プリスケール1:1と設定するには
T2CON = 0b0000100; となります。

CCP1CONレジスタ

CCP1CONレジスタはデューティの下位2ビット(上位8ビットはCCPR1Lで設定)、CCPモードを設定するためのレジスタです。

デューティは10ビットで設定されますが、12F683の特殊レジスタSFRは8ビットであるため入りきりません。なので、デューティの上位8ビットはCCPR1Lに、下位2ビットはCCP1CONに設定します。

CCPR1Lレジスタ

1つ上で説明した通り、CCPR1Lレジスタはデューティの上位8ビットを設定します。

@PULSE WIDTH(データシートより)
PULSE WIDTH

上の画像はデューティの長さの計算式です。

CCPR1L:CCP1CON<5:4>というのは「CCPR1LとCCP1CONの4ビット目、5ビット目を順に並べた値」という意味です。つまりデューティの10ビットを表します。

@DUTY CYCLE RATIO(データシートより)
DUTY SYCLE RATIO

上の画像はデューティ比の計算式です。

 

上の2つのデータシートに基づいて具体例をあげます。

PR2が200の時、デューティ比を10としたい場合は
CCP = 0.10 * 4 * (200 + 1) = 80.4 となります。

つまりCCPを80として上位8ビットをCCPR1Lに、下位2ビットをCCPR1Lに入れます。

サンプルコード

サンプルコードを書きます。

1秒ごとにLEDの明るさが切り替わるプログラムです。

// PIC12F683 Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // MCLR Pin Function Select bit (MCLR pin function is MCLR)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = ON       // Brown Out Detect (BOR enabled)
#pragma config IESO = ON        // Internal External Switchover bit (Internal External Switchover mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is enabled)

#define _XTAL_FREQ 4000000

void main(void)
{
    //クロック数(4MHz)
    IRCF2 = 1;
    IRCF1 = 1;
    IRCF0 = 0;
    //ピンの入出力(全て出力)
    TRISIO = 0b00000000;
    //アナログ入力(全てデジタル入出力)
    ANS3 = 0;
    ANS2 = 0;
    ANS1 = 0;
    ANS0 = 0;
    //PWM設定
    CCP1CON = 0b1100;       //PWM有効
    PR2 = 200;              //PWM Period = 2.01 * 10^-4
    T2CON = 0b00000100;     //TMR2有効、プリスケーラ1
    
    while(1)
    {
        //DUTY = 10%
        CCPR1L = 0b00010100;
        __delay_ms(1000);
        
        //DUTY = 20%
        CCPR1L = 0b00101000;
        __delay_ms(1000);
        
        //DUTY = 30%;
        CCPR1L = 0b00111100;
        __delay_ms(1000);
        
        //DUTY = 40%
        CCPR1L = 0b01010000;
        __delay_ms(1000);
        
        //DUTY = 50%
        CCPR1L = 0b01100100;
        __delay_ms(1000);
    }
}

いつもの如く、回路図はアップしません(⌒-⌒; ) 画像の画像だけアップします笑。

@回路図
回路図

 

これで1秒ごとに明るさが変わります!

 

ノシ

PS
備忘録のつもりで書いたので、分かりにくいかもしれません( ;´Д`)

 - 技術系