PIC18F27Q43 PWM module

# Q43 PWM

https://youtube.com/shorts/ff6vNy2Pvbc?si=BtlKbf2hhIiX2dGF

PWM専用のモジュールが搭載されています。すぐに動かせる機構になっています。
![IMG_4766.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/d54de4c8-5f9d-be94-e55b-ecc473ed2c24.jpeg)
# 使用したDCモータドライバー　NJU7386
DCモータを正転、逆転させたいので、DCモータドライブIC、NJU7386を使いました。
NJU7386ブロック図
![NJU738_ブロック図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/8db425b9-2176-d4b2-983c-ba93a61ca5b3.png)
NJU7386真理値表
![NJU7386_真理値表.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/b860cbe4-5265-d6b6-6973-3c785b65e8bc.png)
![NJU7386.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/12fd819d-99de-248f-30a8-c3fd0e91f82f.png)
フォトカプラでピックマイコンのPWM信号を受け取ります。マイコン基板と、モータ基板のグランドは、分離させています。
NJU7386のINA端子、INB端子にQ43のPWM信号を接続します。

# Q43 PWMモジュール概略
DCモータの正逆転を、可変速で制御します。

PWM Left-Aligned modeブロック図
![Left_aligned mode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693934/833f2da0-9436-bd04-5c04-5d994f58af41.png)

:::note info
**設定する必要があるレジスタ一覧**
PWMコンフィグレーション設定:`PWMxSaCFG`レジスタ
PWMクロックソースの選択:`PWMCKL`レジスタ
PWMクロックプリスケーラ:`PWMxCPRE`レジスタ
PWM周期：`PWMxPR`レジスタ
PWMduty時間:`PWMxSaP1,PWMxSaP2`レジスタ
:::

PWMのモードは、Left-Alignedにしています。
```C:PWM1モジュール初期設定
void pwm1Init(void)
{
    PWM1CLK=0x05;//MFINTOSC 500khz
    //PWM1PR=0x00EA;//15ms
    PWM1PR=0x0138;//20ms
    //PWM1PR=0x7EF;//100ms
    PWM1S1CFGbits.MODE=0b000;//Left-Alighned mode
    //PWM1PR=0x02FFF;
    PWM1CPRE=0x20;//prescaler
    PWM1S1P1H=0x00;
    PWM1S1P1L=0x00;
    PWM1S1P2H=0x00;
    PWM1S1P2L=0x00;
    PWM1S1CFG=0x00;
    
    //Clear PWM1_16BIT period interrupt flag
    PIR4bits.PWM1PIF = 0;
    //Clear PWM1_16BIT interrupt flag
    PIR4bits.PWM1IF = 0;  
    //Clear PWM1_16BIT slice 1, output 1 interrupt flag
    PWM1GIRbits.S1P1IF = 0;
    //Clear PWM1_16BIT slice 1, output 2 interrupt flag
    PWM1GIRbits.S1P2IF = 0;
    //PWM1_16BIT interrupt enable bit
    PIE4bits.PWM1IE = 0;
    //PWM1_16BIT period interrupt enable bit
    PIE4bits.PWM1PIE = 0;
   
    //PPS
    //6.PPS
    PPSLOCK = 0x55; 
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0;//Unlock.
    //RB4PPS=0x18;
    RC1PPS=0x18;
    RC2PPS=0x19;
    PPSLOCK = 0x55; 
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 1;//lock.
    PWM1CONbits.EN=1;
}
```
※PWM割り込みフラグ、割り込み許可を使用していません。
通常のDCモータ制御では、使用しなくても、問題ないと思います。

