灵动微MM32F003硬件最小系统 --- GPIO模拟I2C读取24c02例程解析【24】

如果需要少量的存储数据,24C02是个可选的方案。24C02是I2C接口,由于I2C接口是个低速通讯接口,既可以采用GPIO模拟的方式,也可以使用芯片硬件的I2C接口。
本例程首先接受GPIO模拟的方式,这个例程具有一定的通用性,其他单片机也可以移植过去使用。读写24C02有两个需要注意的地方,一个是24C02可以通过电路配置I2C的读写地址,编写驱动程序的时候需要核对原理图,错误的地址是没有办法读写数据的。另一个需要注意的地方,就是24系列芯片不同容量的型号,页大小是不一样的。比如24C02是8字节每页,24C04/08/16则是16字节每页。
例程分为三个部分:

1 GPIO模拟I2C接口

bool I2C_Start(void)
{
    I2C_delay();
    SDA_H;
    SCL_H;
    I2C_delay();
    if(!SDA_read) return FALSE;  //SDAÏßΪµÍµçƽ×ÜÏß棬Í˳ö

    SDA_L;
    I2C_delay();
    if(SDA_read) return FALSE; //SDAÏßΪ¸ßµçƽÔò×ÜÏß³ö´í£¬Í˳ö

    SDA_L;
    I2C_delay();
    return TRUE;
}

void I2C_Stop(void)
{
    SCL_L;
    I2C_delay();
    SDA_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SDA_H;
    I2C_delay();
}

void I2C_Ack(void)
{
    SCL_L;
    I2C_delay();
    SDA_L;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SCL_L;
    I2C_delay();
}

void I2C_NoAck(void)
{
    SCL_L;
    I2C_delay();
    SDA_H;
    I2C_delay();
    SCL_H;
    I2C_delay();
    SCL_L;
    I2C_delay();
}

bool I2C_WaitAck(void)  //·µ»ØΪ£º-1ÓÐACK£¬ =0 ÎÞACK
{
    bool bstatus;
    SCL_L;
    I2C_delay();
    SDA_H;
    I2C_delay();
    SCL_H;
    I2C_delay();
    if(SDA_read) {
        bstatus = FALSE;
    } else {
        bstatus = TRUE;
    }
    SCL_L;
    return bstatus;

}

2 I2C数据读写接口

void I2C_SendByte(u8 SendByte) //Êý¾Ý´Ó¸ßλµ½µÍλ
{
    u8 i = 8;
    while(i--) {
        SCL_L;
        I2C_delay();
        if(SendByte & 0x80)
            SDA_H;
        else
            SDA_L;
        SendByte <<= 1;
        I2C_delay();
        SCL_H;
        I2C_delay();

    }
    SCL_L;
}
u8 I2C_ReceiveByte(void) //Êý¾Ý´Ó¸ßλµ½µÍλ
{
    u8 i = 8;
    u8 ReceiveByte = 0;

    SDA_H;
    while(i--) {
        ReceiveByte <<= 1;
        SCL_L;
        I2C_delay();
        SCL_H;
        I2C_delay();
        if(SDA_read) {
            ReceiveByte |= 0x01;
        }
    }
    SCL_L;
    return ReceiveByte;
}
//дÈë1×Ö½ÚÊý¾Ý £¨´úдÈëÊý¾Ý£¬´ýдÈëµØÖ·£¬Æ÷¼þÀàÐÍ£©
bool EEPROM_ByteWrite(u8 SendByte, u16 WriteAddress, u8 DeviceAddress)
{
    if(!I2C_Start()) return FALSE;

    I2C_SendByte(((WriteAddress & 0x0700) >> 7) | (DeviceAddress & 0xFE));  //ÉèÖøßÆðʼµØÖ· + Æ÷¼þµØÖ·

    if(!I2C_WaitAck()) {
        I2C_Stop();
        return FALSE;
    }
    I2C_SendByte((u8)(WriteAddress & 0x00FF)); //ÉèÖõÍÆðʼµØÖ·
    I2C_WaitAck();
    I2C_SendByte(SendByte);
    I2C_WaitAck();
    I2C_Stop();
    //×¢Ò⣺ÒòΪÕâÀïÒªµÈ´ýEERPOMдÍê³É£¬¿ÉÒÔ²ÉÓòéѯ »òÑÓʱ·½Ê½£¨10ms£©
    Systick_Delay_1ms(10);
    return TRUE;
}

