⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c.bak

📁 详细介绍M8两版间通讯
💻 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 + -