digital西行庵 wiki  Index  Search  Changes  PageRank  RSS  Login

digital西行庵 wiki - PWM for PIC12F629 Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

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

今回はPICアセンブラはかったるいので、[[B Knudsen Data(Norway)|http://www.bknd.com/]]の[[CC5X|http://www.bknd.com/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;
}
>>>