やるべき機能

  • 書き込み
  • Digital IO/Analog I
  • タイマー割り込み→TMR0
  • PWM
  • 外部通信(USERT, I2C, SPI)

データシート疑問点とその解決

  • RA0 General Purpose IO
  • AN0 AD Channel
  • レジスタには行があり、Bankとよぶ(00-1F, 90-9Fのように)
  • PORTAが双方向ポートで、TRISAがその向き。
  • ANSELはinputのみをアナログにする?
  • アセンブリ用語
    • W アキュムレータ(一般用語)、ワーキングレジスタ(PIC用語)。tmp変数に相当。
    • F Function Register: そこに読み書きするとビヘイビアが出たり読めたりする。(TRIS, Rなど)
    • L リテラル
  • prescaler 分周器
  • Communication 通信
  • SINGLE IN-LINE CONNECTOR ピンソケット

PIC16F887

環境設定

  • MPLABをインストール(Windows版は不安定との噂)
  • XC8 compilerをインストール

デジタル入出力

#include <xc.h>

#pragma config BOREN = OFF
#pragma config CPD = OFF 
#pragma config FOSC = INTRC_CLKOUT
#pragma config MCLRE = OFF
#pragma config WDTE = OFF
#pragma config CP = OFF
#pragma config LVP = OFF 
#pragma config PWRTE = ON 

#define _XTAL_FREQ 5000000 

// Timer Interrupt Function
int count = 0;
void interrupt InterTimer(void)
{
    if (T0IF) {
        TMR0 = 10, T0IF = 0; // reset TMR0 and T0IF

        count++;
        RA1 = (count & 0xFFF > 0x8FF);
    }
}

#define T2_DIV_BY_1 0b00000000
#define T2_DIV_BY_4 0b00000001
#define T2_DIV_BY_16 0b00000010

#define CCP_PWM 0b00001100
#define PR2_DATA 0xFF
void setPWM1Duty(unsigned int duty)
{
    CCPR1L = duty >> 2;
    CCP1CON &= 0b11001111;
    CCP1CON |= 0b00110000 & (duty << 4);
}
void setPWM2Duty(unsigned int duty)
{
    CCPR2L = duty >> 2; // set lower 8 bit
    CCP2CON &= 0b11001111; // clear and
    CCP2CON |= 0b00110000 & (duty << 4); // set upper 2 bit
}

void initTimer2(unsigned char pr2, unsigned char t2ckps)
{
    PR2 = pr2;
    T2CON = t2ckps; // set prescalar
    T2CON |= 0x04; // timer 2 on
}
void initPWM1(void)
{
    CCP1CON = CCP_PWM; // single PWM
    setPWM1Duty(0);
}
void initPWM2(void)
{
    CCP2CON = CCP_PWM; // simgle PWM
    setPWM2Duty(0);
}

int main(void) {
    // GPIO settings
    ANSEL = 0b10000000; // addddddd
    TRISA = 0b11110000; // iiiioooo
    TRISC = 0b00000000; // oooooooo for PWM (= CCP and GPIO out and Timer)
    
    // Analog setting
    ADCON0 = 0b00000001;  // enagle ADC
    ADCON0 &= 0b11000011; // clear reading mode
    ADCON0 |= 0b00011100; // reading-AN7 mode
    ADCON1 = 0b10000000;  // right justified, base vol. is VSS/VDD

    /* Timer Interrupt */
    // Timer 0 interrupt (prescalar 111=1/256)
    OPTION_REG = 0b00000111;
    TMR0   = 10;   // Init timer 0
    T0IF   = 0;     // Timer 0 Interrupt Flag
    T0IE   = 1;     // Timer 0 Interrupt Enable
    GIE    = 1;     // Global Interrupt Enable (if 0, all is disabled)

    // PWM (Use Timer 2 and Comparator 1, 2)
    initTimer2(PR2_DATA, T2_DIV_BY_1);
    initPWM1();
    initPWM2();
    setPWM1Duty(0);
    setPWM2Duty(0);

    while (1) {
        // Digital IO (RA5)
        RA3 = RA5;

        // Delay
        RA0 = 1;
        __delay_ms(150);
        RA0 = 0;
        __delay_ms(150);

        // PWM
        setPWM1Duty(1023);

        // Analog Read (the output is PWM2)
        GO_DONE = 1;
        while(GO_DONE);
        setPWM2Duty((ADRESH << 8) | ADRESL);

    }
}

delay

  • __delay_us, __delay_msを利用する。
    • 引数に変数を入力してはいけない
    • 可変にしたい場合は、以下のようにする。
#define _XTAL_FREQ 5000000 // F_OSC/4
for(i=0;i<n;i++)__delay_ms(10);/*10msをn回繰り返し*/

TIMER0

  • 4/F_OSC*プリスケーラ設定値 [s]周期で呼ばれる。

疑問

  • configの説明はいったいどこにあるのか。
    • ブラウンアウトリセットとは
    • データコードプロテクションとは
  • PORTAを直接書き換えてもだめで、RA0などをいじるとOKなのはなぜか。
  • _XTAL_FREQを20MHzにしたらむしろ点滅周期が遅くなったのはなぜか。
  • Applications/microchip/doc/chipsにconfigの説明が書いてある。
  • Cプログラム上で利用可能なピンのディレクティブをどこで調べればいいのか(PORTA, RA0など)。
  • simulatorがあるとの噂、どのように利用するのか。
  • PWMのactive low, highとは何か。
  • timer一つで複数のPWMの駆動ができるということか。
  • timerがいろんな所に使われているが併用はできるのか。

Config


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS