打印
[DemoCode下载]

用IO模拟I2C

[复制链接]
77|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
598330983|  楼主 | 2025-2-22 11:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/**************************************************************************//**
* [url=home.php?mod=space&uid=288409]@file[/url]     main.c
* [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
* [url=home.php?mod=space&uid=247401]@brief[/url]    Use GPIO to simuliate I2C waveform
*
* @note
* Copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
******************************************************************************/
#include <stdio.h>
#include "NUC230_240.h"
#include "NuEdu-Basic01.h"


/*----------------------------------------------------------------------------*/
/* Define                                                                     */
/*----------------------------------------------------------------------------*/
#define I2C_ADDRESS_W   0xa0
#define I2C_ADDRESS_R   0xa1
#define I2C_DELAY_TIME  10
#define ACK             0
#define NO_ACK          1
#define I2C_CLK         PA11
#define I2C_DAT         PA10


/*----------------------------------------------------------------------------*/
/* Global variable                                                            */
/*----------------------------------------------------------------------------*/


/*----------------------------------------------------------------------------*/
/* Functions                                                                  */
/*----------------------------------------------------------------------------*/


void I2C_Init(void)
{
    /* Configure PA10 as open-drain mode */
    GPIO_SetMode(PA, BIT10, GPIO_PMD_OPEN_DRAIN);

    /* Configure PA11 as open-drain mode */
    GPIO_SetMode(PA, BIT11, GPIO_PMD_OPEN_DRAIN);

    /* Control PA11 output status */
    I2C_CLK = 1;

    /* Control PA10 output status */
    I2C_DAT = 1;
}


void I2C_Start(void)
{
    /*  I2C START Condition */
    I2C_DAT = 1;
    I2C_CLK = 1;

    /*  I2C delay 10us */
    CLK_SysTickDelay(I2C_DELAY_TIME);
    I2C_DAT = 0;
    I2C_CLK = 0;
    CLK_SysTickDelay(I2C_DELAY_TIME);
}


void I2C_Stop(void)
{
    /*  I2C STOP Condition */
    I2C_DAT = 0;
    I2C_CLK = 1;
    I2C_DAT = 1;
}


uint8_t I2C_Write(uint8_t u8Data)
{
    uint8_t u8Count;

    /* Write to slave */
    for (u8Count = 0; u8Count < 8; u8Count++)
    {
        /* Send data bit */
        if ((u8Data & 0x80) == 0x80)
            I2C_DAT = 1;
        else
            I2C_DAT = 0;

        /* Shift one bit */
        u8Data <<= 1;

        I2C_CLK = 1;

        /*  I2C delay 10us */
        CLK_SysTickDelay(I2C_DELAY_TIME);
        I2C_CLK = 0;
        CLK_SysTickDelay(I2C_DELAY_TIME);
    }

    I2C_DAT = 1;
    I2C_CLK = 1;

    /*  I2C delay 5us */
    CLK_SysTickDelay(I2C_DELAY_TIME / 2);

    /* Read ACK bit from slave */
    u8Data = I2C_DAT;

    CLK_SysTickDelay(I2C_DELAY_TIME / 2);
    I2C_CLK = 0;
    CLK_SysTickDelay(I2C_DELAY_TIME);
    return u8Data;
}


uint8_t I2C_Read(uint8_t u8Ack)
{
    uint8_t u8Data, u8Count;

    u8Data = 0x00;

    /* Read from slave */
    for (u8Count = 0; u8Count < 8; u8Count++)
    {
        /* Shift one bit */
        u8Data <<= 1;

        /* Read data bit */
        u8Data |= I2C_DAT;

        I2C_CLK = 1;
        CLK_SysTickDelay(I2C_DELAY_TIME);
        I2C_CLK = 0;
        CLK_SysTickDelay(I2C_DELAY_TIME);
    }

    /* Send ACK bit to slave */
    I2C_DAT = u8Ack;

    I2C_CLK = 1;

    /*  I2C delay 10us */
    CLK_SysTickDelay(I2C_DELAY_TIME);
    I2C_CLK = 0;
    CLK_SysTickDelay(I2C_DELAY_TIME);

    return u8Data;
}


void I2C_GPIO_Write_Byte(uint16_t u16Addr, uint8_t u8Data)
{
    uint8_t u8AddrH, u8AddrL;

    u8AddrH = u16Addr >> 8;
    u8AddrL = (uint8_t)u16Addr;

    /* Send Start bit to I2C EEPROM */
    I2C_Start();

    /* Send control byte to I2C EEPROM */
    printf("ack=0x%x,\n\r", I2C_Write(I2C_ADDRESS_W));

    /* Send I2C EEPROM's High Byte Address */
    printf("ack=0x%x,\n\r", I2C_Write(u8AddrH));

    /* Send I2C EEPROM's Low Byte Address */
    printf("ack=0x%x,\n\r", I2C_Write(u8AddrL));

    /* Send data byte to I2C EEPROM */
    printf("ack=0x%x,\n\r", I2C_Write(u8Data));

    /* Send Stop bit to I2C EEPROM */
    I2C_Stop();
}

void I2C_GPIO_Read_Byte(uint16_t u16Addr, uint8_t *pu8Data)
{
    uint8_t u8AddrH, u8AddrL;

    u8AddrH = u16Addr >> 8;
    u8AddrL = (uint8_t)u16Addr;

    /* Send Start bit to I2C EEPROM */
    I2C_Start();

    /* Send control byte to I2C EEPROM */
    printf("ack=0x%x,\n\r", I2C_Write(I2C_ADDRESS_W));

    /* Send I2C EEPROM's High Byte Address */
    printf("ack=0x%x,\n\r", I2C_Write(u8AddrH));

    /* Send I2C EEPROM's Low Byte Address */
    printf("ack=0x%x,\n\r", I2C_Write(u8AddrL));

    /* Send Start bit to I2C EEPROM */
    I2C_Start();

    /* Send control byte to I2C EEPROM */
    printf("ack=0x%x,\n\r", I2C_Write(I2C_ADDRESS_R));

    /* Read data byte from EEPROM */
    *pu8Data = I2C_Read(NO_ACK);

    /* Send Stop bit to I2C EEPROM */
    I2C_Stop();
}
/*----------------------------------------------------------------------------*/
/*  MAIN function                                                             */
/*----------------------------------------------------------------------------*/
int main(void)
{
    uint8_t u8Data;

    /* Init System */
    SYS_Init();

    /* Initial UART0 to 115200-8n1 for print message */
    UART0_Init();

    /* Init software I2C */
    I2C_Init();

    /* Write 0x55 into address 0x0000 */
    I2C_GPIO_Write_Byte(0x0000, 0x55);

    /* Delay 10ms */
    CLK_SysTickDelay(10000);

    /* Read 0x55 from address 0x0000 */
    I2C_GPIO_Read_Byte(0x0000, &u8Data);
    printf("data=0x%x,\n\r", u8Data);

    while (1);
}

/*** (C) COPYRIGHT 2019 Nuvoton Technology Corp. ***/



使用特权

评论回复
沙发
598330983|  楼主 | 2025-2-22 11:04 | 只看该作者
IO模拟I2C,要注意使用IO的开漏模式,这样,只有拉低和高阻态,高阻态的时候可以通过上拉电阻给总线拉高。这样就完美的模拟了I2C的物理特性。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

255

主题

5483

帖子

22

粉丝