// 读取数据 unsigned char d = 0,i = 0; for (;i < 8;i++) { // 在eeprom修改sda之前,sda需要是高电平 // 即单片机的引脚需要读入数据是,必须置高 SCL = 0; Delay(); SDA = 1; Delay(); // scl置高,表示将要读取数据 SCL = 1; Delay(); d <<= 1; if (SDA == 1) { // 该位为高电平 d |= 0x01; } // scl此时已经是高,不必置高 Delay(); } // 读完一个字节,发送一个非应答位 SCL = 0; Delay(); SDA = 1; Delay(); SCL = 1; Delay(); SCL = 0; return d; }
前面用到的延时函数引用了一个头文件:#include
以下为完整的代码: #include
// 实现单片机的IIC通信
void main() { unsigned char i = 0; unsigned char d = 0; InitAll(); // 向eeprom写1~10的数字,起始地址为0x00 for (i = 1;i <= 10;i++) { if (Write_IIC(i - 1,i) == 0) { P0 = 0x00; } Delay_2(20000); } // 从EEPROM读取前十个数字,通过uart通信发送到电脑 while (1) { for (i = 0;i < 10;i++) { d = Read_IIC(i); Send_UART(d); // 延时 Delay_2(20000); } } }
void InitAll() { // IIC通信 SDA = 1,SCL = 1; // uart通信,scon SM0 = 0,SM1 = 1,REN = 1; // 定时器1 TR1 = 1; // 时间 TH1 = 0xfd,TL1 = 0xfd; // 使用模式2 TMOD = 0x20; // 设置led灯 ENLED = 0,ADDR3 = 1; ADDR0 = 0,ADDR1 = 0,ADDR2 = 0; P0 = 0xff; }
unsigned char WriteData(unsigned char c) { // 向EEPROM写数据
unsigned char temp = 0x80,i; for (i = 0;i < 8;i ++) { SCL = 0; Delay(); if ((c & temp) != 0) { // 真表示测试位是1 SDA = 1; } else { // 假表示测试位是0 SDA = 0; } temp >>= 1; // 将scl置高,让EEPROM有机会读取SDA上的信息 Delay(); SCL = 1; Delay(); } // 最后再接收一个应答位 SCL = 0; Delay(); SDA = 1; Delay(); SCL = 1; Delay(); // 此时SDA已经接收到一个应答位,暂不处理 if (SDA != 0) { // 没有接收到应答位,返回错误 return 0; } SCL = 0; return 1; }
unsigned char Write_IIC(unsigned char address,unsigned char d) { // 开始信号 StartIIC(); // 发送设备地址和操作方式,设备地址为000,操作方式写:0 if (WriteData(0xa0) == 0) { return 0; } // 发送操作数据的地址 if (WriteData(address) == 0) {
return 0; } // 发送数据 if (WriteData(d) == 0) { return 0; } // 停止信号 StopIIC(); }
unsigned char Read_IIC(unsigned char address) { unsigned char d = 0; // 开始信号 StartIIC(); // 写设备地址和操作方式,设备地址为000,操作方式写:0 WriteData(0xa0); // 写操作数据的地址 WriteData(address); // 重新发送开始信号 StartIIC(); // 写设备地址和操作方式,设备地址为000,操作方式读:1 WriteData(0xa1); // 由于前面已经写入希望操作的数据的地址,所以现在不用重新发送 // 读取信号 d = ReadData(); // 停止信号 StopIIC(); return d; }
unsigned char ReadData() { // 读取数据 unsigned char d = 0,i = 0; for (;i < 8;i++) { // 在eeprom修改sda之前,sda需要是高电平 // 即单片机的引脚需要读入数据是,必须置高 SCL = 0; Delay(); SDA = 1; Delay(); // scl置高,表示将要读取数据 SCL = 1; Delay(); d <<= 1; if (SDA == 1) {
// 该位为高电平 d |= 0x01; } // scl此时已经是高,不必置高 Delay(); } // 读完一个字节,发送一个非应答位 SCL = 0; Delay(); SDA = 1; Delay(); SCL = 1; Delay(); SCL = 0; return d; }
void StartIIC() { // 先将scl置底,以便将sda置高 SCL = 0; Delay(); SDA = 1; Delay(); SCL = 1; Delay(); // 在此基础上将sda置低,表示开始 SDA = 0; Delay(); SCL = 0; }
void StopIIC() { // SCL = 0; Delay(); SDA = 0; Delay(); // 现在SDA,SCL都是低电平 SCL = 1; Delay(); SDA = 1; Delay(); }
void Delay() { // 大概延时四个机器周期 _nop_(); _nop_(); _nop_();
_nop_(); }
void Delay_2(unsigned int t) { while (t--) {} }
void Send_UART(unsigned char d) { SBUF = d; while (!TI) ; TI = 0; }