//×¢Òâ²»ÄÜ¿çҳд
//дÈë1´®Êý¾Ý£¨´ýдÈëÊý×éµØÖ·£¬´ýдÈ볤¶È£¬´ýдÈëµØÖ·£¬Æ÷¼þÀàÐÍ£©
bool EEPROM_PageWrite(u8 *pBuffer, u8 length, u16 WriteAddress, u8 DeviceAddress)
{
    if((length + WriteAddress % I2C_PageSize) > I2C_PageSize) return FALSE;
    if(!I2C_Start()) return FALSE;
    I2C_SendByte(((WriteAddress & 0x0700) >> 7) | (DeviceAddress & 0xFE));  //ÉèÖøßÆðʼµØÖ· + Æ÷¼þµØÖ·

    if(!I2C_WaitAck()) {
        I2C_Stop();
        return FALSE;
    }
    I2C_SendByte((u8)(WriteAddress & 0x00FF)); //ÉèÖõÍÆðʼµØÖ·
    I2C_WaitAck();

    while(length--) {
        I2C_SendByte(*pBuffer);
        I2C_WaitAck();
        pBuffer++;
    }
    I2C_Stop();
    //×¢Ò⣺ÒòΪÕâÀïÒªµÈ´ýEERPOMдÍê³É£¬¿ÉÒÔ²ÉÓòéѯ »òÑÓʱ·½Ê½£¨10ms£©
    Systick_Delay_1ms(10);
    return TRUE;
}
//¿çҳдÈë1´®Êý¾Ý£¨´ýдÈëÊý×éµØÖ·£¬´ýдÈ볤¶È£¬´ýдÈëµØÖ·£¬Æ÷¼þÀàÐÍ£©
void EEPROM_BufferWrite(u8 *pBuffer, u16 length, u16 WriteAddress, u8 DeviceAddress )
{
    u16 i;
    u16 Addr = 0, count = 0;
    Addr = WriteAddress % I2C_PageSize; //дÈëµØÖ·ÊÇ¿ªÊ¼Ò³µÄµÚ¼¸Ò³
    count = I2C_PageSize - Addr; //ÔÚ¿ªÊ¼Ò³ÒªÐ´ÈëµÄ¸öÊý
    if(length <= count) {
        EEPROM_PageWrite(pBuffer, length, WriteAddress, DeviceAddress); //½öдһҳµÄÊý¾Ý
    } else {
        EEPROM_PageWrite(pBuffer, count, WriteAddress, DeviceAddress); //ÏÈдµÚÒ»Ò³µÄÊý¾Ý
        if((length - count) <= I2C_PageSize) {
            EEPROM_PageWrite(pBuffer + count, length - count, WriteAddress + count, DeviceAddress); //½öÔÙдһҳµÄÊý¾Ý½áÊø
        } else {
            for(i = 0; i < ((length - count) / I2C_PageSize); i++) {
                EEPROM_PageWrite(pBuffer + count + i * I2C_PageSize, I2C_PageSize, WriteAddress + count + i * I2C_PageSize, DeviceAddress);
            }
            if( ((length - count) % I2C_PageSize) != 0 ) {
                EEPROM_PageWrite(pBuffer + count + i * I2C_PageSize, ((length - count) % I2C_PageSize), WriteAddress + count + i * I2C_PageSize, DeviceAddress);
            }
        }
    }
}


