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