*******************************************************************/ //24c02-- SCL接PD4 , SDA接PD5 。单片机PA口接8路指示灯,开始时 72个花样灯 //表示将程序写入24c02,过10秒后, 再从24c02中读出,显示在指示灯上 #include <iom16v.h> #define _BV(k) (1<<k) #define uchar unsigned char #define uint unsigned int #define SCL PD4 //I2总线时钟线 #define SDA PD5 //I2总线数据线 #define SCL_L PORTD &=~_BV(SCL) #define SCL_H PORTD |= _BV(SCL) #define SDA_L PORTD &=~_BV(SDA) #define SDA_H PORTD |= _BV(SDA) #define SDA_IN DDRD&=~_BV(SDA) //设数据线位输入 #define SDA_OUT DDRD|= _BV(SDA) //设数据线位输出 #define SDA_RD (PIND&_BV(SDA)) //读电平 #define FREQ 1 //芯片工作频率 #define Slave 0xa0 uchar temp=0xff; uchar display[72]={ 0}; uchar const IN_data[72]={ 0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F, 0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF, 0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00, 0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF, 0xFC,0xF9,0xF3,0xE7,0xCF,0x9F,0x3F, 0x9F,0xCF,0xE7,0xF3,0xF9,0xFC,0xFF, 0xE7,0xDB,0xBD,0x7E,0xBD,0xDB,0xE7,0xFF, 0xE7,0xC3,0x81,0x00,0x81,0xC3,0xE7,0xFF, 0xAA,0x55,0x18,0xFF,0xF0,0x0F, 0x00,0xFF,0x00,0xFF}; /******************************************************** * * * N*ms延时函数 * * * ********************************************************/ void delayms(uint n) { uint i=0,j ; for (i=0 ;i<n ;i++) for(j=0;j<250*FREQ;j++) ; } /******************************************************** * * * y*us延时函数 * * * ********************************************************/ void delay(uint y) { int j; for(j=0;j<250*FREQ;j++) ; } /********************************************************** 起始信号 在 SCL 高电平期间 SDA 发生负跳变 **********************************************************/ void I2C_start(void) { SDA_H; SCL_H; delay(5); SDA_L; delay(5); SCL_L; } /********************************************************** 停止信号 在 SCL 高电平期间 SDA 发生正跳变 **********************************************************/ void I2C_stop(void) { SDA_L; SCL_H; delay(5); SDA_H; delay(5); SCL_L; delay(5); } /********************************************************** 把一个字节数据输入器件,并以收到应答信号为止 发送一个字节子程序 **********************************************************/ void I2C_Send(uchar W_data) { uchar i; for(i=0;i<8;i++) { if((W_data&0x80)) SDA_H; else SDA_L; SCL_H; delay(5); SCL_L; delay(5); W_data <<=1; } } /********************************************************** **********************************************************/ void Wait_Ack(void) { SDA_IN; //置SDA为输入 SDA_H; delay(5); do { SCL_L; SDA_H; delay(50); SCL_H; delay(50); } while(SDA_RD); SDA_L; SCL_L; SDA_OUT; //置SDA为输出 } /********************************************************** 读一个字节子程序 **********************************************************/ uchar I2C_REV(void) { uchar i; SDA_H; //开上拉 SDA_IN; //置SDA为输入 delay(5); for(i=0;i<8;i++) { SCL_H; delay(5); temp<<=1; if(SDA_RD) temp=(temp | 0x01); else temp=(temp & 0xfe); SCL_L; } SDA_OUT; //置SDA为输出 return(temp); } /********************************************************** 发送应答位子函数 在 SDA 低电平期间 SCL 发生一个正脉冲 **********************************************************/ void I2C_Ack(void) { SCL_L; delay(4); SDA_L; delay(4); SCL_H; delay(4); SCL_L; delay(4); SDA_H; delay(4); } /********************************************************** 发送非应答位子函数 在 SDA 高电平期间 SCL 发生一个正脉冲 **********************************************************/ void I2C_NAck(void) { SDA_H; delay(4); SCL_H; delay(4); SCL_L; delay(4); SDA_L; } /********************************************************** 从MCU移出数据到AT24C02 在指定地址addr处写入一个字节子程序 **********************************************************/ void Write_byte(uchar Addr,uchar in_Data) { I2C_start(); I2C_Send(Slave); Wait_Ack(); I2C_Send(Addr); Wait_Ack(); I2C_Send(in_Data); Wait_Ack(); I2C_stop(); delay(10); } /********************************************************** 在指定地址addr处读出一个字节子程序从AT24C04读数据到MCU **********************************************************/ void Read_byte(uchar Addr) { I2C_start(); I2C_Send(Slave); Wait_Ack(); I2C_Send(Addr); Wait_Ack(); I2C_start(); I2C_Send(Slave+1); Wait_Ack(); I2C_REV(); I2C_NAck(); I2C_stop(); delay(10); } /********************************************************** 主函数 **********************************************************/ int main(void) { uchar m; DDRA=0xff; PORTA=0xff; DDRC=0xff; PORTC=0xff; DDRD=0xff; PORTD=0xff; for(m=0;m<72;m++) { //写数据 Write_byte(m,IN_data[m]); PORTA= IN_data[m]; } for(m=0;m<72;m++) //读数据 { Read_byte(m); display[m]=temp; } while(1) { for(m=0;m<72;m++) //显示数据 { PORTA= display[m]; delayms(60); } } }