digital西行庵 wiki  Index  Search  Changes  PageRank  RSS  Login

PWM for PIC12F629

ページを編集するにはログインが必要です。

CCP回路が実装されていないPIC12F629でPWMを行う。

PIC16F877AにはCCP(キャプチャ・コンペア)回路が実装されており、PWM制御を比較的簡単に行うことが出来る。多機能だが、40Pinパッケージでサイズが大きく、部品単価も高い(@500-程度)。8Pinパッケージで、低価格(@120-程度)のPIC12F629でPWMによるLEDやMotorの制御が行いたい。

今回はPICアセンブラはかったるいので、B Knudsen Data(Norway)CC5XというCコンパイラ仕様で、ちゃちゃっと書いてみた。割り込みハンドラで、約35uS毎のパルス制御、約500mS毎の時間制御、sleepからのwakeupを行っている。パルスパターンは const char pt[] に宣言したものを用いる。部品数低減の為clockは内部発振回路。遅いので、motorなどを回すと微妙なスイッチング音が確認出来る。電車でも鳴ってるやつがあるんだから、まっ、いいだろう。

以下、Cソースをそのまま載せる。各自解読するように。コメントに嘘が書いてある場合があるので注意のこと。

改めてソースを眺めて今思ったけど、割り込みハンドラの中身はきちんと else if にするか switch/case文の方がいいかもね。

PIC16F877AのPWMについては、 「作りながら学ぶPICマイコン入門」 神崎康宏 著 CQ出版株式会社 ISBN4-7898-3736-X 2005年5月1日 初版発行 ¥2,730- を、各自購入して研究しなさい。(神崎氏及びCQ出版とは利害関係は一切ない)

/*
 * pwm_test.c for PIC12F629
 * Ver1.00 2007/05/05 Written by H.Nitobe
 * (C)Copyright 2007 Hiroaki Nitobe All rights reserved.
 */

//#pragma optimize = 0
#include	<INT16CXX.h>
//#include ../"12f629.h"

/*
              +--\_/--+
    (5V)VDD --|1     8|-- VSS(0V)
     GP5    XX|2     7|-> GP0(ICSPDAT) --> to Motor
     GP4    XX|3     6|XX GP1(ICSPCLK) 
      [VPP] X>|4     5|<- GP2/INT -------< from Switch
              *-------+
*/

// Chip Settings
#define CP_off   |= 0x2180		// Bandgap value + CPD(disable) + CP(disable)
#define MCLR_off &= ~0x80
#pragma config BODEN = off, MCLR_off, PWRTE = on, WDTE = off, FOSC = 4, CP_off

// Definitions
#define true !0
#define	false 0
#define	ON	1
#define	OFF 0

// Function Prototypes
interrupt int_server( void);
void main(void);
void wait(char count);

// Global Variables
char tick;
char pattern;
const char pt[] = {
	0b.0000.0000,		// 0%
	0b.0000.0001,		// 12.5%
	0b.0001.0001,		// 25%
	0b.0001.0101,		// 37.5%
	0b.0101.0101,		// 50%
	0b.0101.0111,		// 62.6%
	0b.0111.0111,		// 75%
	0b.0111.1111,		// 87.5%
	0b.1111.1111};		// 100%

// Interrupt Server
#pragma	origin	4
interrupt int_server( void)
{
	int_save_registers

	RP0 = 0;			// page#0

	if(T0IF){
		T0IF = OFF;		// Clear T0 Flag
		TMR0 = 220;		// 255 - 220 = 35Cycles = 35uS
		W = rr(pattern);		// Rotate Right F through C to W
		pattern = rr(pattern);	// Rotate Right F through C to F
		if(pattern.0){	// OUTPUT Bit0 of pattern
			GPIO0 = ON;		// Motor ON
		} else {
			GPIO0 = OFF;	// Motor OFF
		}
	}
	if(TMR1IF){			// 500mS Interrupt
		TMR1IF = OFF;	// Clear T1 Flag
		TMR1L  = 221;	// (65535-3037)*8 = 499984uS
		TMR1H  = 11;	// 3037 = 11*256+221
		tick += 1;		// Incriment tick
	}
	if(INTF){			// Wakeup from sleep
		INTF = OFF;		// Clear Int Flag (SW ON)
	}
	int_restore_registers
}

// Main Routine
void main(void)
{
	char i;

    // Initialize
	RP0 = 1;					// page#1
    #asm
        DW /*CALL*/ 0x2000 + 0x3ff
    #endasm
    OSCCAL = W;					// 90h: Set OSCCAL
    OPTION = 0b.0000.1000;		// 81h: TMR0 1:2 prescaler divide by 2

	RP0 = 0;					// page#0
	INTCON = 0b.0000.0000;		// 0bh:
    CMCON  = 0b.0000.0111;		// 19h: Not Use COMP
    GPIO   = 0b.0000.0000;		// 05h:
	T1CON  = 0b.0011.0000;		// 10h: 1/8 Prescale
	TMR0   = 220;				// 01h:
	TMR1L  = 221;				// 0eh:
	TMR1H  = 11;				// 0fh:

	RP0 = 1;					// page#1
    TRISIO = 0b.0000.0100;		// 85h:
	WPU    = 0b.0000.0100;      // 95h:
	
// Main Routine
	while (1) {
		RP0 = 0;				// page#0
		INTCON = 0b.1001.0000;	// 0bh: GIE | INTE
		T1CON  = 0b.0011.0000;	// 10h: TMR1ON_OFF
		RP0 = 1;				// page#1
		PIE1   = 0b.0000.0000; 	// 8ch: TMR1IE_OFF

		nop();			// for BreakePoint of Debugger
		sleep();			// Sleeps until Switch-ON
		nop();			// for BreakePoint of Debugger

		RP0 = 0;				// page#0
		INTCON = 0b.1110.0000;	// 0bh: GIE | PEIE | T0IE
		T1CON  = 0b.0011.0001;	// 10h: TMR1ON_ON
		RP0 = 1;				// page#1
		PIE1   = 0b.0000.0001; 	// 8ch: TMR1IE_ON

		pattern = pt[3];		// Start 0.5s
		wait(1);

		pattern = pt[2];		// Pattern(2) 2.5s
		wait(5);

		for(i = 3; i < 8; i++) {
			pattern = pt[i];	// Pattern(3-7) 5s
			wait(2);
		}

		pattern = pt[8];		// Pattern(8) 3s
		wait(6);

		for(i = 7; i > 2; --i) {
			pattern = pt[i];	// Pattern(7-3) 5s
			wait(2);
		}

		pattern = pt[2];		// Pattern(2) 3s
		wait(6);

		for(i = 3; i < 8; i++) {
			pattern = pt[i];	// Pattern(3-7) 5s
			wait(2);
		}

		pattern = pt[8];		// Pattern(8) 3s
		wait(6);

		for(i = 7; i > 2; --i) {
			pattern = pt[i];	// Pattern(7-3) 5s
			wait(2);
		}

		pattern = pt[2];		// Pattern(2) 3s
		wait(6);
	}

}

// Subroutine of Time Count
void wait(char count)
{
	tick = 0;				// tick = 500mS
	while(tick < count);

	return;
}
Last modified:2007/11/12 07:53:47
Keyword(s):[PIC] [PIC12F629]
References:
This page is frozen.