TOP > MPLAB XC8編(PIC16F88) > I2CでEEPROMを使う(PIC16F88 XC8) > ソース
I2CでEEPROMを使う(ソース)
(PIC16F88 XC8)
| 作成日2012.6.10 |
以下のソースを取り込んで、コンパイル→PIC書き込み→実行して下さい。
// ========================== ここから ==============================
//ファイル名 I2C_EEPROM1.c
//作成日 2010.9.12
//更新日 2012.6.9
//作成者 mit.ueno
//バージョン 1.1
//コンパイラ MPLAB XC8
//PIC PIC16F88
//クロック 8MHz(INTIO)
//
//概要
// EEPROM(AT24C1024B)の動作確認
// I2C使用(マスタモード)ファームウェア制御
// SCL/SDAの無通信時の状態
// SCL output,1
// SDA input,1
//
// NOP() の数は20MHz動作前提
//
//使用ポート
// RB1:EEPROM(SDA)
// RB4:EEPROM(SCL)
//
// RB2:LCD(RS)
// RB3:LCD(E)
// RA0:LCD(DB4)
// RA1:LCD(DB5)
// RA2:LCD(DB6)
// RA3:LCD(DB7)
//
// LCD_V0 : 10KΩVRでGND
// LCD_R/W : GND
// LCD_DB0-3: open
//
// LCD表示形式
// 0123456789abcdef
// W xxxxxxxxxxxxxx
// R xxxxxxxxxxxxxx
//
// EEPROM_A1 : GND
// EEPROM_A2 : GND
// EEPROM_WP : GND
//
#include "pic.h"
#define LCD_E RB3
#define LCD_RS RB2
#define I2C_SCL RB4
#define I2C_SDA RB1
#define I2C_SDA_TRIS TRISB1
// EEPROMアドレス(I2Cフォーマット)
#define EE_dev_addr 0xA0 // EEPROMアドレス
#define EE_P0_0 0x00 // EEPROMメモリアドレス最上位ビット:0
#define EE_P0_1 0x02 // EEPROMメモリアドレス最上位ビット:1
static void pic_init();
static void I2C_start();
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_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_OFF & IESO_OFF & LVP_OFF);
const unsigned char hex_tbl[16] = "0123456789ABCDEF";
// ==================== メイン処理 ===========================
main() {
unsigned char c;
pic_init(); // PICの初期化
LCD_init(); // LCDの初期化
LCD_ival(); // LCD初期表示
// EEPROMに2バイト書き込む。そのデータをLCDに表示。
LCD_hex(0x82, 0xA5);
I2C_snd_char(EE_P0_0 ,0x00 ,0x00 ,0xA5);
wait_ms(5);
LCD_hex(0x84, 0x5B);
I2C_snd_char(EE_P0_1 ,0xFF ,0x00 ,0x5B);
wait_ms(5);
// EEPROMより2バイト読み込み、そのデータをLCDに表示。
c = I2C_rcv_char(EE_P0_0 ,0x00 ,0x00); // read
LCD_hex(0xC2, c);
c = I2C_rcv_char(EE_P0_1 ,0xFF ,0x00); // read
LCD_hex(0xC4, c);
while(1) {}
}
// ==================== PICの初期化 ===========================
static void pic_init() {
OSCCON = 0x70; // INTOSC 8MHz
ANSEL = 0x00; // AN未使用
TRISA = 0xF0; // RA0-3:out
TRISB = 0xE3; // RB2-4:out SDAは通常input(開放)
PORTA = 0x00;
PORTB = 0x12; // SCL=1,SDA=1
// SSPCON = 0x2B; // SSP enable & I2C Firmware Controlled Master mode
// この設定をするとうまく動作しない
return;
}
// ==================== I2C Start =============================
static void I2C_start() {
I2C_SDA = 1;
I2C_SDA_TRIS = 0; // output
I2C_SCL = 1; // SCL high
NOP();
NOP();
NOP();
NOP();
I2C_SDA = 0; // SDA low : start
NOP();
NOP();
NOP();
NOP();
I2C_SCL = 0; // SCL low
return;
}
// ==================== I2C Stop ==============================
static void I2C_stop() {
I2C_SDA = 0; // SDA low
I2C_SDA_TRIS = 0; // output
I2C_SCL = 1; // SCL high
NOP();
NOP();
NOP();
NOP();
I2C_SDA_TRIS = 1; // input(SDA high) : stop
return;
}
// ==================== I2C Send ==============================
static void I2C_send(unsigned char send_data) {
unsigned char i2c_data,i;
I2C_SDA_TRIS = 0; // SDA output
i2c_data = send_data;
for (i=8 ; i>0 ; i--) {
if (i2c_data & 0x80) { // ビットセット
I2C_SDA = 1;
} else {
I2C_SDA = 0;
}
i2c_data = i2c_data << 1; // next bit set
I2C_SCL = 1; // 1ビット送信
NOP();
NOP();
NOP();
NOP();
I2C_SCL = 0;
}
I2C_SDA_TRIS = 1; // SDA input
return;
}
// ==================== I2C Recive ============================
static unsigned char I2C_rcv() {
unsigned char i2c_data,i;
I2C_SDA_TRIS = 1; // SDA input
for (i=8 ; i>0 ; i--) {
NOP();
I2C_SCL = 1; // 1ビット受信
i2c_data = i2c_data <<1;
if (PORTB & 0x02) {
i2c_data = i2c_data | 0x01;
} else {
i2c_data = i2c_data & 0xFE;
}
I2C_SCL = 0;
}
return(i2c_data);
}
// ==================== 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;
I2C_SCL = 1; // ACKビット受信
NOP();
i2c_data = PORTB & 0x02;
I2C_SCL = 0;
return(i2c_data);
}
// ==================== I2C ACK send ==========================
static void I2C_acksnd() {
I2C_SDA = 0; // ACK
I2C_SDA_TRIS = 0; // SDA output
NOP();
I2C_SCL = 1; // ACK送信
NOP();
NOP();
NOP();
NOP();
I2C_SCL = 0;
I2C_SDA_TRIS = 1; // SDA input
return;
}
// ==================== I2C NACK send =========================
static void I2C_nacksnd() {
I2C_SDA = 1; // NACK
I2C_SDA_TRIS = 0; // SDA output
I2C_SCL = 1; // NACK送信
NOP();
I2C_SCL = 0;
NOP();
I2C_SDA_TRIS = 1; // SDA input
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) {
PORTA = (PORTA & 0xF0) | c;
LCD_E = 1;
NOP();
LCD_E = 0;
return;
}
// ==================== LCDコマンドWRITE =================
static void LCD_cmd(unsigned char cmd) {
LCD_RS = 0;
PORTA = (PORTA & 0xF0) | ((cmd >>4) & 0x0F);
LCD_E = 1; // 上位4ビット書き込み
NOP();
LCD_E = 0;
PORTA = (PORTA & 0xF0) | (cmd & 0x0F);
LCD_E = 1; // 下位4ビット書き込み
NOP();
LCD_E = 0;
wait_50us();
return;
}
// ==================== LCDデータWRITE =================
static void LCD_data(unsigned char cmd) {
LCD_RS = 1;
PORTA = (PORTA & 0xF0) | ((cmd >>4) & 0x0F);
LCD_E = 1; // 上位4ビット書き込み
NOP();
LCD_E = 0;
PORTA = (PORTA & 0xF0) | (cmd & 0x0F);
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 & 0x0F]);
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;
}
// ========================== ここまで ==============================