# duty比を変えるためのLDビット
動作中にPWMのduty比を変えて、速度を加減速するとき、`PWMxS1P1, PWMxS1P2`レジスタに値をセットします。
ダブルﾊﾞｯﾌｧになっているので、ソフトで書きこんでも、即有効になりません。
**PWMコントロールレジスタ`PWMxCON`のLDビットをセットします。**
新しい値を更新することをハードに要求します。
ハードは、新しい値を書き込みバッファから読み出して、PWMのdutyカウンタを更新します。
更新完了すると、ハードは、LDビットをクリアします。
**ユーザーソフトは、このLDビットがクリアされたことを確認する必要があります。**
```C:PWMのduty比を変えるコード
    PWM1S1P1 =dutyWide; //slice1:dutyカウンタ値
    PWM1S1P2 =dutyWide; //slice2:dutyカウンタ値

    PWM1CONbits.LD=1;   //新しいP1,P2の値を更新する
    while(PWM1CONbits.LD);    //ハードがクリアすれば、設定完了。
```
# PWMモジュールの2つのSlice
PWMのブロック図を見ると、2つのduty比が違うPWM信号を出力できることがわかります。
PWMモジュール一つで、DCモータの正逆転を制御できます。
左右の車輪がついたリモコンカーの場合、PWM1,PWM2モジュールの2つを使えば、2つのDCモータの正逆転を制御することができます。
```C:dutyセットのコード
    //PWM1モジュールの加減速
    PWM1S1P1 = duty値/15;
    PWM1S1P2 = 0;
    //PWM2モジュールの加減速
    PWM2S1P1 = duty値/15;
    PWM2S1P2 = 0;
```
`PWMxS1P1,PWMxS1P2`レジスタは、DCモータの速度を設定するレジスタになります。

# 今回使用したコード
正逆転の指示を出すためにスーファミコントローラを使用しています。
```C:famicon.h
#ifndef FAMICON_H
#define	FAMICON_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <xc.h>
    
#define PS LATAbits.LATA5
#define CLK LATAbits.LATA6
#define DATA1 PORTAbits.RA7

extern uint16_t famiconButtonState;
extern  void famiconInit(void);    
extern  uint16_t getButton(void);
    
   
#ifdef	__cplusplus
}
#endif

#endif	/* FAMICON_H */
```
```C:famicon.c
#include "famicon.h"
#include "I2C_LCD.h"

uint16_t famiconButtonState;
///@brief コントローラーの初期化
void famiconInit(void)
{
    TRISAbits.TRISA7=1;//Data線
}

///@brief ボタン押下状況取得関数
///return ボタン押下16ビットデータ
uint16_t getButton(void)
{
    uint16_t w_val;
    uint8_t cnt;
    w_val=0x0000;
        cnt=0;
        
        //最初の1ビット
        PS=1;
        CLK=1;
        __delay_us(10);
        PS=0;
        CLK=0;
        __delay_us(10);
        
        w_val|=DATA1;
        w_val<<=1;
        cnt++;
        //残り15ビットの取得
        do{
            CLK=1;
            __delay_us(10);
            CLK=0;
           // __delay_us(5);
            w_val|=DATA1;
            if(cnt!=15)
            {
                w_val<<=1;
            }
            cnt++;
        }while(cnt!=16);
        //受信完了    
        w_val&=0xFFF0;//ボタンデータのみを、抽出
        if(w_val!=0xFFF0)    
        {
            if((w_val&0x8000)==0x0)
            {
                printf("B ");
            }
            
            if((w_val&0x4000)==0x0)
            {
                printf("Y ");
            }
            
            if((w_val&0x2000)==0x0)
            {
                printf("SELECT ");
            }
            
            if((w_val&0x1000)==0x0)
            {
                printf("START ");
            }
            
            if((w_val&0x0800)==0x0)
            {
                printf("UP ");             
            }
                        
            if((w_val&0x0400)==0x0)
            {
                printf("DOWN ");
            }
            
            if((w_val&0x0200)==0x0)
            {
                printf("LEFT ");
            }
            
            if((w_val&0x0100)==0x0)
            {
                printf("RIGHT ");
            }
            
            if((w_val&0x0080)==0x0)
            {
                printf("A ");
            }
            
            if((w_val&0x0040)==0x0)
            {
                printf("X ");
            }
            
            if((w_val&0x0020)==0x0)
            {
                printf("L ");
            }
            
            if((w_val&0x0010)==0x0)
            {
                printf("R ");
            }
            printf("%04x\r",w_val);
        }
        return w_val;
}

```
```C:Q_Peripheral.h PWM1,PWM2の初期化

#ifndef Q_PERIPHERAL27Q43_H
#define	Q_PERIPHERAL27Q43_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
    
#define Low 0
#define High 1
   
#define _XTAL_FREQ 32000000
#define BAUDRATE 115200
#define SET_SPBRG_DATA  (((unsigned int)((_XTAL_FREQ/4)/BAUDRATE))-1)
#define SET_SPBRG_DATA1 (((unsigned int)((_XTAL_FREQ/16)/BAUDRATE))-1)   
//USART---------------------------------------
#define RXUSART_BUFFER_SIZE 20
typedef struct
{
    uint8_t buf[RXUSART_BUFFER_SIZE];
    uint8_t length;
    uint8_t completed;
}_rxUsart;
extern _rxUsart rxUsart;
extern void usartInit(void);
extern void putch(uint8_t);
extern uint8_t getch(void);
//Timer--------------------------------------
typedef struct
{
    uint16_t cnt;
    bool fg;
}_tm;
extern _tm tm0,tm2;
extern void timer0Init(void);    
extern void timer2Init(void);
extern void timer6Init(void);
//IOC------------------------------------------
extern void iocInit(void);
typedef struct
{
    bool fg;
}_ioc;
extern _ioc ioc;  
//--------------------------------------//
//ADC 12bits
//--------------------------------------//
#define ADC_AverageMode
#define ADC_SamplingNum 8
typedef struct{
    uint16_t val[6];
    uint32_t sum[6];
    uint16_t avr[6];
    uint8_t ch;
    uint8_t cnt;
    bool completed;
}_adc;
extern _adc adcInfo;
extern void adcInit(void);    
//--------------------------------------//
//Clock Reference Output
//--------------------------------------//
extern void CLKREF_Init(void);
//--------------------------------------//
//CCP PWM
//--------------------------------------//
extern void CCP1_PWM_Init(void);

//--------------------------------------//
//PWM 16bits
//--------------------------------------//
typedef struct
{
    uint16_t val;
}_pwm;

extern _pwm pwm1,pwm2;
extern void pwm1Init(void);
extern void pwm2Init(void);
extern void pwm3Init(void);


#ifdef	__cplusplus
}
#endif

#endif	/* Q_PERIPHERAL27Q43_H */


```
```C:Q_Peripheral.c PWM1,PWM2の初期化
_pwm pwm1,pwm2;
//******************************************************//
// * PWM1初期化
// *****************************************************//
void pwm1Init(void)
{
    PWM1CLK=0x05;//MFINTOSC 500khz
    //PWM1PR=0x00EA;//15ms
    PWM1PR=0x0138;//20ms
    //PWM1PR=0x7EF;//100ms
    
    //PWM1PR=0x02FFF;
    PWM1CPRE=0x20;//prescaler
    PWM1S1P1H=0x00;
    PWM1S1P1L=0x00;
    PWM1S1P2H=0x00;
    PWM1S1P2L=0x00;
    PWM1S1CFG=0x00;
    
    //Clear PWM1_16BIT period interrupt flag
    PIR4bits.PWM1PIF = 0;
    //Clear PWM1_16BIT interrupt flag
    PIR4bits.PWM1IF = 0;  
    //Clear PWM1_16BIT slice 1, output 1 interrupt flag
    PWM1GIRbits.S1P1IF = 0;
    //Clear PWM1_16BIT slice 1, output 2 interrupt flag
    PWM1GIRbits.S1P2IF = 0;
    //PWM1_16BIT interrupt enable bit
    PIE4bits.PWM1IE = 0;
    //PWM1_16BIT period interrupt enable bit
    PIE4bits.PWM1PIE = 0;
   
    //PPS
    //6.PPS
    PPSLOCK = 0x55; 
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0;//Unlock.
    //RB4PPS=0x18;
    RC1PPS=0x18;
    RC2PPS=0x19;
    PPSLOCK = 0x55; 
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 1;//lock.
    PWM1CONbits.EN=1;
    
    pwm1.val=0x0000;
}

//******************************************************//
// * PWM2 初期化
// *****************************************************//
void pwm2Init(void)
{
    PWM2CLK=0x05;//MFINTOSC 500khz
    PWM2PR=0x00EA;//15ms
    //PWM2PR=0x7EF;//100ms
    //PWM2PR=0x02FFF;
    PWM2CPRE=0x20;//prescaler
    PWM2S1P1H=0x00;
    PWM2S1P1L=0x00;
    PWM2S1CFG=0x00;
    
    //Clear PWM1_16BIT period interrupt flag
    PIR5bits.PWM2PIF = 0;
    //Clear PWM1_16BIT interrupt flag
    PIR5bits.PWM2IF =0;
    //Clear PWM1_16BIT slice 1, output 1 interrupt flag
    PWM2GIRbits.S1P1IF=0;
    //Clear PWM1_16BIT slice 1, output 2 interrupt flag
    PWM2GIRbits.S1P2IF =0;
    //PWM1_16BIT interrupt enable bit
    PIE5bits.PWM2IE=0;
    //PWM1_16BIT period interrupt enable bit
    PIE5bits.PWM2PIE=0;
   
    //PPS
     //6.PPS
    PPSLOCK = 0x55; 
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0;//Unlock.
    RB0PPS=0x1A;
    RC5PPS=0x1B;
    PPSLOCK = 0x55; 
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 1;//lock.
    PWM2CONbits.EN=1;
    
    pwm2.val=0x0000;
}
```

```C:main.c

/*
 * File:   main.c
 * Author: yutak
 *
 * Created on 2022/12/29, 18:47
 */



// PIC18F27Q43 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1
#pragma config FEXTOSC = OFF    // External Oscillator Selection (Oscillator not enabled)
#pragma config RSTOSC = HFINTOSC_64MHZ// Reset Oscillator Selection (HFINTOSC with HFFRQ = 64 MHz and CDIV = 1:1)

// CONFIG2
#pragma config CLKOUTEN = OFF   // Clock out Enable bit (CLKOUT function is disabled)
#pragma config PR1WAY = OFF     // PRLOCKED One-Way Set Enable bit (PRLOCKED bit can be set and cleared repeatedly)
#pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)

// CONFIG3
#pragma config MCLRE = EXTMCLR  // MCLR Enable bit (If LVP = 0, MCLR pin is MCLR; If LVP = 1, RE3 pin function is MCLR )
#pragma config PWRTS = PWRT_OFF // Power-up timer selection bits (PWRT is disabled)
#pragma config MVECEN = ON      // Multi-vector enable bit (Multi-vector enabled, Vector table used for interrupts)
#pragma config IVT1WAY = ON     // IVTLOCK bit One-way set enable bit (IVTLOCKED bit can be cleared and set only once)
#pragma config LPBOREN = OFF    // Low Power BOR Enable bit (Low-Power BOR disabled)
#pragma config BOREN = SBORDIS  // Brown-out Reset Enable bits (Brown-out Reset enabled , SBOREN bit is ignored)

// CONFIG4
#pragma config BORV = VBOR_1P9  // Brown-out Reset Voltage Selection bits (Brown-out Reset Voltage (VBOR) set to 1.9V)
#pragma config ZCD = OFF        // ZCD Disable bit (ZCD module is disabled. ZCD can be enabled by setting the ZCDSEN bit of ZCDCON)
#pragma config PPS1WAY = OFF     // PPSLOCK bit One-Way Set Enable bit (PPSLOCKED bit can be cleared and set only once; PPS registers remain locked after one clear/set cycle)
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Low Voltage Programming Enable bit (Low voltage programming enabled. MCLR/VPP pin function is MCLR. MCLRE configuration bit is ignored)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Extended Instruction Set and Indexed Addressing Mode disabled)

// CONFIG5
#pragma config WDTCPS = WDTCPS_31// WDT Period selection bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = OFF       // WDT operating mode (WDT Disabled; SWDTEN is ignored)

// CONFIG6
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = SC      // WDT input clock selector (Software Control)

// CONFIG7
#pragma config BBSIZE = BBSIZE_512// Boot Block Size selection bits (Boot Block size is 512 words)
#pragma config BBEN = OFF       // Boot Block enable bit (Boot block disabled)
#pragma config SAFEN = OFF      // Storage Area Flash enable bit (SAF disabled)
#pragma config DEBUG = OFF      // Background Debugger (Background Debugger disabled)

// CONFIG8
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block not Write protected)
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers not Write protected)
#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM not Write protected)
#pragma config WRTSAF = OFF     // SAF Write protection bit (SAF not Write Protected)
#pragma config WRTAPP = OFF     // Application Block write protection bit (Application Block not write protected)

// CONFIG10
#pragma config CP = OFF         // PFM and Data EEPROM Code Protection bit (PFM and Data EEPROM code protection disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "Q_peripheral27Q43.h"
#include "Q_interrupt27Q43.h"
#include "Q_initialize.h"
#include "Q_I2C1.h"
#include "I2C_LCD.h"
#include "stringFormat.h"
#include "Q_SPI2.h"
#include "MCP23Sxx.h"
#include "famicon.h"

void portInit(void);
void oscillatorInit(void);
void vicInit(void);


void main(void)
{
    int16_t speed=0;
    uint8_t counter=0;
    uint16_t ledVal;
    uint8_t lcd_length;
    //CPUハード初期化-----------------------
    portInit();
    oscillatorInit();
    vicInit();
    
    //周辺機能初期化--------------------------------
    timer0Init();
    pwm1Init();
    pwm2Init();
    iocInit();
    usartInit();
    
    CLKREF_Init();
    I2C1_Init();
    SPI2_Init();
    
    //device initialize
    LCD_Init(LcdDeviceAdd);//100kHzで初期化
    //Clock Reference Output//I2C用クロックソース400KHz
    I2C1CLK = 0b00100;    
    MCP23S17_Init(MCP23S08_Device1Add);
    famiconInit();
    
    printf("START\n");    
    lcd_length=sprintf(LcdTextBuf,"START");
    LCD_Printf(LcdDeviceAdd,LcdTextBuf,lcd_length,0x80);
    
    INTCON0bits.GIE=1;//Enable all masked interrupts
    ledVal=0x55;
    while(1)
    {
        //Timer0 interrupt process-------
        if(tm0.fg)
        {
            tm0.fg=false;
            //Interrupt ADCC process----------
            
            SPI2_b3Write(MCP23S17_Device1Add,0x0A,ledVal);    //GPIOA 
            SPI2_b3Write(MCP23S17_Device1Add,0x1A,ledVal);
            if(ledVal==0x55)
            {
                ledVal=0xAA;
            }else
            {
                ledVal=0x55;
            }
            T0CON0bits.EN=1;
            PIE3bits.TMR0IE=1;
        } 
        
        //Usart interrupt process--------
        if(rxUsart.completed)
        {
            rxUsart.completed=false;
            printf("echo:%s\n",rxUsart.buf);
            rxUsart.length=0;
            PIE4bits.U1RXIE=1;
        }
        
        //Interrupt On Change process--------
        if(ioc.fg)
        {
            ioc.fg=false;
            printf("Switch ON:%d\n",counter);
            PORTBbits.RB1=~PORTBbits.RB1;
            counter++;
            PIE0bits.IOCIE=1;
        }

        //ここからPWM1，2を制御------------------
        famiconButtonState = getButton();//スーファミコントローラ押下取得
        
        if((famiconButtonState&0x0020)==0x0000)//L
        {//減速
            if(speed>=100)
                speed-=100;
        }

        if((famiconButtonState&0x0010)==0x0000)//R
        {//加速
            speed+=100;
            if(speed>4000)
            {
                speed=4000;
            }
        }                        

        lcd_length=sprintf(LcdTextBuf,"%04d",speed);
        LCD_Printf(LcdDeviceAdd,LcdTextBuf,lcd_length,0xC0);

        pwm1.val=speed;
        pwm2.val=speed;


        if((famiconButtonState&0x0800)==0x0000)//UP　前進
        {
            PWM1S1P1 = 0;
            PWM1S1P2 = pwm1.val/15;//4095/15=273(0x111)＜312(0x138)
            PWM2S1P1 = 0;
            PWM2S1P2 = pwm2.val/15;                
        }
        if((famiconButtonState&0x0400)==0x0000)//DOWN　更新
        {                
            PWM1S1P1 = pwm1.val/15;
            PWM1S1P2 = 0;
            PWM2S1P1 = pwm2.val/15;
            PWM2S1P2 = 0;                
        }
        if((famiconButtonState&0x0200)==0x0000)//LEFT　左折
        {
            PWM1S1P1 = pwm1.val/15;
            PWM1S1P2 = 0;
            PWM2S1P1 = 0;
            PWM2S1P2 = pwm2.val/15;
        }
        if((famiconButtonState&0x0100)==0x0000)//RIGHT　右折
        {
            PWM1S1P1 = 0;
            PWM1S1P2 = pwm1.val/15;
            PWM2S1P1 = pwm2.val/15;
            PWM2S1P2 = 0;
        }
        if((famiconButtonState==0xFFF0))//No push button　静止状態
        {
            PWM1S1P1 =0;
            PWM1S1P2 =0;
            PWM2S1P1 =0;
            PWM2S1P2 =0;
        }

        PWM1CONbits.LD=1;
        while(PWM1CONbits.LD);

        PWM2CONbits.LD=1;
        while(PWM2CONbits.LD); 
           
    }
    return;
}

void oscillatorInit(void)
{
    //オシレータ設定----------------
    OSCCON3bits.CSWHOLD=1;//Hold
    OSCCON1bits.NDIV=1;//64Mhz/2=32Mhz;
    while(!OSCCON3bits.NOSCR);
    while(!PIR0bits.CSWIF);//ready state
    PIR0bits.CSWIF=0;
    OSCCON3bits.CSWHOLD=0;
    while(!OSCCON3bits.ORDY);
}

void portInit(void)
{
    //ポート設定----------------------    
    PORTA=0x00;
    LATA=0x00;
    ANSELA=0x00;
    TRISA=0x00;
    
    PORTB=0x00;
    LATB=0x00;
    ANSELB=0x00;
    TRISB=0x00;
    
    PORTC=0x00;
    LATC=0x00;
    ANSELC=0x00;
    TRISC=0x00;
    
     //PPS---------------------
    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 0;
    
    //I2C1-------------------------
    //RC4 for SDA
    RC4PPS=0x38;
    I2C1SDAPPS=0x14;
    //RC3 for SCL
    RC3PPS = 0x37;
    I2C1SCLPPS=0x13;
    
    PPSLOCK = 0x55;
    PPSLOCK = 0xAA;
    PPSLOCKbits.PPSLOCKED = 1;
    
    ODCONCbits.ODCC3=1;
    ODCONCbits.ODCC4=1;
    
    RC3I2Cbits.TH=1;
    RC4I2Cbits.TH=1;
    
}

void vicInit(void)
{
 //割り込みテーブルaddress設定----------------------------------
    INTCON0bits.GIE=0;//Enable all masked interrupts
    IVTLOCK=0x55;
    IVTLOCK=0xAA;
    IVTLOCKbits.IVTLOCKED=0;
    IVTBASE = 0x000008;
    IVTLOCK=0x55;
    IVTLOCK=0xAA;
    IVTLOCKbits.IVTLOCKED=1;
}
```