基于MC9S12G128的I2C驱动M24M02 EEPROM的实现方案

基于MC9S12G128的I2C驱动M24M02 EEPROM的实现方案


一、硬件连接配置

MC9S12G128        M24M02
------------      --------
SCL  → SCL (PB2)
SDA  → SDA (PB3)
GND  → GND
VCC  → 3.3V
WP   → VCC (写保护关闭)

二、关键寄存器配置

#include "derivative.h"  // 包含MC9S12G128寄存器定义

#define I2C_BASE_ADDR  0x00  // I2C模块基地址
#define FCLKDIV        (*(volatile unsigned char *)0x0000)  // 时钟分频寄存器
#define FSTAT          (*(volatile unsigned char *)0x0001)  // 状态寄存器
#define FCCOBIX        (*(volatile unsigned char *)0x0002)  // 命令/地址指针
#define FCCOB          (*(volatile unsigned short *)0x0003) // 数据缓冲区

// 设备地址配置(7位地址格式)
#define M24M02_ADDR    0xA0  // A17=0, A16=0, E2=0
#define MEM_ADDR_SIZE  2      // 16位内存地址

三、I2C初始化函数

void I2C_Init() {
    // 设置I2C时钟分频(总线频率=总线时钟/(2*(FCLKDIV+1)))
    FCLKDIV = 0x17;  // 24MHz总线时钟 → 100kHz I2C
    
    // 清除状态标志
    FSTAT = 0x00;
    
    // 配置I2C为主模式,启用ACK
    // (具体配置需参考MC9S12G128数据手册的I2C章节)
}

四、EEPROM写操作

void EEPROM_Write(uint16_t memAddr, uint8_t *data, uint16_t size) {
    uint16_t pageAddr = memAddr & 0xFF00;  // 页地址高位
    uint16_t offset = memAddr & 0x00FF;    // 页内偏移
    
    while(size > 0) {
        uint16_t writeSize = (size > 256) ? 256 : size;  // 单页最大256字节
        
        // 发送起始条件+设备地址+写命令
        I2C_Start();
        I2C_Write(M24M02_ADDR << 1 | 0);  // 写模式
        
        // 发送内存地址(高字节在前)
        I2C_Write((pageAddr >> 8) & 0xFF);
        I2C_Write(pageAddr & 0xFF);
        
        // 写入数据
        for(uint16_t i=0; i<writeSize; i++) {
            I2C_Write(data[offset + i]);
        }
        
        I2C_Stop();
        
        // 等待写入完成(需根据时序添加延时)
        Delay_ms(5);  // M24M02写入时间≤5ms
        
        // 更新地址和剩余数据
        size -= writeSize;
        memAddr += writeSize;
        pageAddr += (offset + writeSize) / 256;
        offset = (offset + writeSize) % 256;
    }
}

五、EEPROM读操作

void EEPROM_Read(uint16_t memAddr, uint8_t *buffer, uint16_t size) {
    uint16_t pageAddr = memAddr & 0xFF00;
    uint16_t offset = memAddr & 0x00FF;
    
    // 发送起始条件+设备地址+写命令(发送内存地址)
    I2C_Start();
    I2C_Write(M24M02_ADDR << 1 | 0);
    
    // 发送内存地址
    I2C_Write((pageAddr >> 8) & 0xFF);
    I2C_Write(pageAddr & 0xFF);
    
    // 重新发送起始条件+设备地址+读命令
    I2C_Start();
    I2C_Write((M24M02_ADDR << 1) | 1);
    
    // 读取数据
    for(uint16_t i=0; i<size; i++) {
        buffer[i] = I2C_Read(i == size-1);  // 最后一字节发送NACK
    }
    
    I2C_Stop();
}

六、辅助函数实现

// I2C起始条件
void I2C_Start() {
    while(!IBSR_IBIF);  // 等待总线空闲
    IBSR_IBIF = 1;      // 清除中断标志
    IBDR = 0xFF;        // 拉低SDA启动信号
    while(IBSR_IBAL);   // 等待SDA拉低
}

// I2C停止条件
void I2C_Stop() {
    while(!IBSR_IBIF);
    IBSR_IBIF = 1;
    IBDR = 0xFF;        // 拉高SDA
    while(IBSR_IBAL);
}

// I2C写字节
uint8_t I2C_Write(uint8_t data) {
    while(!IBSR_IBIF);
    IBSR_IBIF = 1;
    IBDR = data;
    while(IBSR_IBAL);
    return IBSR_IBT;    // 返回ACK状态
}

// I2C读字节
uint8_t I2C_Read(uint8_t ack) {
    while(!IBSR_IBIF);
    IBSR_IBIF = 1;
    IBSR_IBR = ack;     // 设置ACK/NACK
    while(IBSR_IBAL);
    return IBDR;
}

参考代码 基于9S12G128的I2C驱动并含有EEPROM的M24M02的存储器读写程序 www.youwenfan.com/contentcsr/57243.html

七、完整工程结构

M24M02_Driver/
├── Src/
│   ├── main.c
│   ├── i2c.c
│   └── eeprom.c
├── Inc/
│   ├── i2c.h
│   └── eeprom.h
├── Libs/
│   └── MC9S12G128_Driver/
└── Project/
    ├── .project
    └── .ccsproject

八、扩展功能实现

  1. 页写入保护

    void EEPROM_LockPage(uint16_t pageAddr) {
        uint8_t data[3] = {0x00, (pageAddr>>8)&0xFF, pageAddr&0xFF};
        EEPROM_Write(0x0000, data, 3);  // 写入页锁定位
    }
    
  2. CRC校验功能

    uint16_t EEPROM_CalculateCRC(uint16_t addr, uint16_t size) {
        uint16_t crc = 0xFFFF;
        while(size--) {
            crc ^= (uint16_t)(*buffer++) << 8;
            for(uint8_t i=0; i<8; i++) {
                crc = (crc & 0x8000) ? (crc << 1) ^ 0x1021 : crc << 1;
            }
        }
        return crc;
    }
    

 

专注于matlab/simulink,电子电路,编程