回覆列表
  • 1 # 陶白

    可以,模擬i2c即可,舉例:

    void IIC_Init(void)

    {

    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推輓輸出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    IIC_SCL=1;

    IIC_SDA=1;

    }

    //產生IIC起始訊號

    void IIC_Start(void)

    {

    SDA_OUT(); //sda線輸出

    IIC_SDA=1;

    IIC_SCL=1;

    delay_us(4);

    IIC_SDA=0;//START:when CLK is high,DATA change form high to low

    delay_us(4);

    IIC_SCL=0;//鉗住I2C匯流排,準備傳送或接收資料

    }

    //產生IIC停止訊號

    void IIC_Stop(void)

    {

    SDA_OUT();//sda線輸出

    IIC_SCL=0;

    IIC_SDA=0;//STOP:when CLK is high DATA change form low to high

    delay_us(4);

    IIC_SCL=1;

    IIC_SDA=1;//傳送I2C匯流排結束訊號

    delay_us(4);

    }

    //等待應答訊號到來

    //返回值:1,接收應答失敗

    // 0,接收應答成功

    u8 IIC_Wait_Ack(void)

    {

    u8 ucErrTime=0;

    SDA_IN(); //SDA設定為輸入

    IIC_SDA=1;delay_us(1);

    IIC_SCL=1;delay_us(1);

    while(READ_SDA)

    {

    ucErrTime++;

    if(ucErrTime>250)

    {

    IIC_Stop();

    return 1;

    }

    }

    IIC_SCL=0;//時鐘輸出0

    return 0;

    }

    //產生ACK應答

    void IIC_Ack(void)

    {

    IIC_SCL=0;

    SDA_OUT();

    IIC_SDA=0;

    delay_us(2);

    IIC_SCL=1;

    delay_us(2);

    IIC_SCL=0;

    }

    //不產生ACK應答

    void IIC_NAck(void)

    {

    IIC_SCL=0;

    SDA_OUT();

    IIC_SDA=1;

    delay_us(2);

    IIC_SCL=1;

    delay_us(2);

    IIC_SCL=0;

    }

    //IIC傳送一個位元組

    //返回從機有無應答

    //1,有應答

    //0,無應答

    void IIC_Send_Byte(u8 txd)

    {

    u8 t;

    SDA_OUT();

    IIC_SCL=0;//拉低時鐘開始資料傳輸

    for(t=0;t<8;t++)

    {

    IIC_SDA=(txd&0x80)>>7;

    txd<<=1;

    delay_us(2); //對TEA5767這三個延時都是必須的

    IIC_SCL=1;

    delay_us(2);

    IIC_SCL=0;

    delay_us(2);

    }

    }

    //讀1個位元組,ack=1時,傳送ACK,ack=0,傳送nACK

    u8 IIC_Read_Byte(unsigned char ack)

    {

    unsigned char i,receive=0;

    SDA_IN();//SDA設定為輸入

    for(i=0;i<8;i++ )

    {

    IIC_SCL=0;

    delay_us(2);

    IIC_SCL=1;

    receive<<=1;

    if(READ_SDA)receive++;

    delay_us(1);

    }

    if (!ack)

    IIC_NAck();//傳送nACK

    else

    IIC_Ack(); //傳送ACK

    return receive;

    }

    void I2C_WriteByte(uint16_t addr,uint8_t data,uint8_t device_addr)

    {

    IIC_Start();

    if(device_addr==0xA0) //eeprom地址大於1位元組

    IIC_Send_Byte(0xA0 + ((addr/256)<<1));//傳送高地址

    else

    IIC_Send_Byte(device_addr); //發器件地址

    IIC_Wait_Ack();

    IIC_Send_Byte(addr&0xFF); //傳送低地址

    IIC_Wait_Ack();

    IIC_Send_Byte(data); //傳送位元組

    IIC_Wait_Ack();

    IIC_Stop();//產生一個停止條件

    if(device_addr==0xA0) //

    delay_ms(10);

    else

    delay_us(2);

    }

    uint16_t I2C_ReadByte(uint16_t addr,uint8_t device_addr,uint8_t ByteNumToRead) //讀暫存器或讀資料

    {

    uint16_t data;

    IIC_Start();

    if(device_addr==0xA0)

    IIC_Send_Byte(0xA0 + ((addr/256)<<1));

    else

    IIC_Send_Byte(device_addr);

    IIC_Wait_Ack();

    IIC_Send_Byte(addr&0xFF); //傳送低地址

    IIC_Wait_Ack();

    IIC_Start();

    IIC_Send_Byte(device_addr+1); //發器件地址

    IIC_Wait_Ack();

    if(ByteNumToRead == 1)//LM75溫度資料為11bit

    {

    data=IIC_Read_Byte(0);

    }

    else

    {

    data=IIC_Read_Byte(1);

    data=(data<<8)+IIC_Read_Byte(0);

    }

    IIC_Stop();//產生一個停止條件

    return data;

    }

  • 中秋節和大豐收的關聯?
  • 工控通訊有幾種?