PIC

PICkit 2を購入

2009年6月21日

先日、サンフランシスコの紀伊国屋に行ったとき、何気なく手にしたトランジスタ技術・2009年4月号。そこでの特集が、『これなら分かる!!PICマイコン』。以前から、PICでもAVRでもなんでもいいから、マイクロコントローラを使えるようにならにゃイカンなと思っていて、その機会がなかったのだが、これを機に勉強することにした。

トラ技をよむと、Cでプログラムが組めるではないか!しかも、HITEC-C liteというのを用いれば、すべてフリーソフトでできる。これはいい。アセンブラも楽しいが、Cで組めるとなると、やりたいことがすぐにコードになるという利点がある。

Microchip社が、これもフリーで出しているMPLAB IDEと、HITEC-Cを用いてトラ技を見ながら始めて書いたコードは以下のとおり。
#include <pic.h>
__CONFIG(INTIO & WDTDIS & PWRTDIS & MCLRDIS & UNPROTECT & BORDIS & IESODIS & FCMDIS);

void main(){

}

main()関数の中に色々と書けば、色々とできる。簡単・簡単。

早速、手作りコンピューターでのとりあえずの目標である、円周率の計算を行うマイコンを製作した。アルゴリズムは、Jeans & Developmentに書いたとおり。

PICのほうの技術としては、タイマー割り込みとLEDのダイナミック点灯を利用している。これらの詳しい解説は、トラ技に載っている。回路も、3つの7セグメントLEDを点灯させるだけの簡単なものなので、割愛。下の写真は、できた回路を、PICkit 2につないでいるところ。

pi_calc

プログラムは以下のようになった。
#include <pic.h>
__CONFIG(INTIO & WDTDIS & PWRTDIS & MCLRDIS & UNPROTECT & BORDIS & IESODIS & FCMDIS);

unsigned char led7(char num){
    unsigned char ret=0xFF;
    if (num & 0x10) ret=0xF7;
    switch (num & 0x0F) {
        case 0: return ret & 0x28;
        case 1: return ret & 0x7B;
        case 2: return ret & 0x1C;
        case 3: return ret & 0x19;
        case 4: return ret & 0x4B;
        case 5: return ret & 0x89;
        case 6: return ret & 0x88;
        case 7: return ret & 0x2B;
        case 8: return ret & 0x08;
        case 9: return ret & 0x09;
        default: return 0xff;
    }
}

// 10000 cycles @ 8 MHz / 4 == 5 ms
#define WAIT_CYCLE (10000-23)
#define TMR1H_INIT ((unsigned char)(((unsigned short)(65536-WAIT_CYCLE))>>8))
#define TMR1L_INIT ((unsigned char)(((unsigned short)(65536-WAIT_CYCLE))&0x00ff))

unsigned char g_ledp=0;
unsigned short g_num=0;

void interrupt int_function (void) {
    if (!TMR1IF) return;
    TMR1H=TMR1H_INIT;
    TMR1L=TMR1L_INIT;
    TMR1IF=0;

    if (++g_ledp==3) g_ledp=0;
    PORTA=0x00;
    
    switch (g_ledp) {
        case 0:
            PORTC=led7(0x10 | g_num / 100);
            PORTA=0x04;
            break;
        case 1:
            PORTC=led7(( g_num / 10 ) % 10);
            PORTA=0x10;
            break;
        case 2:
        default:
            PORTC=led7(g_num % 10);
            PORTA=0x20;
            break;
    }
}

void delay(){
    unsigned char c1,c2;
    for (c1=0;c1<255;c1++) for (c2=0;c2<255;c2++);
}
float calc_pi(unsigned long max){
    unsigned long total=0;
    unsigned long max2=max*max;
    unsigned long prev_y=max-1;
    unsigned long x,y,max2_x2;
    for (x=0;x<max;x++) {
        max2_x2=max2-x*x;
        for (y=prev_y;0<=y;y--) {
            if (y*y<max2_x2) break;
        }
        total+=y+1;
        prev_y=y;
    }
    return ((float)total/(float)max2)*4;
}
void main(){
    // CLK=8 MHz
    OSCCON=0x70;
    // All output
    TRISA=0;
    TRISB=0;
    TRISC=0;
    // Non-analog mode
    ANSEL=0x00;
    ANSELH=0x00;

    // Scaler 1:1
    T1CON=0x00;
    // Reset timer
    TMR1H=0x00;
    TMR1L=0x00;
    // Clear flag
    TMR1IF=0;
    // Enable interrupt
    TMR1IE=1;
    PEIE=1;
    GIE=1;
    // Start timer
    TMR1ON=1;

    unsigned long max;
    float pi;
    for(max=1;max<8192;max*=2){
        pi=calc_pi(max);
        g_num=(unsigned short)(pi*100);
        delay();
    }
    while(1);
}

PICkitからはずして、6V電源だけを供給して実行させると、以下のとおり。

コメント

コメントはありません

コメント送信