/*******************************************/
/* 广州天河双龙电子公司 */
/* http://www.sl.com.cn */
/* 硬件I2C总线演示程序 */
/* 作者:ntzwq@wx88.net� */
/* 2002年5月12日 */
/* 目标MCU:MEGA8 晶振:内部RC(INT) 8MHZ */
/*******************************************/
//本演示程序不作超时处理,用户可自行加入超时处理代码
//使用说明:
//1、当LED右边两位(LED0,LED1)显示读出的数据,左边两位(LED2,LED3)
// 显示24C02的地址。
//2、可以使用INT0/INT1键修改地址和数据,INT0为+,INT1为-。
//3、当LED0小数点点亮时,修改数据;当LED2小数点点亮时,修改地址。
//4、如果在按住INT0或INT1键不放的同时,按了另外一个按键,可以切换修改模式;
// 如果是从修改数据模式切换到修改地址模式,则当前有变化的显示数据写入
// 当前显示的地址。�
#include<iom8v.h>
#include"TWI.H"
#define rd_device_add 0xa1
#define wr_device_add 0xa0
extern const unsigned char seg_table[16];
extern unsigned char led_buff[4];
extern void delay_ms(unsigned int time);
extern void display(void);
/******************************************
I2C总线写一个字节
返回0:写成功
返回非0:写失败
*******************************************/
unsigned char i2c_Write(unsigned char Wdata,unsigned char RomAddress)
{
Start();//I2C启动
Wait();
if(TestAck()!=START) return 1;//ACK
Write8Bit(wr_device_add);//写I2C从器件地址和写方式
Wait();
if(TestAck()!=MT_SLA_ACK) return 1;//ACK
Write8Bit(RomAddress);//写24C02的ROM地址
Wait();
if(TestAck()!=MT_DATA_ACK) return 1;//ACK
Write8Bit(Wdata);//写数据到24C02的ROM
Wait();
if(TestAck()!=MT_DATA_ACK) return 1;//ACK
Stop();//I2C停止
delay_ms(10);//延时等EEPROM写完
return 0;
}
/******************************************
I2C总线读一个字节
如果读失败也返回0
*******************************************/
unsigned char i2c_Read(unsigned char RomAddress)
{
unsigned char temp;
Start();//I2C启动
Wait();
if (TestAck()!=START) return 0;//ACK
Write8Bit(wr_device_add);//写I2C从器件地址和写方式
Wait();
if (TestAck()!=MT_SLA_ACK) return 0;//ACK
Write8Bit(RomAddress);//写24C02的ROM地址
Wait();
if (TestAck()!=MT_DATA_ACK) return 0;
Start();//I2C重新启动
Wait();
if (TestAck()!=RE_START) return 0;
Write8Bit(rd_device_add);//写I2C从器件地址和读方式
Wait();
if(TestAck()!=MR_SLA_ACK) return 0;//ACK
Twi();//启动主I2C读方式
Wait();
if(TestAck()!=MR_DATA_NOACK) return 0;//ACK
temp=TWDR;//读取I2C接收数据
Stop();//I2C停止
return temp;
}
unsigned char i2c_add,i2c_dat;//I2C地址/数据
unsigned char mode;//修改模式
void fill_buff(void)
{
led_buff[1]=seg_table[i2c_dat/16];
led_buff[0]=seg_table[i2c_dat%16];
led_buff[3]=seg_table[i2c_add/16];
led_buff[2]=seg_table[i2c_add%16];
if (mode==0)
led_buff[0]&=0x7f;
else
led_buff[2]&=0x7f;
}
void main(void)
{
unsigned char i;
unsigned char add_old,dat_old,mode_old;
TWBR=32;
TWSR=00;
mode=0xff;//mode=0修改数据,!=0修改地址
for(i=0;i<4;i++)
{
led_buff[i]=seg_table[8];
}
for(i=0;i<200;i++)
display();
i2c_add=0;
i2c_dat=i2c_Read(i2c_add);
fill_buff();
add_old=i2c_add;
dat_old=i2c_dat;
mode_old=mode;
while(1)
{
if(add_old!=i2c_add)//如果地址修改刷新数据
{
add_old=i2c_add;
i2c_dat=i2c_Read(i2c_add);
dat_old=i2c_dat;
fill_buff();
}
display();
i=PIND&0x0c;//判断按键
if(i!=0x0c)
{
display();//按键消抖
if(i==(PIND&0x0c))
{
if (i==0x08)//INT0键按下,递增
{
if (mode!=0)//修改地址
{
if(i2c_add<0xff)
i2c_add++;
else
i2c_add=0;
}
else //修改数据
{
if(i2c_dat<0xff)
i2c_dat++;
else
i2c_dat=0;
}
}
if (i==0x04)//INT1键按下,递减
{
if (mode!=0)//修改地址
{
if(i2c_add>0)
i2c_add--;
else
i2c_add=0xff;
}
else //修改数据
{
if(i2c_dat>0)
i2c_dat--;
else
i2c_dat=0xff;
}
}
fill_buff();
i=0;
while((PIND&0x0c)!=0x0c)//检查按键释放
{
display();
while(((PIND&0x0c)==0)&(i==0))
{
i=0xff;
if (mode==0)
{
mode=0xff;
led_buff[2]&=0x7f;
led_buff[0]|=0x80;
if (dat_old!=i2c_dat)
{
dat_old=i2c_dat;
i2c_Write(i2c_dat,i2c_add);
}
}
else
{
mode=0;
led_buff[0]&=0x7f;
led_buff[2]|=0x80;
}
}
}
}
}
}
}