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