見出し画像

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

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



出来ればサポート頂けると、嬉しいです。 新しい基板や造形品を作る資金等に使いたいと思います。