2014/11/23

16F88 XC8開発例 - 可変抵抗でLEDの輝度を制御する

概要

PIC16F88とMPLAB XC8 C Compilerを使用した開発例として,可変抵抗でLEDの輝度を制御するプログラムを紹介します. この開発例では,PIC16F88のA/D変換モジュールとCCPモジュールのPWMモードを使用しています. 開発環境は下記のとおりです.

PIC PIC16F88-I/P
MPLAB X IDE MPLAB X IDE v2.15
MPLAB XC8 MPLAB XC8 C Compiler v1.32
PICkit 2 MPLAB X IDEを使用して書込み
回路
回路図

PICkit 2を使用してICSP (In Circuit Serial Programming)と電源供給を行うことを前提とした回路です. 今回は,これをブレッドボード上に組んで動作を確認しました.

電源はPICkit 2から5.0Vを供給しています. 内蔵クロックを使用するため,外部発振子は不要です. AN0に可変抵抗を接続し,RB3に電流制限用抵抗 330Ωを経由してLEDを接続しています.


回路図
回路部品

下表は使用部品表です.

番号 部品名 型番 数量 参考単価
U1 PICマイコン Microchip PIC16F88-I/P 1 200円
LED1 LED 各社 各色 1 10円
VR1 可変抵抗 各社 30kΩ B 1 40円
R1 炭素皮膜抵抗 各社 1/4W 10kΩ 1 1円
R2 炭素皮膜抵抗 各社 1/4W 330Ω 1 1円
その他 リード線など 適量
プログラム
main.c

下記はソースファイル「main.c」です.参考になれば幸いです.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <xc.h>
 
#define _XTAL_FREQ 8000000  // 8MHz
 
#define PR2_DATA 0xFF
#define T2_DIV_BY_1 0b00000000
#define CCP_PWM 0b00001100
 
// 16F88
// CONFIG1
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off)
#pragma config CCPMX = RB3      // CCP1 Pin Selection bit (CCP1 function on RB3)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
 
// CONFIG2
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal External Switchover mode disabled)
 
// プロトタイプ宣言
void setADCChannel(unsigned char channel);
unsigned int readADCValue(void);
void initPWM1(unsigned char pr2, unsigned char t2ckps);
void setPWM1Duty(unsigned int duty);
 
void main(void)
{
    unsigned int duty1;
 
    OSCCON = 0b01110000;    // 内蔵クロックの周波数を8MHzに設定
 
    PORTA = 0x00;           // PORTAを初期化
    PORTB = 0x00;           // PORTBを初期化
 
    TRISA = 0b00000001;     // PORTAの入出力設定
    TRISB = 0b00000000;     // PORTBの入出力設定
 
    ANSEL = 0b00000001;     // AN0を有効化
    ADCON0 = 0b01000001;    // Fosc/16, ADON
    ADCON1 = 0b11000000;    // 右詰め, AVdd, AVss
 
    duty1 = 0;
 
    initPWM1(PR2_DATA, T2_DIV_BY_1);    // CCP1をPWMモードに設定
    // PWM周波数は約7.8kHz(計算式は下記)
    // PWM Frequency = 1 / ((PR2_DATA + 1) * 4 * (1 / _XTAL_FREQ))
    setPWM1Duty(duty1);                 // デューティ値を初期化(10bit, 0-1023)
 
    while(1){
        setADCChannel(0);               // A/D変換対象チャンネルを設定
        __delay_us(50);                 // アクィジション時間(50マイクロ秒)
        duty1 = readADCValue();         // A/D変換値を取得
 
        setPWM1Duty(duty1);             // A/D変換値をデューティ値に設定
    }
}
 
/*
 * A/D変換対象チャンネル設定関数
 *
 * 引数:
 * unsigned char channel    A/D変換対象チャンネル
 *
 * 復帰値:
 * なし
 */
void setADCChannel(unsigned char channel)
{
    ADCON0 &= 0b11000111;               // CHS<2:0>を初期化
    ADCON0 |= (channel << 3);
}
 
/*
 * A/D変換値取得関数
 *
 * 引数:
 * なし
 *
 * 復帰値:
 * unsigned int             A/D変換値(10bit, 0-1023)
 */
unsigned int readADCValue(void)
{
    GO_nDONE = 0b1;
    while(GO_nDONE);
    return ((ADRESH << 8) + ADRESL);
}
 
/*
 * CCP1モジュール PWM初期設定関数
 *
 * 引数:
 * unsigned char pr2        PR2設定値
 * unsigned char t2ckps     プリスケーラ設定値
 *
 * 復帰値:
 * なし
 */
void initPWM1(unsigned char pr2, unsigned char t2ckps)
{
    PR2 = pr2;
    CCP1CON = CCP_PWM;
    setPWM1Duty(0);
    T2CON = t2ckps;
    T2CON |= 0x04;
}
 
/*
 * CCP1モジュール PWMデューティ値設定関数
 *
 * 引数:
 * unsigned char pr2        PR2設定値
 * unsigned char t2ckps     プリスケーラ設定値
 *
 * 復帰値:
 * なし
 */
void setPWM1Duty(unsigned int duty)
{
    CCPR1L = duty >> 2;
    CCP1CON &= 0b11001111;
    CCP1CON |= 0b00110000 & (duty << 4);
}

0 件のコメント:

コメントを投稿