//¶Á³ö1×Ö½ÚÊý¾Ý£¨´æ·Å¶Á³öÊý¾Ý£¬´ý¶Á³ö³¤¶È£¬´ø¶Á³öµØÖ·£¬Æ÷¼þÀàÐÍ£©
bool EEPROM_RandomRead(u8 *pByte, u16 ReadAddress, u8 DeviceAddress)
{
    if(!I2C_Start()) return FALSE;
    I2C_SendByte(((ReadAddress & 0x0700) >> 7) | (DeviceAddress & 0xFE)); //ÉèÖøßÆðʼµØÖ·+Æ÷¼þµØÖ·
    if(!I2C_WaitAck()) {
        I2C_Stop();
        return FALSE;
    }
    I2C_SendByte((u8)(ReadAddress & 0x00FF));//ÉèÖõÍÆðʼµØÖ·
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(((ReadAddress & 0x0700) >> 7) | (DeviceAddress | 0x0001));
    I2C_WaitAck();
    *pByte = I2C_ReceiveByte();
    I2C_NoAck();
    I2C_Stop();
    return TRUE;
}

//¶Á³ö1´®Êý¾Ý£¨´æ·Å¶Á³öÊý¾Ý£¬´ý¶Á³ö³¤¶È£¬´ø¶Á³öµØÖ·£¬Æ÷¼þÀàÐÍ£©
bool EEPROM_SequentialRead(u8 *pBuffer, u8 length, u16 ReadAddress, u8 DeviceAddress)
{
    if(!I2C_Start()) return FALSE;
    I2C_SendByte(((ReadAddress & 0x0700) >> 7) | (DeviceAddress & 0xFE)); //ÉèÖøßÆðʼµØÖ·+Æ÷¼þµØÖ·
    if(!I2C_WaitAck()) {
        I2C_Stop();
        return FALSE;
    }
    I2C_SendByte((u8)(ReadAddress & 0x00FF));//ÉèÖõÍÆðʼµØÖ·
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(((ReadAddress & 0x0700) >> 7) | (DeviceAddress | 0x0001));
    I2C_WaitAck();
    while(length) {
        *pBuffer = I2C_ReceiveByte();
        if(length == 1) I2C_NoAck();
        else I2C_Ack();
        pBuffer++;
        length--;
    }
    I2C_Stop();
    return TRUE;
}


void I2CEEPROMWriteany(u16 addr, u8* ptr, u16 cnt)
{
    EEPROM_BufferWrite(ptr, cnt, addr, 0xA0);
}

3 main函数

int main(void)
{
    u16 i;
    u16 temp;


    delay_init();
    LED_Init();

    /*
        Use I2C1 Port to connect external I2C interface type EEPROM 24C02;
        run Write and Read series bytes Data;
    */
    //Initial I2C
    I2C_Initialize();
    //Write 8 bytes from buffer0[128] to 0x10 of EEPROM
    I2CEEPROMWrite(0x10, buffer0, 0x08);
    //Read 8 bytes from 0x10 of EEPROM to buffer1[128]
    I2CEEPROMRead(0x10, buffer1, 0x08);
    for(i = 0; i < 0x08; i++) {
        buffer0[i] = i;
    }
    I2CEEPROMWriteany(0x20, buffer0, 0x8);
    I2CEEPROMRead(0x20, buffer1, 0x08);
    I2CEEPROMWriteany(0x20 + 0x8, buffer0, 0x8 + 0x8);
    I2CEEPROMRead(0x20 + 0x8, buffer1, 0x8 + 0x8);
    I2CEEPROMRead(0x20, buffer1, 0x8 + 0x8);
    temp = 0;
    for(i = 0; i < 0x08; i++) {
        if((buffer0[i]) == (buffer1[i])) {
            temp++;
        }
    }
    while(1) {
        LED1_TOGGLE();
        if(temp < 0x08) {
            delay_ms(100);
        }

        else {
            delay_ms(500);
        }
    }
}

程序写8个字节到0x10地址,然后读取8个字节,比较读写的数据是否一致,如果一致则LED指示灯慢闪,否则LED指示灯慢闪。

官方例程的修正已基本完成,需要程序的同学可以到百度网盘下载。
提取码:0o5i

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,186评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,858评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,620评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,888评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,009评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,149评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,204评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,956评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,385评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,698评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,863评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,544评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,185评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,899评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,141评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,684评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,750评论 2 351

推荐阅读更多精彩内容