io口模拟协议,以iic为例,平台atmega32

记录下,方便以后需要模拟协议

#include <avr/io.h>
#include <util/delay.h>

#define SDA_PIN PD1
#define SCL_PIN PD0

// 初始化I2C引脚
void I2C_Init() {
    DDRD |= (1 << SDA_PIN) | (1 << SCL_PIN);  // 设置SDA和SCL为输出
    PORTD |= (1 << SDA_PIN) | (1 << SCL_PIN); // 设置SDA和SCL为高
}

// 产生起始条件
void I2C_Start() {
    PORTD |= (1 << SDA_PIN);  // SDA高
    PORTD |= (1 << SCL_PIN);  // SCL高
    _delay_us(4);
    PORTD &= ~(1 << SDA_PIN); // SDA低
    _delay_us(4);
    PORTD &= ~(1 << SCL_PIN); // SCL低
}

// 产生停止条件
void I2C_Stop() {
    PORTD &= ~(1 << SDA_PIN); // SDA低
    PORTD |= (1 << SCL_PIN);  // SCL高
    _delay_us(4);
    PORTD |= (1 << SDA_PIN);  // SDA高
    _delay_us(4);
}

// 发送一个字节
void I2C_WriteByte(uint8_t data) {
    for (uint8_t i = 0; i < 8; i++) {
        if (data & 0x80) {
            PORTD |= (1 << SDA_PIN); // 发送1
        } else {
            PORTD &= ~(1 << SDA_PIN); // 发送0
        }
        data <<= 1;
        PORTD |= (1 << SCL_PIN);  // SCL高
        _delay_us(4);
        PORTD &= ~(1 << SCL_PIN); // SCL低
        _delay_us(4);
    }
}

// 读取应答
uint8_t I2C_ReadAck() {
    uint8_t ack;
    DDRD &= ~(1 << SDA_PIN);  // 设置SDA为输入
    PORTD |= (1 << SDA_PIN);  // 上拉
    PORTD |= (1 << SCL_PIN);  // SCL高
    _delay_us(4);
    ack = PIND & (1 << SDA_PIN);
    PORTD &= ~(1 << SCL_PIN); // SCL低
    DDRD |= (1 << SDA_PIN);   // 恢复SDA为输出
    return ack == 0;
}

// 读取一个字节
uint8_t I2C_ReadByte() {
    uint8_t data = 0;
    DDRD &= ~(1 << SDA_PIN);  // 设置SDA为输入
    for (uint8_t i = 0; i < 8; i++) {
        PORTD |= (1 << SCL_PIN); // SCL高
        _delay_us(4);
        data <<= 1;
        if (PIND & (1 << SDA_PIN)) {
            data |= 1;
        }
        PORTD &= ~(1 << SCL_PIN); // SCL低
        _delay_us(4);
    }
    DDRD |= (1 << SDA_PIN);  // 恢复SDA为输出
    return data;
}

// 发送应答
void I2C_SendAck() {
    PORTD &= ~(1 << SDA_PIN); // 发送0
    PORTD |= (1 << SCL_PIN);  // SCL高
    _delay_us(4);
    PORTD &= ~(1 << SCL_PIN); // SCL低
    _delay_us(4);
    PORTD |= (1 << SDA_PIN);  // SDA高
}

void I2C_SendNack() {
    PORTD |= (1 << SDA_PIN);  // 发送1
    PORTD |= (1 << SCL_PIN);  // SCL高
    _delay_us(4);
    PORTD &= ~(1 << SCL_PIN); // SCL低
    _delay_us(4);
}

int main() {
    I2C_Init();
    I2C_Start();
    I2C_WriteByte(0xA0); // 示例地址
    I2C_ReadAck();
    I2C_Stop();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值