*******************************************************************/ //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); } } }