📄 i2c.c.bak
字号:
/*******************************************************
本部分为TWI总线的被控器部分程序,可以完成被控接收、被控发送数据
其工作方式与At240×系列的EEPROM的字节读写相同
目前问题是EEPROM的读写速度太慢,无法跟上TWI总线速度。
*///////////////////////////////////////////////////////
#include<iom8v.h>
#include <macros.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
//SR-从机方式接收 ST-从机方式传输 ALL-广播 NOCTRL-主机丢失控制权
#define SR_SLA_ACK 0x60
#define SR_SLA_ACK_NOCTRL 0x68
#define SR_ALL_ACK 0x70
#define SR_ALL_ACK_NOCTRL 0x78
#define SR_DATA_ACK 0X80
#define SR_DATA_NOACK 0X88
#define SR_ALL_DATA_ACK 0x90
#define SR_ALL_DATA_NOACK 0x98
#define SR_STOP_RESTART 0xa0
#define ST_SLA_ACK 0xa8
#define ST_SLA_ACK_NOCTRL 0xb0
#define ST_DATA_ACK 0xb8
#define ST_DATA_NOACK 0xc0
#define ST_LAST_DATA_ACK 0xc8
///////////////////////////////////////////////////////////
#define EE_READ 0xf0
#define EE_READ_OK 0x50
#define EE_WRITE 0x0f
#define EE_WRITE_OK 0x05
#define EE_WRITE_OVER 0xa5
#define TestAck() (TWSR&0xf8)
//TWSR--I2C状态寄存器,检查TWI状态,应该将预分频位屏蔽(第三位是保留位)
#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 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 char cDataBuff[];
extern void rom_write(unsigned int Address,unsigned char Data);
extern unsigned char rom_read(unsigned int Address);
unsigned char charData;//TWI中断中,传送的数据
unsigned char charAddr;//TWI中断中,数据所处的EEPROM地址
unsigned char charState;//TWI中断中,中断所处的状态
void TWI_init(void)
{
DDRC&=0b11001111;//设置PC4、PC5为输入
PORTC|=0b00110000;//将SDA、SCL线拉高(内置上拉电阻)
charState=EE_READ;
TWBR=0x00;//波特率寄存器,主机正常情况下应不小于10
TWSR=0x00;//TWI状态寄存器,时钟分频值1
TWAR=0xa0;/*被控器地址寄存器。0xa0为AT2402的地址,可以用ATMEGA8来模拟AT2402。
作为从机,应该将被控器的地址写入。注意不要和其他器件相同*/
TWCR=(TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA));//清除中断标志位,使能TWI功能,开放TWI中断
}
#pragma interrupt_handler TWI_Ready:iv_TWI//TWI中断处理
void TWI_Ready(void)
{
static unsigned char charIndex=0;
unsigned char charTemp;
unsigned char TWI_STATE;
TWI_STATE=TestAck();
switch (TWI_STATE)//检查状态标志字
{
case SR_SLA_ACK:
{
MT_ACK;
}
break;
case SR_DATA_ACK:
{
switch (charState)
{
case EE_READ://进入开始读取数据状态,此处即将读取的数据为ROM的Index
{
PORTC^=(0b00001000);//闪亮LED
charAddr=TWDR;
MT_ACK;
charState=EE_READ_OK;
}
break;
case EE_READ_OK://进入读取数据完成状态此处即将读取的数据为ROM->Index的数据
{
charData=TWDR;
MT_ACK;
//rom_write((unsigned char)charAddr,charData);
charState=EE_READ;
charIndex+=3;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围 cDataBuff[charIndex--]=0x0a;//间隔空格符
charTemp=charAddr%10;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
cDataBuff[charIndex--]=charTemp;
charAddr/=10;
charTemp=charAddr%10;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
cDataBuff[charIndex--]=charTemp;
charAddr/=10;
cDataBuff[charIndex]=charAddr;
charIndex+=4;//指向末尾空位
charIndex+=3;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
cDataBuff[charIndex--]=0x0a;//间隔空格符
charTemp=charData%10;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
cDataBuff[charIndex--]=charTemp;
charData/=10;
charTemp=charData%10;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
cDataBuff[charIndex--]=charTemp;
charData/=10;
cDataBuff[charIndex]=charData;
charIndex+=4;//指向末尾空位
}
break;
}
}
break;
case SR_STOP_RESTART://收到STOP信号或者RESTART
{
MT_ACK;
}
break;
case ST_SLA_ACK://收到读信号,将(最后一个-NT_NACK、普通数据-MT_ACK)数据发送出去
{
/*charTemp=rom_read((unsigned int)charAddr);
TWDR=charTemp;*/
TWDR=0xee;//测试用,发送测试数据。MEGA8的EEPROM的读速度跟不上TWI
MT_ACK;
}
break;
case ST_DATA_ACK://主机要求继续发送数据
{
TWDR=cDataBuff[++charAddr];
MT_ACK;
}
break;
case ST_DATA_NOACK://数据发送完毕
{
MT_ACK;
}
break;
default://出现异常中断时,通过MEGA8 2#显示
{
charData=TWI_STATE;
charIndex+=3;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
cDataBuff[charIndex--]=0x0b;//间隔空格符
charTemp=charData%10;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
cDataBuff[charIndex--]=charTemp;
charData/=10;
charTemp=charData%10;
charIndex&=0b00011111;//检查charIndex,防止数据超出0~31范围
cDataBuff[charIndex--]=charTemp;
charData/=10;
cDataBuff[charIndex]=charData;
charIndex+=4;//指向末尾空位
MT_ACK;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -