Q43のSPI通信
MSSPからの変更点
・送信バッファと、受信バッファが用意された。
・送信ビット数、送信バイト数をカウントするレジスタ
・LSBとMSBを逆転できるようなった。
・SPIの4線それぞれに、極性を指定できる。
・ボーレートの計算が楽。
1.SPIモジュールの初期化
SPI1モジュールはI2C1モジュールとデフォルトピンが競合しているので、
SPI2モジュールを使用します。
1.1 SPI2のピン割り付け
ピン番号 | ピン名 | 機能 | SPI端子名 |
---|---|---|---|
23 | RB2 | SPI2 | SDI |
24 | RB3 | SPI2 | CLK |
25 | RB4 | SPI2 | SDO |
26 | RB5 | SPI2 | /CS |
※PPS機能を使えば、主にPORTB、PORTCに割り付けることができます。
※CSピンだけは、モジュールで駆動しないで、ユーザーがポート端子を操作するようにしました。SPIモジュールで自動制御もできまが、SPIモジュールが複数あった場合は、汎用のIOピン制御になります。
※CSピンをハードウェアで制御するばあいは、ポートA、ポートCに割り付けることができます。
//SPI2 pin setting-------------------
TRISB|=0x04; //RB2:SDI input
//PPS
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCKbits.PPSLOCKED = 0;//Unlock.
SPI2SDIPPS=0x0A;//RB2;
RB3PPS=0x34; //SPI2 CLK
RB4PPS=0x35; //SPI2 SDO
//RB5PPS=0x36; //SPI2 SS
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCKbits.PPSLOCKED = 1;//lock.
#define SPI2_CS PORTBbits.RB5
1.2 SPI2モジュールの初期化
まず、SPIクロックの極性と、サンプリング位置を設定します。
Clientデバイスの規定にあわせて、SPIクロック波形をこの3ビットで決定します。今回は、MCP23S17に合わせて設定しました。
同じレジスタで、チップセレクトピンの極性を設定しておきます。SSPビットをセットします。これで、ハードウェアでCSピンを制御する場合、CSピンが自動で、Active low出力されます。
SPI2CON1=0x44; //SMP:0,CKE:1,CKP:0,SSP:1 active low
1.3 SPIモジュール ホストモード
HOSTモードは4種類。全二重、受信のみ、送信のみ、NoTransfers。
送信、受信ともに同時に行いたいので、Full Duplex modeを選択します。TRXビット、RXTビットをセットします。
SPI2CON2=0x03; //TXR=1 RXR=1; Full Duplex mode
1.3 SPIクロックソース
SPIのクロックソースを選びます。
MSSPモジュールよりも高速に設定できようになりました。
システムクロックFoscは、32Mhzです。
クロックソースをFoscシステムクロック(32Mhz)に設定します。この入力クロックを上記式を用いて、減速して8Mhzに設定しました。
SPI2CLK=0b00000;//Fosc=32Mhz
SPI2BAUD=0x1; //8Mhz n=1 32Mhz/(2*(1+1))
1.4 ビットカウントの仕方を設定
送信、受信カウンタを設定します。ビット単位または、バイト単位でカウントするかを決定します。
SPICON0レジスタのBMODEビットで選択します。
今回は、BMODE=1とし、8ビット単位でカウントするように設定しました。8ビット長の指定は、後述のSPIxTWIDEで設定します。
SPI2CON0=0x03; //MST:1 BMODE:1
同じレジスタの、MSTビットもセットしておきます。SPIバスをHostとして使用するか、Clientとして使用するかを決定するビットです。Hostとしてバスを使用するので1をセットしています。
1.5 データの大きさをビットで指定。
BMODE=1の場合、 SPI2TWIDTHレジスタに、1データのビット長をセットしておきます。送信データ長を3ビットで指定します。ということは、通常は8ビットで構成されているデータを3ビットや、5ビットにして送信することもできるはずです。
今回は、データは通常どうりの、8ビットで構成されているので、8をセットします。
SPI2TWIDTH=8; //1データビット数(8bitデータ)
SPI2CNTレジスタは、BMODE=1の場合、送受信のデータ数をその都度、プログラムの中でセットします。
1.6 SPI2モジュールの有効化
最後にSPI2モジュールを有効にします。EN=1の時は、設定が有効になりませんので、EN=0で設定して、EN=1で、モジュールの設定を確定させます。
SPI2CON0bits.EN=1;
2.Q43 SPIコード
・CSピンだけは、ソフトウェアで制御しています。
・通信の開始は、BusyフラグでモジュールがIdle状態か、確認したのちに、CSピンをLOWにして、通信を開始しています。通信の終了もCSピンで制御して、Highにして終了です。
・送信バッファに1バイトデータを書きこむと、ハードが8クロック出力し、受信バッファに8ビットデータが格納されます。
・読込だけ行うときは、ダミーデータ(0xFF)をクライアントに送信して、受信バッファから、データを読み出します。
#ifndef Q_SPI2_H
#define Q_SPI2_H
#ifdef __cplusplus
extern "C" {
#endif
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "Q_peripheral27Q43.h"
#define SPI2_CS PORTBbits.RB5
typedef struct{
uint8_t val;
bool errorCode;
}SPI_RD;
extern void SPI2_Init(void);
extern void SPI2_START(void);
extern void SPI2_STOP(void);
extern SPI_RD SPI2_b3Write(uint8_t _val, int8_t _data1, int8_t _data2);
extern SPI_RD SPI2_bnWrite(uint8_t _num, uint8_t* _data);
extern SPI_RD SPI2_b1Read(uint8_t _val, uint8_t _data1);
extern SPI_RD SPI2_b1Write(uint8_t _val);
extern void SPI2_SetTotalCount(uint16_t _val);
extern uint16_t SPI2_GetTotalCount(void);
extern SPI_RD SPI2_Write(uint8_t _val);
#ifdef __cplusplus
}
#endif
#endif /* Q_SPI2_H */
#include "Q_SPI2.h"
//****************************************//
//* SPI2_Init *//
//SPI2モジュール初期化
//****************************************//
void SPI2_Init(void)
{
//SPI2 pin setting-------------------
TRISB|=0x04; //RB2:SDI input
//PPS
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCKbits.PPSLOCKED = 0;//Unlock.
SPI2SDIPPS=0x0A; //RB2;
RB3PPS=0x34; //SPI2 CLK
RB4PPS=0x35; //SPI2 SDO
//RB5PPS=0x36; //SPI2 SS
PPSLOCK = 0x55;
PPSLOCK = 0xAA;
PPSLOCKbits.PPSLOCKED = 1;//lock.
//SPI2 Configration----------------
SPI2CON1=0x44; //CKE:1, SSP:1 active low
SPI2CON2=0x03; //TXR=1 RXR=1; Full Duplex mode
SPI2CLK=0b00000;//Fosc=32Mhz
SPI2BAUD=0x1; //8Mhz n=1 32Mhz/(2*(1+1))
SPI2CON0=0x03; //MST:1 BMODE:1
SPI2TWIDTH=8; //1データビット数
SPI2CON0bits.EN=1;
SPI2_CS=1;
}
//****************************************//
//* SPI2_START *//
//****************************************//
void SPI2_START(void)
{
uint8_t timeUp=0;
while(SPI2CON2bits.BUSY)
{
timeUp++;
if(timeUp>200)
{
return;
}
};
SPI2_CS=0;
}
//****************************************//
//* SPI2_STOP *//
//****************************************//
void SPI2_STOP(void)
{
SPI2_CS=1;
}
//****************************************//
//* SPI2_SetTotalCount *//
//_val:ビット数またはバイト数(BMODEによる)
//****************************************//
#define BMODE 1
void SPI2_SetTotalCount(uint16_t _val)
{
#if BMODE
SPI2TCNT=_val;//バイト数
#else
SPI2TWIDTH = (uint8_t)(_val&0x0007);
SPI2TCNT=_val>>3;
#endif
}
//****************************************//
//* SPI2_SetTotalCount *//
//return: SPI2CNT値 または、SPI2CNT&SPI2WIDHT値
//****************************************//
uint16_t SPI2_GetTotalCount(void)
{
uint16_t ret;
#if BMODE
ret=SPI2TCNT;
printf("byteNum=%d\n",ret);
#else
ret = SPI2TCNT;
ret = ret<<3 | SPI2TWIDTH;
printf("bitNum=%d\n",ret);
#endif
return ret;
}
//****************************************//
//* SPI2_Write *//
//_val:送信データ
//****************************************//
SPI_RD SPI2_Write(uint8_t _val)
{
SPI_RD spiRD;
uint8_t val,timeUp;
spiRD.errorCode=false;
SPI2TXB=_val;
timeUp=0;
while(PIR5bits.SPI2RXIF == 0)
{
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
spiRD.val=SPI2RXB;
spiRD.errorCode=true;
return spiRD;
}
//****************************************//
//* SPI2_bnWrite *//
//nバイト送信関数
//_num:送信数(バイト数)
//_data:送信バッファ先頭アドレス
//****************************************//
SPI_RD SPI2_bnWrite(uint8_t _num, uint8_t* _data)
{
uint8_t val,timeUp;
SPI_RD spiRD;
SPI2_START();
SPI2_SetTotalCount(_num);//bit Counter set
do{
SPI2TXB=*_data++;
timeUp=0;
while(PIR5bits.SPI2RXIF == 0)
{
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
val=SPI2RXB;
}while(--_num);
SPI2_STOP();
spiRD.val=val;
spiRD.errorCode=true;
return spiRD;
}
//****************************************//
//* SPI2_b1Write *//
//1バイト送信関数
//_val:送信データ
//return:自作Spiデータ構造体
//****************************************//
SPI_RD SPI2_b1Write(uint8_t _val)
{
SPI_RD spiRD;
uint8_t val,timeUp;
spiRD.errorCode=false;
SPI2_SetTotalCount(1);//送信バイト数セット
SPI2_START(); //CS High=>Low
SPI2TXB=_val; //送信データセット
timeUp=0;
while(PIR5bits.SPI2RXIF == 0)//送信完了待ちを受信フラグで確認
{
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
val=SPI2RXB; //バイト読み出し
SPI2_STOP(); //CS Low=>High
spiRD.val=SPI2RXB;//結果を構造体に格納。
spiRD.errorCode=true;
return spiRD;
}
//****************************************//
//* SPI2_b3Write *//
//3バイト送信関数
//_val:送信データ
//_data1:送信データ
//_data2:送信データ
//****************************************//
SPI_RD SPI2_b3Write(uint8_t _val, int8_t _data1, int8_t _data2)
{
SPI_RD spiRD;
uint8_t val,timeUp;
uint8_t bitNum;
spiRD.errorCode=false;
SPI2_SetTotalCount(3);
SPI2_START();
SPI2_GetTotalCount();
SPI2TXB=_val;
timeUp=0;
while(PIR5bits.SPI2RXIF == 0)
{
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
SPI2_GetTotalCount();
val=SPI2RXB;
SPI2TXB=_data1;
timeUp=0;
while(PIR5bits.SPI2RXIF == 0){
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
SPI2_GetTotalCount();
val=SPI2RXB;
SPI2TXB=_data2;
timeUp=0;
while(PIR5bits.SPI2RXIF == 0){
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
val=SPI2RXB;
SPI2_STOP();
spiRD.val=SPI2RXB;
spiRD.errorCode=true;
SPI2_GetTotalCount();
return spiRD;
}
//****************************************//
//* SPI2_b1Read *//
//1バイト受信関数(2バイト送信後)
//_val:送信データ
//_data:送信データ
//return:SPI_RD構造体(受信データ)
//****************************************//
SPI_RD SPI2_b1Read(uint8_t _val, uint8_t _data1)
{
SPI_RD spiRD;
uint8_t val,timeUp;
SPI2_SetTotalCount(3);
SPI2_START();
//1.SPIアドレス送信
SPI2TXB=_val;
timeUp=0;
while(PIR5bits.SPI2RXIF == 0)
{
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
val=SPI2RXB;
//2.レジスタアドレス送信
SPI2TXB=_data1;
timeUp=0;
while(PIR5bits.SPI2RXIF == 0)
{
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
val=SPI2RXB;
//3.レジスタ値受信
SPI2TXB=0xFF;//dummy tx data
timeUp=0;
while(PIR5bits.SPI2RXIF == 0)
{
timeUp++;
if(timeUp>200)
{
return spiRD;
}
};
val=SPI2RXB;
SPI2_STOP();
spiRD.val=val;
spiRD.errorCode=true;
return spiRD;
}
#ifndef MCP23S17_H
#define MCP23S17_H
#ifdef __cplusplus
extern "C" {
#endif
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "Q_peripheral27Q43.h"
#include "Q_SPI2.h"
#define MCP23S17_deviceAdd1 0x4E
#define MCP23S17_deviceAdd2 0x46
/*-----------------------------------*/
//MCP23S08 I/O expander
/*-----------------------------------*/
#define MCP23S08_Device1Add 0x40
#define MCP23S08_Device2Add 0x42
#define MCP23S_R 1
#define MCP23S_W 0
typedef enum
{
IODIR=0x00,
IPOL,
GPINTEN,
DEFVAL,
INTCN,
IOCON,
GPPU,
mINTF,
INTCAP,
GPIO,
OLAT=0x0A
}_reg;
extern unsigned char reg_value[10];
extern uint8_t MCP23S_buf[30];
extern SPI_RD MCP23S08_Init(uint8_t _device_add);
/*-----------------------------------*/
//MCP23S17 I/O expander
/*-----------------------------------*/
#define MCP23S17_Device1Add 0x4E
extern SPI_RD MCP23S17_Init(uint8_t _device_add);
#ifdef __cplusplus
}
#endif
#endif /* MCP23S17_H */
#include "MCP23Sxx.h"
/*-----------------------------------*/
//MCP23S08 I/O expander
//_device_add:デバイスアドレス
//return:SPI_RD構造体
/*-----------------------------------*/
SPI_RD MCP23S08_Init(uint8_t _device_add)
{
SPI_RD spiRD;
uint8_t i;
for(i=0x00; i<0x0A; i++)
{
SPI2_b3Write(MCP23S08_Device1Add,i,0x00);
}
SPI2_b3Write(MCP23S08_Device1Add,IODIR,0x00);
SPI2_b3Write(MCP23S08_Device1Add,IOCON,0x38);
SPI2_b3Write(MCP23S08_Device2Add,IODIR,0x00);
SPI2_b3Write(MCP23S08_Device2Add,IOCON,0x38);
spiRD.errorCode=true;
for(i=0x00; i<=0x0A; i++)
{
spiRD=SPI2_b1Read(MCP23S08_Device1Add|0x01,i);
printf("[%02x]=%02x\n",i,spiRD.val);
}
putch('\n');
for(i=0x00; i<=0x0A; i++)
{
spiRD=SPI2_b1Read(MCP23S08_Device2Add|0x01,i);
printf("[%02x]=%02x\n",i,spiRD.val);
}
return spiRD;
}
/*-----------------------------------*/
//MCP23S17 I/O expander
/*-----------------------------------*/
SPI_RD MCP23S17_Init(uint8_t _device_add)
{
SPI_RD spiRD;
uint8_t i;
//Bank切り替え
SPI2_b3Write(MCP23S17_Device1Add,0x0A,0xA8);
__delay_ms(10);
//Bank=1
SPI2_b3Write(MCP23S17_Device1Add,0x00,0x00); //PORTA IO direction
SPI2_b3Write(MCP23S17_Device1Add,0x10,0x00); //PORTB IO direction
SPI2_b3Write(MCP23S17_Device1Add,0x09,0x00); //GPIOA
SPI2_b3Write(MCP23S17_Device1Add,0x19,0x00); //GPIOB
spiRD.errorCode=true;
//設定確認のレジスタ読み出し
printf("MCP23S17 init\n");
for(i=0x00; i<=0x0A; i++)
{
spiRD=SPI2_b1Read(MCP23S17_Device1Add|0x01,i);
printf("[%02x]=%02x\n",i,spiRD.val);
}
for(i=0x10; i<=0x1A; i++)
{
spiRD=SPI2_b1Read(MCP23S17_Device1Add|0x01,i);
printf("[%02x]=%02x\n",i,spiRD.val);
}
putch('\n');
return spiRD;
}
/*
* 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"
void portInit(void);
void oscillatorInit(void);
void vicInit(void);
void main(void)
{
uint8_t counter=0;
uint16_t ledVal;
//CPUハード初期化-----------------------
portInit();
oscillatorInit();
vicInit();
//周辺機能初期化--------------------------------
timer0Init();
iocInit();
usartInit();
adcInit();
SPI2_Init();
MCP23S17_Init(0x4E);
printf("START\n");
INTCON0bits.GIE=1;//Enable all masked interrupts
while(1)
{
//Timer0 interrupt process-------
if(tm0.fg)
{
tm0.fg=false;
//Interrupt ADCC process----------
if(adcInfo.completed)
{
adcInfo.completed=false;
printf("ANA2:%02X %4d\n",adcInfo.val[0],adcInfo.val[0]);
//LED点灯
ledVal = adcInfo.val[0];
SPI2_b3Write(MCP23S17_Device1Add,0x0A,(uint8_t)ledVal);
ledVal >>=8;
SPI2_b3Write(MCP23S17_Device1Add,0x1A,(uint8_t)ledVal);
//ADCC復帰処理
PIE1bits.ADIE=1;
PIE3bits.TMR2IE=1;
T2CONbits.TMR2ON=1;
}
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;
}
}
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;
}