📄 twi.c
字号:
/*******************************************************************************/
// 主机、中断方式(读写24C02)
//原作者: ntzwq@wx88.net?
//建立时间: 2003年3月25日
//目标MCU:MEGA8 晶振:内部RC(INT) 8MHZ
//模块整理: sam
//模块建立时间: 2008-5-23
/********************************************************************************/
#include<iom128.h>
#include<AT24C02.h>
#include <global.h>
#ifdef Debug_I2C
#include <Rs485.h>
#endif
#define RD_DEVICE_ADD 0xA1
#define WR_DEVICE_ADD 0xA0
//TWI中断处理(主机模式读和写,以访问AT24C02为例)
#define EE_READ 0xF0
#define EE_READ_OK 0x50
#define EE_WRITE 0x0F
#define EE_WRITE_OK 0x05
#define EE_WRITE_REG 0xA5
unsigned char EE_STATE; //EEPROM操作状态
unsigned char EE_DATA; //写入的数据
unsigned char EE_ADD; //写入的地址
unsigned char g_i2ceesave=0x1e; //I2CEEPROM保存标志
#pragma vector=TWI_vect
__interrupt void TWI_ISR(void) //I2C中断服务程序
{
switch (TestAck())
{
case START:
{
Write8Bit(WR_DEVICE_ADD); //写I2C从器件地址和写方式
break;
}
case RE_START:
{
Write8Bit(RD_DEVICE_ADD); //写I2C从器件地址和读方式
break;
}
case MT_SLA_ACK:
{
Write8Bit(EE_ADD); //写24C02的ROM地址
break;
}
case MT_DATA_ACK:
{
switch(EE_STATE)
{
case EE_WRITE:
{
Write8Bit(EE_DATA); //写数据到24C02的ROM
EE_STATE=EE_WRITE_REG;
break;
}
case EE_WRITE_REG:
{
Stop(); //I2C停止
EE_STATE=EE_WRITE_OK;
break;
}
case EE_READ:
{
Start(); //I2C重新启动
break;
}
}
break;
}
case MR_SLA_ACK:
{
Twi(); //启动主I2C读方式
break;
}
case MR_DATA_NOACK:
{
EE_DATA=TWDR; //读取I2C接收数据
Stop(); //I2C停止
EE_STATE=EE_READ_OK;
break;
}
default:
Stop(); //I2C停止
}
}
/********************************************************************************
功能: I2C总线写一个字节
函数原型:unsigned char I2C_Write(unsigned char Wdata,unsigned char RomAddress)
参数: unsigned char Wdata 写入的数据
unsigned char RomAddress 写入数据的地址0-255
返回值: 0:写成功
非0:写失败
*********************************************************************************/
unsigned char I2C_Write(unsigned char Wdata,unsigned char RomAddress)
{
unsigned char n=0;
EE_DATA=Wdata;
EE_ADD=RomAddress;
EE_STATE=EE_WRITE;
Start(); //I2C启动
while(EE_STATE!=EE_WRITE_OK)
{
Delay_100us();
if( n++ >40) //超时时间为2ms
return 1;
}
Delay_ms(2);
#ifdef Debug_I2C
PC_putchar_D(n);
#endif
return 0;
/*以下是查询方式访问AT24C02的代码
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总线读一个字节
函数原型:unsigned char I2C_Read(unsigned char RomAddress)
参数:
unsigned char RomAddress 读出数据的地址0-255
返回值: 实际值, 如果读失败也返回0
*********************************************************************************/
unsigned char I2C_Read(unsigned char RomAddress)
{
unsigned char n=0;
EE_ADD=RomAddress;
EE_STATE=EE_READ;
Start();//I2C启动
while(EE_STATE!=EE_READ_OK)
{
Delay_100us();
if( n++ >20) //超时时间为2ms
return 0;
}
#ifdef Debug_I2C
PC_putchar_D(n);
#endif
return EE_DATA;
//以下是查询方式访问AT24C02的代码
/*
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;*/
}
/********************************************************************************
功能: 初始化I2C收发器
函数原型:void I2C_Init(void)
参数: 无
返回值: 无
*********************************************************************************/
void I2C_Init(void)
{
TWBR=0x08; //时钟为clock/(16+2*8)
TWSR=0x00;
}
/*unsigned char i2c_add,i2c_dat;//I2C地址/数据
unsigned char mode;//修改模式
void main(void)
{
unsigned char i;
unsigned char add_old,dat_old,mode_old;
EE_STATE=EE_READ;
asm("sei");
TWBR=32;
TWSR=00;
mode=0xff;//mode=0修改数据,!=0修改地址
i2c_add=0;
i2c_dat=i2c_Read(i2c_add);
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;
}
i=PIND&0x0c;//判断按键
if(i!=0x0c)
{
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;
}
}
i=0;
while((PIND&0x0c)!=0x0c)//检查按键释放
{
while(((PIND&0x0c)==0)&(i==0))
{
i=0xff;
if (mode==0)
{
mode=0xff;
if (dat_old!=i2c_dat)
{
dat_old=i2c_dat;
i2c_Write(i2c_dat,i2c_add);
}
}
else
{
mode=0;
}
}
}
}
}
}
}
*/
/*end of at24c02.c*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -