I2C 読み出しタイミング(2-5フレーム)
CH1: SCL, CH2: SDA, CH3:トリガ(T)用の信号
トリガ信号のフォールエッジでトリガ
5番目のフレーム(右端)は読みだされたデータ(0xAA)+Nack(1)
最期がNackだとEEPROMは終了と判断
最も右端にストップコンディション
テストパターンを書いてみました
すべてのアドレス(0 - 8191番地)に0xAAを書き込み、その後読み出すという単純なものです。上記波形を観測したプログラムです。
ソースコード
PIC 18F4553
MPLAB X IDE, XC8
main.c
#include <xc.h>
#include <p18f4553.h>
#include <stdio.h>
#include <math.h>
#pragma config CPUDIV = OSC2_PLL3 //[Primary Oscillator Src: /2][96 MHz PLL Src: /3]
#pragma config PLLDIV = 5 //Divide by 5 (20 MHz oscillator input)
#pragma config USBDIV = 2 //USB clock source comes from the 96 MHz PLL divided by 2
#pragma config FCMEN = OFF //Fail-Safe Clock Monitor disabled
#pragma config IESO = OFF //Oscillator Switchover mode disabled
#pragma config FOSC = HS //HS oscillator (HS)
#pragma config PWRT = OFF //PWRT disabled
#pragma config VREGEN = OFF //USB voltage regulator disabled
#pragma config BORV = 3 //Minimum setting
#pragma config BOR = ON //Brown-out Reset enabled in hardware only (SBOREN is disabled)
#pragma config WDTPS = 32768 //1:32768
#pragma config WDT = OFF //WDT disabled (control is placed on the SWDTEN bit)
#pragma config CCP2MX = OFF //CCP2 input/output is multiplexed with RB3
#pragma config PBADEN = OFF //PORTB<4:0> pins are configured as digital I/O on Reset
#pragma config MCLRE = ON //MCLR pin enabled; RE3 input pin disabled
#pragma config LPT1OSC = OFF //Timer1 configured for higher power operation
#pragma config STVREN = ON //Stack full/underflow will cause Reset
#pragma config DEBUG = OFF //Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
#pragma config ICPRT = OFF //ICPORT disabled
#pragma config LVP = OFF //Single-Supply ICSP disabled
#pragma config XINST = OFF //Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
#pragma config CP0 = OFF //Block 0 (000800-001FFFh) is not code-protected
#pragma config CP1 = OFF //Block 1 (002000-003FFFh) is not code-protected
#pragma config CP2 = OFF //Block 2 (004000-005FFFh) is not code-protected
#pragma config CP3 = OFF //Block 3 (006000-007FFFh) is not code-protected
#pragma config CPB = OFF //Boot block (000000-0007FFh) is not code-protected
#pragma config CPD = OFF //Data EEPROM is not code-protected
#pragma config WRT0 = OFF //Block 0 (000800-001FFFh) is not write-protected
#pragma config WRT1 = OFF //Block 1 (002000-003FFFh) is not write-protected
#pragma config WRT2 = OFF //Block 2 (004000-005FFFh) is not write-protected
#pragma config WRT3 = OFF //Block 3 (006000-007FFFh) is not write-protected
#pragma config WRTB = OFF //Boot block (000000-0007FFh) is not write-protected
#pragma config WRTC = OFF //Configuration registers (300000-3000FFh) are not write-protected
#pragma config WRTD = OFF //Data EEPROM is not write-protected
#pragma config EBTR0 = OFF //Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks
#pragma config EBTR1 = OFF //Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks
#pragma config EBTR2 = OFF //Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks
#pragma config EBTR3 = OFF //Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks
#pragma config EBTRB = OFF //Boot block (000000-0007FFh) is not protected from table reads executed in other blocks
#define LED PORTEbits.RE2 //Sens Time
void i2c_init(void);
void i2c_enable(void);
void lcd_init(void);
void lcd_clear(void);
void lcd_write(unsigned char, unsigned char, const unsigned char*);
void EEPROM_24lc64_write(unsigned int, unsigned char);
unsigned char EEPROM_24lc64_read(unsigned int);
#define _XTAL_FREQ 10000000 //__delay_ms
void delay_us(int time){
int i;
for(i = 0; i < time; i++) __delay_us(1);
}
void delay_ms(int time){
int i;
for(i = 0; i < time; i++) __delay_ms(1);
}
void init(void){
OSCCONbits.SCS = 0; //Primary OSC 10MHz
ADCON1 = 0b00001111; // All Digital
CMCON = 0b00000111; // No Comparator
TRISA = 0b00000000;
TRISB = 0b00000000;
TRISC = 0b00000000;
TRISD = 0b00000000;
TRISE = 0b00000011;
LATA = 0b00000000;
LATB = 0b00000000;
LATC = 0b00000000;
LATD = 0b00000000;
LATE = 0b00000000;
}
void main(void){
unsigned int eeprom_address;
unsigned char get_val;
char string[10];
init();
i2c_init();
i2c_enable();
lcd_init();
lcd_clear();
while(1){
LED = 1;
for(int i = 0; i < 8191; i++){
sprintf(string, "ADR:%4d", i);
lcd_write(0, 0, string);
eeprom_address = i;
EEPROM_24lc64_write(eeprom_address, 0xAA);
lcd_write(0, 1, "WDT:0xAA");
delay_ms(10);
}
for(int i = 0; i < 8191; i++){
sprintf(string, "ADR:%4d", i);
lcd_write(0, 0, string);
eeprom_address = i;
get_val = EEPROM_24lc64_read(eeprom_address);
sprintf(string, "RDT:0x%2X", get_val);
lcd_write(0, 1, string);
delay_ms(10);
}
lcd_clear();
LED = 0;
delay_ms(3000);
} //while
} //main
i2c_24lc64.c
#include <xc.h>
#include <p18f4553.h>
#define EEPROM_24lc64_I2C_ADDR 0xA2
#define WRITE_MODE 0x00
#define READ_MODE 0x01
#define PROVE PORTCbits.RC0 //Prove
void delay_us(int);
void delay_ms(int);
void EEPROM_24lc64_write(unsigned int, unsigned char);
unsigned char EEPROM_24lc64_read(unsigned int);
void EEPROM_24lc64_write(unsigned int address, unsigned char data){
PROVE = 1;
SSPCON2bits.SEN = 1;
while(SSPCON2bits.SEN == 1);
SSPBUF = EEPROM_24lc64_I2C_ADDR | WRITE_MODE;
while(SSPSTATbits.BF);
delay_us(1);
if (SSPCON2bits.ACKSTAT){
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return;
}
SSPBUF = address >> 8;
while(SSPSTATbits.BF);
delay_us(1);
if (SSPCON2bits.ACKSTAT){
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return;
}
SSPBUF = address & 0x00FF;
while(SSPSTATbits.BF);
delay_us(1);
if (SSPCON2bits.ACKSTAT){
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return;
}
SSPBUF = data;
while(SSPSTATbits.BF);
delay_us(1);
if (SSPCON2bits.ACKSTAT){
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return;
}
delay_us(1);
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
PROVE = 0;
return;
}
unsigned char EEPROM_24lc64_read(unsigned int address){
unsigned char data;
PROVE = 1; //オシロスコープのトリガ用
SSPCON2bits.SEN = 1;
while(SSPCON2bits.SEN == 1);
SSPBUF = EEPROM_24lc64_I2C_ADDR | WRITE_MODE;
while(SSPSTATbits.BF);
delay_us(1);
if (SSPCON2bits.ACKSTAT){
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return;
}
PROVE = 0;
SSPBUF = address >> 8;
while(SSPSTATbits.BF);
delay_us(1);
if (SSPCON2bits.ACKSTAT){
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return;
}
SSPBUF = address & 0x00FF;
while(SSPSTATbits.BF);
delay_us(1);
if (SSPCON2bits.ACKSTAT){
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return;
}
SSPCON2bits.SEN = 1;
while(SSPCON2bits.SEN == 1);
SSPBUF = EEPROM_24lc64_I2C_ADDR | READ_MODE;
while(SSPSTATbits.BF);
delay_us(1);
if (SSPCON2bits.ACKSTAT){
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
return;
}
delay_us(1);
SSPCON2bits.RCEN = 1;
while(SSPCON2bits.RCEN);
while(SSPSTATbits.BF == 0);
data = SSPBUF;
SSPCON2bits.ACKDT = 1; //Nack
SSPCON2bits.ACKEN = 1; //マスタからNackを送る
PROVE = 0;
delay_us(1);
SSPCON2bits.PEN = 1;
while(SSPCON2bits.PEN);
//PROVE = 0;
return(data);
}
(JF1VRR)