TOP > MPLAB XC8編(PIC16F886) > I2CでEEPROMを使う(PIC16F886 XC8) > ソース
I2CでEEPROMを使う(ソース)
(PIC16F886 XC8)
| 作成日2012.6.24 |
以下のソースを取り込んで、コンパイル→PIC書き込み→実行して下さい。
// ========================== ここから ==============================
//ファイル名 I2C_EEPROM.c
//作成日 2010.10.9
//更新日 2012.6.23
//作成者 mit.ueno
//バージョン 1.1
//コンパイラ MPLAB XC8
//PIC PIC16F886
//クロック 8MHz(INTIO)
//
//概要
// EEPROMの動作確認
// I2C使用(マスタモード)
//
//使用ポート
// RC3:RTC(SCL)
// RC4:RTC(SDA)
//
// RC6:LCD(RS)
// RC7:LCD(E)
// RB4:LCD(DB4)
// RB5:LCD(DB5)
// RB6:LCD(DB6)
// RB7:LCD(DB7)
//
// LCD_V0 : 350ΩでGND
// LCD_R/W : GND
// LCD_DB0-3: open
//
#include "pic.h"
#define LCD_E RC7
#define LCD_RS RC6
#define I2C_SCL RC3
#define I2C_SDA RC4
#define I2C_SDA_TRIS TRISC4
#define EE_dev_addr 0xA0
#define EE_P0_0 0x00
#define EE_P0_1 0x02
static void pic_init();
static void I2C_start();
static void I2C_restart();
static void I2C_send(unsigned char);
static unsigned char I2C_ackchk();
static void I2C_acksnd();
static void I2C_nacksnd();
static unsigned char I2C_rcv();
static void I2C_snd_char(unsigned char EE_P0 ,unsigned char addr1 ,unsigned char addr2 ,unsigned char send_data);
static unsigned char I2C_rcv_char(unsigned char EE_P0 ,unsigned char addr1 ,unsigned char addr2);
static void I2C_stop();
static void LCD_init();
static void LCD_ival();
static void LCD_cmd(unsigned char);
static void LCD_data(unsigned char);
static void LCD_hex(unsigned char, unsigned char);
static void LCD_send4(unsigned char);
static void wait_50us();
static void wait_1ms();
static void wait_ms(unsigned char);
__CONFIG(FOSC_INTRC_NOCLKOUT & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_OFF & IESO_OFF & LVP_OFF);
const unsigned char hex_tbl[16] = "0123456789ABCDEF";
// ==================== メイン処理 ===========================
main() {
unsigned char i;
unsigned char c;
pic_init(); // PICの初期化
LCD_init(); // LCDの初期化
LCD_ival(); // LCD初期表示
c = 0xAA;
LCD_hex(0x82, c);
I2C_snd_char(EE_P0_0 ,0xA1 ,0x00 ,c);
wait_ms(5);
c = 0xBB;
LCD_hex(0x86, c);
I2C_snd_char(EE_P0_1 ,0xA1 ,0x00 ,c);
wait_ms(5);
c = I2C_rcv_char(EE_P0_0 ,0xA1 ,0x00); // read
LCD_hex(0xC2, c);
c = I2C_rcv_char(EE_P0_1 ,0xA1 ,0x00); // read
LCD_hex(0xC6, c);
while(1) {}
}
// ==================== PICの初期化 ===========================
static void pic_init() {
OSCCON = 0x70; // INTOSC 8MHz
ANSEL = 0x00; // AN未使用
TRISB = 0x0F; // RB4-7:out
TRISC = 0x3F; // RC3,6-7:out SDA/SCL:input
PORTB = 0x00;
PORTC = 0x00;
SSPCON = 0x28; // SSP enable & I2C Master mode, clock = FOSC / (4 * (SSPADD+1))
SSPADD = 0x02; // 0x00だと動作しない
return;
}
// ==================== I2C Start =============================
static void I2C_start() {
SEN = 1;
while (SEN) {}
return;
}
// ==================== I2C Start Repeat ======================
static void I2C_restart() {
SSPIF = 0;
RSEN = 1;
while (RSEN) {}
return;
}
// ==================== I2C Stop ==============================
static void I2C_stop() {
SSPIF = 0;
PEN = 1;
while (PEN) {}
SSPIF = 0;
return;
}
// ==================== I2C Send ==============================
static void I2C_send(unsigned char send_data) {
SSPIF = 0;
SSPBUF = send_data;
while (!SSPIF) {}
return;
}
// ==================== I2C Recive ============================
static unsigned char I2C_rcv() {
SSPIF = 0;
RCEN = 1;
while (RCEN) {}
return(SSPBUF);
}
// ==================== I2C Send char ==========================
static void I2C_snd_char(unsigned char ee_p0 ,unsigned char addr1 ,unsigned char addr2 ,unsigned char send_data) {
I2C_start();
I2C_send(EE_dev_addr | ee_p0); // スレーブアドレス & Write
if (I2C_ackchk()) {
LCD_data('4');
}
I2C_send(addr1); // 書き込みアドレス1
if (I2C_ackchk()) {
LCD_data('5');
}
I2C_send(addr2); // 書き込みアドレス2
if (I2C_ackchk()) {
LCD_data('6');
}
I2C_send(send_data); // 書き込み
if (I2C_ackchk()) {
LCD_data('7');
}
I2C_stop();
return;
}
// ==================== I2C Recive char ========================
static unsigned char I2C_rcv_char(unsigned char ee_p0 ,unsigned char addr1 ,unsigned char addr2) {
unsigned char c;
I2C_start();
I2C_send(EE_dev_addr | ee_p0); // スレーブアドレス & Write
if (I2C_ackchk()) {
LCD_data('8');
}
I2C_send(addr1); // 読み出しアドレス1
if (I2C_ackchk()) {
LCD_data('9');
}
I2C_send(addr2); // 読み出しアドレス2
if (I2C_ackchk()) {
LCD_data('A');
}
I2C_start();
I2C_send(EE_dev_addr | ee_p0 | 0x01); // スレーブアドレス & Read
if (I2C_ackchk()) {
LCD_data('B');
}
c = I2C_rcv();
I2C_nacksnd();
I2C_stop();
return(c);
}
// ==================== I2C ACK check =========================
static unsigned char I2C_ackchk() {
unsigned char i2c_data;
if (ACKSTAT) {
i2c_data = 0xFF;
} else {
i2c_data = 0x00;
}
return(i2c_data);
}
// ==================== I2C ACK send ==========================
static void I2C_acksnd() {
ACKDT = 0;
ACKEN = 1;
while (ACKEN) {}
return;
}
// ==================== I2C NACK send =========================
static void I2C_nacksnd() {
ACKDT = 1;
ACKEN = 1;
while (ACKEN) {}
return;
}
// ==================== LCD 初期表示 ==========================
static void LCD_ival() {
// 0123456789abcdef
// W
// R
LCD_cmd(0x80);
LCD_data('W');
LCD_cmd(0xC0);
LCD_data('R');
return;
}
// ==================== LCD 4bit 送信 =========================
static void LCD_send4(unsigned char c) {
PORTB = (PORTB & 0x0F) | (c << 4);
LCD_E = 1;
NOP();
LCD_E = 0;
return;
}
// ==================== LCDコマンドWRITE =================
static void LCD_cmd(unsigned char cmd) {
LCD_RS = 0;
PORTB = (PORTB & 0x0F) | (cmd & 0xF0);
LCD_E = 1; // 上位4ビット書き込み
NOP();
LCD_E = 0;
PORTB = (PORTB & 0x0F) | (cmd <<4);
LCD_E = 1; // 下位4ビット書き込み
NOP();
LCD_E = 0;
wait_50us();
return;
}
// ==================== LCDデータWRITE =================
static void LCD_data(unsigned char cmd) {
LCD_RS = 1;
PORTB = (PORTB & 0x0F) | (cmd & 0xF0);
LCD_E = 1; // 上位4ビット書き込み
NOP();
LCD_E = 0;
PORTB = (PORTB & 0x0F) | (cmd <<4);
LCD_E = 1; // 下位4ビット書き込み
NOP();
LCD_E = 0;
wait_50us();
return;
}
// =============== 1バイトを16進数でLCDに出力 ==========
static void LCD_hex(unsigned char addr, unsigned char ad) {
LCD_cmd(addr);
LCD_data(hex_tbl[ad>>4]);
LCD_data(hex_tbl[ad & 0x0F]);
}
// ==================== LCDの初期化 ===========================
static void LCD_init() {
wait_ms(15);
LCD_E = 0;
LCD_RS = 0;
LCD_send4(0x03); // DB4-7に'3'を出力(8bitモードに)@
wait_ms(5);
LCD_send4(0x03); // DB4-7に'3'を出力(8bitモードに)A
wait_ms(1);
LCD_send4(0x03); // DB4-7に'3'を出力(8bitモードに)B
wait_ms(1);
LCD_send4(0x02); // DB4-7に'2'を出力(4bitモードに)
wait_ms(1);
// ここからは4bitモードで、Busyフラグが使える
LCD_cmd(0x28); // DL=0:4bit ,N=1:2lines ,F=0:5*7dot
LCD_cmd(0x08); // Display off
LCD_cmd(0x0C); // Display on ,cursor on ,no blink
LCD_cmd(0x06); // Entry mode (Inc ,No Shift)
LCD_cmd(0x01); // Clear Display
wait_ms(2);
return;
}
// ==================== 50μSウェイトルーチン =================
static void wait_50us() {
unsigned char i;
for (i=32 ; i>0 ; i--) {}
return;
}
// ==================== 1mSウェイトルーチン =================
static void wait_1ms() {
unsigned char i;
for (i=179 ; i>0 ; i--) {
NOP();
NOP();
NOP();
}
return;
}
// ==================== 1mS×ms ウェイトルーチン =============
static void wait_ms(unsigned char ms) {
unsigned char c;
for (c=ms ; c>0 ; c--) {
wait_1ms();
}
return;
}
// ========================== ここまで ==============================