美文网首页
灵动微MM32F003硬件最小系统 --- GPIO模拟I2C读

灵动微MM32F003硬件最小系统 --- GPIO模拟I2C读

作者: 黄开通 | 来源:发表于2020-11-29 12:36 被阅读0次

如果需要少量的存储数据,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

相关文章

网友评论

      本文标题:灵动微MM32F003硬件最小系统 --- GPIO模拟I2C读

      本文链接:https://www.haomeiwen.com/subject/pifkwktx.html