メインコンテンツへスキップ
見出し画像

PIC18F SFR設定

    PICマイコンのマニュアルを読んでSFRの設定をする作業は、結構面倒なものです。しかも、この作業はプログラム作成の最初に行う必要があります。もっと言えば、回路設計の際にも、必要な機能を確保出来ることを確認している必要があります。

    私がPIC18F23K22 , PIC18F46K22 以外のCPUを滅多に使わなくなったのも、出来るだけ面倒な作業を避けたい一心でした。

    この記事ではPIC18F23K22 を例に、私が普段使っているプログラムのファイル構造とSFR設定の様子を紹介します。

    ファイルの構造

    私が作るプログラムのファイル構造は以下のようなものです。
    1.main.c       メイン
    2.configuration_bits.c MPLAB-Xからコピー
    3.appdef.c      SFR設定
    4.subs.c       関数群
    5.inthigh.c      高位割り込み関数
    6.intlow.c       低位割込み関数

    ファイル名は以前に決めたもので、appdef.c のように意味不明のものもありますが、そのまま使い続けています。

    main.c

    C言語(XC8)で、こんな構造です。

    /******************************************************************************/
    /* Files to Include                                                           */
    /******************************************************************************/
     #include  <stdio.h>
     #include  <stdlib.h>
    
    /******************************************************************************/
    /* Configuration Bits                                                         */
    /******************************************************************************/
     #include  "configuration_bits.c" //
    
    /******************************************************************************/
    /* User Global Variable Declaration                                           */
    /******************************************************************************/
    /* i.e. uint8_t <variable_name>; */
    //#define         qtys        2       //子機の数
    unsigned char   ii       =  0   ;   //汎用ループカウンター
    unsigned char   jj       =  0   ;   //汎用ループカウンター
     #include  "subs.c"                   //サブルーチン集
    
    /******************************************************************************/
    /* Main Program                                                               */
    /******************************************************************************/
    
    int main(int argc, char** argv) {
    
    /* Refer to the device datasheet for information about available
       oscillator configurations. */
        #include  "appdef.c"     //Oscillator A/D Ports Peripherals Int. Def.
    
       /* Enable interrupts */
       INTCONbits.TMR0IF = 0 ;     //TIMER0 割り込みフラグクリア
       INTCONbits.TMR0IE = 1 ;     //TIMER0 割り込み許可
    //    PIR5bits.TMR4IF = 0 ;       //TIMER4  割り込みフラグクリア
    //    PIE5bits.TMR4IE = 1 ;       //TIMER4 割り込み許可
    //    PIR1bits.TMR2IF = 0 ;       //TIMER2  割り込みフラグクリア 送信期間中に限る
    //    PIE1bits.TMR2IE = 1 ;       //TIMER2 割り込み許可     送信期間中に限る
       PIR2bits.TMR3IF   = 0 ;     //TIMER3 割り込みフラグクリア
       PIE2bits.TMR3IE   = 1 ;     //TIMER3 割り込み許可
    //    PIR1bits.RC1IF = 0 ;        //RC1 割り込みフラグクリア PC
    //    PIE1bits.RC1IE = 1 ;        //RC1 割り込み許可
    //    PIR3bits.RC2IF = 0 ;        //RC2 割り込みフラグクリア 
    //    PIE3bits.RC2IE = 1 ;        //RC2 割り込み許可
    
    // 初期動作
       
    
    //  ループ
       
       while(1)
       {
    
       }
    
       
       return (EXIT_SUCCESS);
    }
    
    /******************************************************************************/
    /* Interrupt Routines                                                         */
    /******************************************************************************/
    /* High-priority service */
     #include  "inthigh.c"    //高位割り込み処理
    
    /* Low-priority interrupt routine */
     #include  "intlow.c"     //低位割り込み処理

    先程の6ファイルの内 main.c を除く5ファイルを include しています。

    /* Enable interrupts */ の部分は、一度確認したものを並べ、必要に応じてコメントON/OFFして使っています。

    割り込み関数

    次のように記述して期待した通りに動作しているのですが、行頭に ! マークが出てカーソルを合わせると Unable to resolve identifier interrupt. と表示されます。
    解決方法をご存知の方がいらしたら、教えていただけると助かります。

    inthigh.c

    void interrupt high_isr (void)
    {
    
    }

    intlow.c

    void interrupt low_priority low_isr (void)
    {
    
    {

    SFR設定

    クロックの設定に始まり、割り込みの設定まで記述し、必要に応じてコメントON/OFFしたり値を変えて使っています。

        /* Refer to the device datasheet for information about available
       oscillator configurations. */
       
       /* TODO Add clock switching code if appropriate.  */
       OSCCON = 0b01110010 ;   //内部16MHzにクロック切替
    //    OSCCON = 0b01111000 ;   //外部 Primaryクロックに切替
    
       /* TODO Initialize User Ports/Peripherals/Project here */
       /* Setup analog functionality and port direction */
       ANSELA = 0b00000000 ;
       ANSELB = 0b00000000 ;
       ANSELC = 0b00000000 ;
    //    ANSELD = 0b00000000 ;
    //    ANSELE = 0b00000000 ;   //全てデジタル
    //    ANCON0 = 0b00000000 ;
    //    ANCON1 = 0b00000000 ;
    //    ANCON2 = 0b00000000 ;   //全てデジタル
    
       LATA  = 0b00000000 ;    //LATA = 0
       TRISA = 0b00000000 ;    //PortA 入出力設定
       LATB  = 0b00000000 ;    //LATB = 0
       TRISB = 0b11000111 ;    //PortB 入出力設定
       LATC  = 0b00000000 ;    //LATC = 0
       TRISC = 0b00000000 ;    //PortC 入出力設定
       
       /* Initialize peripherals */
       //USART1
    //    TXSTA1 = 0b00100110 ;   //TXSTA1 8bit 非同期許可 BRGH=1
    //    RCSTA1 = 0b10010000 ;   //TCSTA1 8bit シリアル許可
    //    BAUDCON1bits.BRG16 = 1 ;    //16bit ボーレートジェネレーター使用
    //    SPBRGH1 = 0         ;
    //    SPBRG1 = 34         ;   //115.2kbps -0.79%
    //    SPBRGH1 = 0x01      ;
    //    SPBRG1 = 0xA0       ;   //9600bps -0.08%
    
       //USART2
    //    TXSTA2 = 0b00100110 ;   //TXSTA1 8bit 非同期許可 BRGH=1
    //    RCSTA2 = 0b10010000 ;   //TCSTA1 8bit シリアル許可
    //    BAUDCON2bits.BRG16 = 1 ;    //16bit ボーレートジェネレーター使用
    //    SPBRGH2 = 0         ;
    //    SPBRG2 = 34         ;   //115.2kbps -0.79%
    
       //TIMER0    50msec 汎用イベントタイマー
       T0CON = 0b10000011 ;    //T0CON = Enable,16bits,PSon,1/16
       TMR0H = tim0defh ;      //12500カウント 50msec 10000h-12500d
       TMR0L = tim0defl ;      //0.25usec x 16 x 12500 = 50msec
       evtcnt = evtcntini ;
       
       //TIMER1    センサー駆動用、CCP5 でトグル出力 ×ハードでTIMER1クリア出来ない → 不採用
    //    T1CON = 0b00000011 ;    //Fosc/4 1/1プリスケーラー使用 16bitモード
    //    TMR1H      = 0     ;
    //    TMR1L      = 0     ;
                               //割り込みは使用しない
       //TIMER3    RCサーボ制御タイマー 1.0usec/count
       T3CON = 0b00100011 ;    //Fosc/4 1/4プリスケーラー使用 16bitモード
       TMR3H        = 0     ;
       TMR3L        = 0     ;
                               //高位割り込み
       
       //TIMER2    センサー駆動用周期設定 PR2 、CCP5でPWM(デューティー50% → CCPR5L)
    //    PR2   = pr2a40 ;           //40kHz
    //    TMR2  =  0  ;
    //    T2CON = 0b00000100 ;    //Fosc/4 PreS=1/1 PostS=1:1 Timer ON
    
       //TIMER4    UART2送信用タイマー 2msec
    //    PR4   = 50 ;            //0.25 * 16 * 50 * 10 = 2 msec
    //    TMR4  =  0 ;
    //    T4CON = 0b01001110 ;    //Fosc/4 PreS=1/16 PostS=1:10 Timer ON
    
       //RB CHANGE
    //    IOCB  = 0b00110000 ;    //RB4,RB5 使用
    
       //SPI1
    //    SSP1STAT = 0b01000000 ; //CKE = 1
    //    SSP1CON1 = 0b00100010 ; //Enable SPI Master Fosc/644
       
       //CCP5
    //    CCPTMRS1   = CCPTMRS1 & 0b11110011 ; //CCP5 PWM Timer2
    //    CCP5CON    = 0b00001100 ; //CCP5 PWM mode
    //    CCPR5L     = pr2a40 >> 1 ; //周期の半部 (周期 PR2 は偶数が望ましい)
    
       /* Configure the IPEN bit (1=on) in RCON to turn on/off int priorities */
       RCONbits.IPEN = 1 ;         //割り込み優先順位有効
       INTCONbits.GIE = 1 ;       //高位割り込み有効
       INTCONbits.PEIE = 1 ;       //低位割り込み有効
    //    IPR1bits.SSP1IP = 1 ;       //SSP1 を高位割り込みに設定
    //    IPR1bits.RC1IP = 0  ;       //RX1 を低位割り込みに設定
    //    IPR3bits.RC2IP = 1  ;       //RX2 を高位割り込みに設定
       INTCON2bits.TMR0IP = 0 ;    //TIMER0 を低位割り込みに設定
    //    IPR1bits.TMR2IP = 0 ;       //TIMER2 を低位割り込みに設定
    //    IPR5bits.TMR4IP = 0 ;       //TIMER4 を低位割り込みに設定
       IPR2bits.TMR3IP = 1 ;       //TIMER3 を高位割り込みに設定

    まとめ

    SFR設定を毎回調べるのが面倒なので、一つのファイルの記述を加減して、「秘伝のたれ」のように使っています。

    私のソースについて改善すべき点や、皆さんの工夫をお聞かせいただければ幸いです。



     
     

    uPyC

     
     
    こんにちは! 治具やツールなどマイコン仕掛けを作る機会が多いので、その辺の事柄を中心に紹介したいと思います。ESP32、PIC、RasPiでハード・ソフト、ケース製作まで広く扱います。宜しくお願いします。

    あなたへのおすすめ