Skip to content

单片机_stc89c52_通信协议

I2C - EEPROM

原理

I2C协议

i2c地址,由于E0 ~ E2 都接地,所以

  • 写地址为 1010 0000 = 0xA0
  • 读地址为 1010 0001 = 0xA1 ![](../p/p示例

021_at24c02_i2c_data_store

由高到低发送

一共16页,可以进行页读,页写

c
void Int_WritePage(u8 addr, u8 byte[], u8 len)
{
    u8 i;
    Dri_I2cStart();
    Dri_I2cSendByte(IC_ADDRESS);
    Dri_I2cRecvAck();
    Dri_I2cSendByte(addr);
    Dri_I2cRecvAck();
    for (i = 0; i < len; i++)
    {
        Dri_I2cSendByte(byte[i]);
        Dri_I2cRecvAck();
    }
    Dri_I2cStop();
    Com_Util_DelayMs(10);
}

void Int_ReadPage(u8 addr, u8 byte[], u8 len)
{
    u8 i;
    Dri_I2cStart();
    Dri_I2cSendByte(IC_ADDRESS);
    Dri_I2cRecvAck();
    Dri_I2cSendByte(addr);
    Dri_I2cRecvAck();
    Dri_I2cStart(); // 重新起始信号
    Dri_I2cSendByte(IC_ADDRESS+1); // 读取位
    Dri_I2cRecvAck();
    for (i = 0; i < len; i++)
    {
        byte[i] = Dri_I2cRecvByte();
        Dri_I2cSendAck(i == len - 1 ? 1 : 0);
    }
    Dri_I2cStop();
}

i2c协议实现

c
#include "Dri_I2C.h"
#include <REGX52.H>

sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;

/*
    释放总线
    - SDA = 1
    - SCL = 0
*/


/*
    起始信号(两低)
*/ 
void Dri_I2cStart()
{
    // 在scl电平的时候准备好数据
    I2C_SCL = 1;
    I2C_SDA = 1; 
    I2C_SDA = 0;  // 下降沿
    I2C_SCL = 0; // 时钟下降沿准备接收数据
}

/*
    截止信号(两高)
*/ 
void Dri_I2cStop()
{
    I2C_SDA = 0; 
    I2C_SCL = 1;
    I2C_SDA = 1; // 上升沿
}

/*
    发送数据包
*/ 
void Dri_I2cSendByte(u8 byte)
{
    u8 i;
    for (i = 0; i < 8; i++)
    {
        I2C_SDA = byte & (0x80 >> i) ; // 先写入高位,高电平前准备数据
        I2C_SCL = 1; // SDA在SCL高电平时有效
        I2C_SCL = 0;
    }
}


/*
    接收数据包
*/ 
u8 Dri_I2cRecvByte()
{
    u8 i, byte = 0;

    I2C_SDA = 1; // 释放总线

    for (i = 0; i < 8; i++)
    {
        I2C_SCL = 1; // SDA在SCL高电平时有效
        if (I2C_SDA) {
             byte |= (0x80 >> i); // 先读取高位
        }
        I2C_SCL = 0;
    }

    return byte;
}


void Dri_I2cSendAck(u8 ack_bit)
{
    I2C_SDA = ack_bit; // 0=ACK, 1=NACK
    I2C_SCL = 1; 
    I2C_SCL = 0;
}

u8 Dri_I2cRecvAck()
{
    bit ack;
    I2C_SDA = 1; // 释放数据线
    I2C_SCL = 1;
    ack = I2C_SDA;
    I2C_SCL = 0;
    return ack;
}

SPI - XPT2045 湿度传感器、光敏电阻、可变电阻

原理

花几分钟理解SPI通信原理_哔哩哔哩_bilibili ![](../p../p,cpha相位

  • CPOL = 0,CPHA = 0,空闲低电平,上升沿有效
  • CPOL = 0,CPHA = 1,空闲低电平,下降沿有效
  • CPOL = 1,CPHA = 0,空闲高电平,下降沿有效
  • CPOL = 1,CPHA = 1,空闲高电平,上升沿有效
c
#define XPT_2045_AD1  0x9C // AIN0 = XP    1001 1100
#define XPT_2045_NTC1 0xCC // AIN1 = YP    1100 1100
#define XPT_2045_GR1  0xAC // AIN2 = VBAT  1010 1100

u8 Int_XPT2045_Read(u8 cmd);

![](../p../p1

  • MODE = 0 12位,MODE = 1 8位
  • SER = 1 单端模式,SER = 0 差分模式
  • PD1PD0 = 00 低功率模式; PD1PD0 = 11 供电状态

![](../p示例

025_ad

由高到低发送

![](../p```c u8 Int_XPT2045_Read(u8 cmd) { u8 byte = 0x00; Dri_SPI_Start(); Dri_SPI_SendByte(cmd); byte = Dri_SPI_RecvByte(); Dri_SPI_End();

return byte;

}


spi协议
```c
sbit SPI_CS    = P3^5;
sbit SPI_DCLK  = P3^6;
sbit SPI_DIN   = P3^4;
sbit SPI_DOUT  = P3^7;

void Dri_SPI_Start()
{
    SPI_CS = 0;
    SPI_DCLK = 0;
}

// SPI结束传输
void Dri_SPI_End()
{
    SPI_CS = 1;         // 释放设备
    SPI_DCLK = 0;       // 时钟保持低电平
}

void Dri_SPI_SendByte(u8 byte)
{
    u8 i;
    for (i = 0; i < 8; i++)
    {
        SPI_DCLK = 0;   // 上升沿发送
        SPI_DIN = byte & (0x80 >> i); // 由高到低发送
        SPI_DCLK = 1;
    }    
    SPI_DCLK = 0;
}

u8 Dri_SPI_RecvByte()
{
    u8 i,res = 0x00; 
    for (i = 0; i < 8; i++)
    {
        SPI_DCLK = 1;   // 下降沿读取
        if (SPI_DOUT) {
            res |= (0x80 >> i); // 由高到低读取
        }
        SPI_DCLK = 0;
    }

    return res;
}

1 Wire - DS18B20 温度传感器

原理

通过时间间隔区分高低电平

示例

022_ds18b20

由低到高发送

![](../pR - 红外接收器

原理

类似单总线,通过时间间隔区分高低电平 ![](../p

027_ir028_ir_motor

由低到高发送

![](../p

最近更新