记录下,方便以后需要模拟协议
#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;
}