obsidian-notes/代码/IIC.md
CSSC-WORK\murmur 3e6078442b init version
2024-04-15 11:19:57 +08:00

3.5 KiB
Raw Blame History

title updated created
IIC 2022-01-11 01:26:41Z 2022-01-08 13:18:07Z

软件模拟IIC

/*
This sample show how to use MM32 write read EEPROM AT2404 through
GPIO pin to simulate I2C interface
下面给出MM32通过GPIO模拟I2C读写EEPROM程序
*/
#define I2C1_SCL_PORT               GPIOB
#define I2C1_SCL_PIN                GPIO_Pin_13
#define I2C1_SCL_BUSCLK             RCC_AHBPeriph_GPIOB
#define I2C1_SDA_PORT               GPIOB
#define I2C1_SDA_PIN                GPIO_Pin_14
#define I2C1_SDA_BUSCLK             RCC_AHBPeriph_GPIOB
#define SCL_H                       I2C1_SCL_PORT->BSRR = I2C1_SCL_PIN
#define SCL_L                       I2C1_SCL_PORT->BRR  = I2C1_SCL_PIN
#define SCL_read                    (I2C1_SCL_PORT-IDR  & I2C1_SCL_PIN)
#define	SDA_H	                    I2C1_SDA_PORT->BSRR	= I2C1_SDA_PIN
#define SDA_L	                    I2C1_SDA_PORT->BRR	= I2C1_SDA_PIN
#define SDA_read                    (I2C1_SDA_PORT->IDR & I2C1_SDA_PIN)
void I2C_GPIO_Config(void);
bool EEPROM_ByteWrite(u8 SendByte, u16 WriteAddress, u8 DeviceAddress);
bool EEPROM_SequentialRead(u8 *pBuffer, u8 length, u16 ReadAddress, u8 DeviceAddress);
#define I2C_PageSize 16//8
void delay_ms(__IO uint32_t nTime);
#define Systick_Delay_1ms delay_ms
void I2C_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    /*Configure I2C1 Pins:SCL and SDA*/
    RCC_AHBPeriphClockCmd(I2C1_SCL_BUSCLK, ENABLE);
    RCC_AHBPeriphClockCmd(I2C1_SDA_BUSCLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C1_SCL_PIN ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(I2C1_SCL_PORT, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = I2C1_SDA_PIN;
    GPIO_Init(I2C1_SDA_PORT, &GPIO_InitStructure);
}
static void I2C_delay(void)
{
    //set I2C SCL speed 设置通信速度
    u8 i = 13; //100;
    while(i) {
        i--;
    }
}
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;
}
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;
}