PIC16F1705は、CCP(Capture/Compare/PWM)モジュール2個とPWMモジュール2個、合わせて4つのPWM出力を持っています。
まず、CCPモジュールを使ってみます。
CCP1(PWM1)をRC0に、CCP2(PWM2)をRC1に出力してみます。
CCPモジュールでのPWM発生のしくみです。
(PIC16F1705の説明書より)
PIC12F1822やPIC16F1827などと同じしくみです。上の図では、TMR2を利用した例です。
今回は、CCP1(PWM1)では、TMR4を使用し、CCP2(PWM2)では、TMR6を使用します。
クロックは、内部クロック8MHzとし、CCP1(PWM1)の周期(周波数)は、1ms(1000Hz)、CCP2(PWM2)の周期(周波数)は、2ms(500Hz)で、ともにデューティ比は50%の信号を出力します。
PWMの周期とデューティ比の値の決め方は、下の図のとおりです。(PIC16F1827の説明ですが、式は同じです)
上の式からPRxの値は、クロック周波数をFosc、出力周波数をFoutとすると
PRx=(Fosc/(Fout×4×TMRxPrescale Value))-1となります。
プログラムです。
------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdlib.h>
#include <xc.h>
// CONFIG1
#pragma config FOSC = INTOSC //内部クロックを使う
#pragma config WDTE = OFF //ウォッチドックタイマー無効
#pragma config PWRTE = ON //パワーアップタイマーを有効にする
#pragma config MCLRE = OFF //MCLRピンをRA3として使用する
#pragma config CP = OFF //プログラムメモリを保護しない
#pragma config BOREN = ON //ブラウンアウトリセットを有効にする
#pragma config CLKOUTEN = OFF //クロック出力を無効とし、RA4ピンとして使用する
#pragma config IESO = OFF //内部・外部クロックの切り替えでの起動を行わない
#pragma config FCMEN = OFF //外部クロックを監視しない
#pragma config FOSC = INTOSC //内部クロックを使う
#pragma config WDTE = OFF //ウォッチドックタイマー無効
#pragma config PWRTE = ON //パワーアップタイマーを有効にする
#pragma config MCLRE = OFF //MCLRピンをRA3として使用する
#pragma config CP = OFF //プログラムメモリを保護しない
#pragma config BOREN = ON //ブラウンアウトリセットを有効にする
#pragma config CLKOUTEN = OFF //クロック出力を無効とし、RA4ピンとして使用する
#pragma config IESO = OFF //内部・外部クロックの切り替えでの起動を行わない
#pragma config FCMEN = OFF //外部クロックを監視しない
// CONFIG2
#pragma config WRT = OFF //フラッシュメモリを保護しない
#pragma config PPS1WAY = OFF //ロック解除シーケンスで何度でもPPSLOCKをセット/クリアできる
#pragma config ZCDDIS = ON //ゼロクロス検出回路無効
#pragma config PLLEN = OFF //PLLを動作させない
#pragma config STVREN = ON //スタックオーバーフローリセットを行う
#pragma config BORV = HI //ブラウンアウトリセット電圧を高(2.7V)に設定
#pragma config LPBOR = OFF //低消費電力ブラウンアウトリセット無効
#pragma config LVP = OFF //低電圧プログラミングを行わない
#pragma config WRT = OFF //フラッシュメモリを保護しない
#pragma config PPS1WAY = OFF //ロック解除シーケンスで何度でもPPSLOCKをセット/クリアできる
#pragma config ZCDDIS = ON //ゼロクロス検出回路無効
#pragma config PLLEN = OFF //PLLを動作させない
#pragma config STVREN = ON //スタックオーバーフローリセットを行う
#pragma config BORV = HI //ブラウンアウトリセット電圧を高(2.7V)に設定
#pragma config LPBOR = OFF //低消費電力ブラウンアウトリセット無効
#pragma config LVP = OFF //低電圧プログラミングを行わない
#define _XTAL_FREQ 8000000 //クロック8MHz
void main() {
OSCCON = 0b01110010; // 内部クロック8MHz
ANSELA = 0b00000000; // AN0-AN1を使わない
ANSELC = 0b00000000; // AN4-AN6を使わない
TRISA = 0b00000000; // RORTAは全て出力
TRISC = 0b00000000; // PORTCは全て出力
PORTA = 0b00000000; // PORTAクリア
PORTC = 0b00000000; // PORTCクリア
/* PWMに関する設定
* CCP1(PWM1)をRC0に出力する
* CCP1(PWM1)の周波数は、1000Hz(周期は1ms)
* CCP2(PWM2)をRC1に出力する
* CCP2(PWM2)の周波数は、500Hz(周期は2ms)
* デューティ比は、50%とする
*/
/* RC0にCCP1(PWM1)を出力する */
RC0PPS = 0b00001100; //RC0=CCP1(PWM1)
/* RC1にCCP2(PWM2)を出力する */
RC1PPS = 0b00001101; //RC1=CCP2(PWM2)
/* CCP1,CCP2はPWM mode */
CCP1CON = 0b00001100; //CCP1=PWM mode
CCP2CON = 0b00001100; //CCP2=PWM mode
/* Timerの割り当て */
CCPTMRS = 0b00001001; //PWM1にTMR4,PWM2にTMR6を割り当てる
/* PWM1の周期とデューティ比の設定 */
PR4 = 124; //PWM1の周期1000Hz(1ms)
CCPR1L = 62; //PWM1のデューティ比 50%
T4CON = 0b00000110; //prescale 1:16 Timer4 start
/* PWM2の周期とデューティ比の設定 */
PR6 = 249; //PWM2の周期500Hz(2ms)
CCPR2L = 125; //PWM2のデューティ比 50%
T6CON = 0b00000110; //prescale 1:16 Timer6 start
while(1){
}
OSCCON = 0b01110010; // 内部クロック8MHz
ANSELA = 0b00000000; // AN0-AN1を使わない
ANSELC = 0b00000000; // AN4-AN6を使わない
TRISA = 0b00000000; // RORTAは全て出力
TRISC = 0b00000000; // PORTCは全て出力
PORTA = 0b00000000; // PORTAクリア
PORTC = 0b00000000; // PORTCクリア
/* PWMに関する設定
* CCP1(PWM1)をRC0に出力する
* CCP1(PWM1)の周波数は、1000Hz(周期は1ms)
* CCP2(PWM2)をRC1に出力する
* CCP2(PWM2)の周波数は、500Hz(周期は2ms)
* デューティ比は、50%とする
*/
/* RC0にCCP1(PWM1)を出力する */
RC0PPS = 0b00001100; //RC0=CCP1(PWM1)
/* RC1にCCP2(PWM2)を出力する */
RC1PPS = 0b00001101; //RC1=CCP2(PWM2)
/* CCP1,CCP2はPWM mode */
CCP1CON = 0b00001100; //CCP1=PWM mode
CCP2CON = 0b00001100; //CCP2=PWM mode
/* Timerの割り当て */
CCPTMRS = 0b00001001; //PWM1にTMR4,PWM2にTMR6を割り当てる
/* PWM1の周期とデューティ比の設定 */
PR4 = 124; //PWM1の周期1000Hz(1ms)
CCPR1L = 62; //PWM1のデューティ比 50%
T4CON = 0b00000110; //prescale 1:16 Timer4 start
/* PWM2の周期とデューティ比の設定 */
PR6 = 249; //PWM2の周期500Hz(2ms)
CCPR2L = 125; //PWM2のデューティ比 50%
T6CON = 0b00000110; //prescale 1:16 Timer6 start
while(1){
}
}
---------------------------------------------------------
周波数を測定しました。
CCP1(PWM1)の出力周波数です。

CCP2(PWM2)の出力です。

内部クロックの精度が上がったのでしょう、けっこう正確な周波数を発生しています。
出力波形です。(青がCCP1(PWM1)、赤がCCP2(PWM2))

ほぼ同時にTMR4とTMR6をスタートさせたので、位相がそろっています。
次は、PWM専用モジュールを使ってみます。