📄 i2c.c
字号:
#include<iom8v.h>
/* AT2402C地址
1 0 1 0 A2 A1 A0 R/W
前4位为AT240X系列的特征字
后3位为可编程位
最后一位为读写位
*/
#define rd_device_add 0xa1 //读地址:0b10100001
#define wr_device_add 0xa0 //写地址:0b10100000
/*TWI状态定义----MT 主方式传输 MR 主方式接收*/
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK 0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
#define EE_READ 0xf0
#define EE_READ_OK 0x50
#define EE_WRITE 0x0f
#define EE_WRITE_OK 0x05
#define EE_WRITE_OVER 0xa5
#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE))
//清除中断标志位,在总线上发出起始信号,激活TWI功能,开放TWI中断
#define Stop() (TWCR=((1<<TWINT)|(1<<TWSTO)|(1<<TWEN))&(~(1<<TWIE)))
//清除中断标志位,在总线上发出终止信号,激活TWI功能,关闭TWI中断
#define TestAck() (TWSR&0xf8)
//TWSR--I2C状态寄存器,检查TWI状态,应该将预分频位屏蔽(第三位是保留位)
#define MT_NACK (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE))
//清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下不对SDA线作应答
#define MT_ACK (TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA))
//清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下对SDA线作应答
#define TWItransmit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE);}
//写入8位数据到数据寄存器中,同时清除中断标志位,使能TWI功能,开放TWI中断
extern void delay_ms(unsigned int time);
unsigned char charData;//TWI中断中,传送的数据
unsigned char charAddr;//TWI中断中,数据所处的EEPROM地址
unsigned char charState;//TWI中断中,中断所处的状态
void TWI_init(void)
{
charState=EE_READ;
TWBR=0x20;//波特率寄存器,正常情况下应不小于10
TWSR=0x00;//TWI状态寄存器,时钟分频值1
}
/**********************ATEEPROM读写过程*********************************
字节写:Start→器件地址&W→应答→选ROM地址→应答→写数据→应答→Stop
中断过程 START→MT_SLA_ACK→MT_DATA_ACK(地址)→MT_DATA_ACK(数据)(STOP中止)
页面写:Start→器件地址&W→应答→选ROM地址→应答→写数据→应答→写NEXT地址数据→应答→。。。写NEXT地址数据→应答→Stop
中断过程 START→MT_SLA_ACK→MT_DATA_ACK(地址)→MT_DATA_ACK(数据)→MT_DATA_ACK(数据)→。。。MT_DATA_ACK(数据)(STOP中止)
字节读:Start→器件地址&W→应答→选ROM地址→应答→Restart→器件地址&R→应答→读数据→无应答→Stop
中断过程 START→MT_SLA_ACK→MT_DATA_ACK(地址)→RE_START→MR_SLA_ACK→MR_DATA_NOACK(STOP中止)
页面读:Start→器件地址&W→应答→选ROM地址→应答→Restart→器件地址&R→应答→读数据→应答→读NEXT地址数据→应答→。。。读NEXT地址数据→无应答→Stop
中断过程 START→MT_SLA_ACK→MT_DATA_ACK(地址)→RE_START→MR_SLA_ACK→MR_DATA_ACK→MR_DATA_ACK→。。。MR_DATA_NOACK(STOP中止)
*************************************************************************/
#pragma interrupt_handler TWI_Ready:iv_TWI//TWI中断处理
void TWI_Ready(void)
{
switch (TestAck())//检查状态标志字
{
case START:
{
TWItransmit(wr_device_add);
//选取I2C从器件地址,进行主控写模式
break;
}
case RE_START:
{
TWItransmit(rd_device_add);
//选取I2C从器件地址,进行主控读模式
break;
}
case MT_SLA_ACK:
//Slave器件被识别并产生应答
{
TWItransmit(charAddr);
//写24C02ROM的字地址
break;
}
case MT_DATA_ACK:
//主控发送数据,并得到响应
{
switch(charState)
{
case EE_WRITE://写数据到24C02的ROM
{
TWItransmit(charData);
charState=EE_WRITE_OVER;
break;
}
case EE_WRITE_OVER://I2C停止
{
Stop();
charState=EE_WRITE_OK;
break;
}
case EE_READ:
{
Start();
break;
}
//I2C重新启动
}
break;
}
case MR_SLA_ACK:
{
MT_NACK;
break;
}
//启动主I2C读方式
case MR_DATA_NOACK:
{
charData=TWDR;
Stop();
charState=EE_READ_OK;
break;
}
//读取I2C接收数据,I2C停止
default:
Stop();//I2C停止
}
}
/*
常用TWI操作(主模式写和主模式读)
*/
void i2c_write(unsigned char Wdata,unsigned char RomAddress)
{
charData=Wdata;//I2C总线写一个字节
charAddr=RomAddress;//返回0:写成功
charState=EE_WRITE;//返回非0:写失败
Start();//I2C启动(TWI中断启动)
while(charState!=EE_WRITE_OK);
delay_ms(10);
}
unsigned char i2c_read(unsigned char RomAddress)
{
charAddr=RomAddress;
charState=EE_READ;
Start();//I2C启动
while(charState!=EE_READ_OK);
return charData;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -