我用avr的IO口来模拟I2C,是不是一定要不断地改变输入输出方向啊(DDRx)
马老师:cpu:atmega8
因为现在内部的TWI被占用了,而又要去访问一个带I2C的从器件(DS1302)
所以只能用模拟的,,在仿真的过程中,发现在如果没有改变DDRx的方向则运行不能正常,
如果加上改变输入输出方向,就正常了,
令我不解的是:在读取从机的响应时,我是通过读PINx的,
不是说,不管方向寄存器为何值(0,或 1),都可以读取外部引脚的实际电平吗???
????,即然无关还为什么要加,不加又不行,这到底是为什么?????道理何在,作何解释?
还有一个一小问题:我就是不PINx复位时的值,为N/A,它是什么意思????
如图:
http://cache.amobbs.com/bbs_upload782111/files_3/armok0158926.jpg 首先注意,PINx在物理上不是对于一个D触发器的,它是直接对应外部引脚(请参考《M8》书的图2.20,并分析该电路)。当芯片复位时,PORTx的值为0,DDRx的值为0,I/O状态为输入。PINx的值为引脚的电平,取决于该引脚所连接的外围电路,所以是不确定的,用N/A表示。
手册上的“不管方向寄存器为何值(0,或 1),都可以读取外部引脚的实际电平”是对的,只是你没有真正理解“外部引脚的实际电平”是否就是“DS1302的输出电平”。
举你的例子,当DDRx=1,引脚为输出状态,此时PORTx的值会驱动引脚。假定PORTx=0,引脚PINx被拉到低电平(外部引脚的实际电平),那么不管DS1302输出为1还是0,PINx的实际电平还是“0”,此时你读PINx读到“0”,是PINx的实际值,但不是DS1320的输出值。
所以,用I/O模拟I2C时,DDRx应该根据引脚的工作方式进行转换设置。
另外,使用AVR不建议用I/O模拟I2C,在I2C总线上可以挂接多个“从”器件,甚至构成多“主”I2C总线。为什么不使用AVR的硬件I2C? Delphi串口通信编程
作者: 黄军 熊勇 刘燕 刘晓梅
人民邮电出版社
IC总线应用系统设计
【作者】 何立民
出版社】 北京航空航天大学出版社
DELPHI串口通信工程开发实例导航
作者: 求是科技 崔建华 刘瑞军
出版社: 人民邮电出版社
出版日期:2003-08-01
DELPHI串口通信技术与工程实践
作者: 求是科技 赵兰涛 苏彦华
出版社: 人民邮电出版社 ISBN:7-115-12313-6
出版日期:2004-06-01
Delphi与RS-232串行通信控制
作 者 范逸之 陈立元
出 版 社 清华大学出版社
定价49元
我用avr的IO口来模拟I2C,是不是一定要不断地改变输入输出方向啊(DDRx)
因为现在内部的TWI被占用了,而又要去访问一个带I2C的从器件(DS1302)
所以只能用模拟的,,在仿真的过程中,发现在如果没有改变DDRx的方向则运行不能正常,
如果加上改变输入输出方向,就正常了,
令我不解的是:在读取从机的响应时,我是通过读PINx的,
不是说,不管方向寄存器为何值(0,或 1),都可以读取外部引脚的实际电平吗???
????,即然无关还为什么要加,不加又不行,这到底是为什么?????道理何在,作何解释?
还有一个一小问题:我就是不PINx复位时的值,为N/A,它是什么意思????
如图:
非常感谢马老师的解答,真彻底地说明了,
内部电平会影响到外部引脚上的电平!!!!!
使有硬件的TWI我也想啊,不过它只有一个,而我要用两个的I2C,
一个是用来做跟上位机通讯(本单片机作为从机),上位机是电脑通过一个转换器(uart=>I2C)
送给单片机的,而本身作为从机的单片机(atmega48)又要作为主机来送数给带I2C接口的DAC6574(TI公司的)来实现,DA转换,所以得模拟一个I2C,
对了,我现在用硬件TWI通讯时会出现这样的情况:请分析一下
现像:如果主机(其实就是那个转换器uart转I2C)先通电,然后从机(atmega48)再通电通讯则正常,
反过来,说不行了通讯不了,
(在主机还没有通电时量M48的SDA,SCL的电平为0V,主机通电时量它们的电平为1.5V)
这时主机就再也找不到从机了,,,,
如果从机再断电,通电(相当从机后通电),就又可以正常通讯了(
程序如下:
//常用TWI操作(从模式写和从模式读)
#define Test_Ack() (TWSR & 0x08)
#define Twi_ACK() (TWCR=(1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE))
#define Twi_NoACK() (TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE))
#define Twi_Stop() (TWCR=(1<<TWSTO)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE))
#define Twi_Write_Byte(x) {TWDR=(x); TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE);}
//TWI传输状态
#define TWI_MEM_ADR 0x5A
#define TWI_MEM_DATA 0xA5
#define TWI_NONE 0
unsigned char Twi_State;
unsigned char Mem_Data, Mem_Adr, Mem_Write_Flag;
//---------------------------------------------------------------
#define TRUE 1
#define FALSE 0
#pragma interrupt_handler twi_isr:25
void twi_isr(void)
{ unsigned char status, dat;
status = TWSR & 0xF8;
switch(status)
{
//-------------- I2C 写相关:0x60, 0x80, 0xA0 -------------------
case 0x60: Twi_State = TWI_MEM_ADR;
Twi_ACK();
break;
case 0x80: if(Twi_State == TWI_MEM_ADR)
{ Mem_Adr = TWDR;
Twi_State = TWI_MEM_DATA;
}
else if(Twi_State == TWI_MEM_DATA)
{ Mem_Data = TWDR;
Mem_Write_Flag = TRUE;
Twi_State = TWI_NONE;
}
Twi_ACK();
break;
case 0xA0: Twi_State = TWI_NONE;
Twi_ACK();
break;
// ----------- I2C 读相关 0xA8, 0xC0 ---------------
case 0xA8: Twi_Write_Byte( Ram_Buf );
Twi_ACK();
break;
case 0xC0: Twi_ACK();
break;
default: Twi_State = TWI_NONE;
Twi_Stop();
break;
}
} 请参考《M128》书的第五章,AVR的I2C本身硬件有总线仲裁的功能。
使用I2C多主通信,需要你对I2C协议有比较深的了解,然后才能编写自己的程序。
如果你对I2C不是非常了解,只能采取你原来的设计,用I/O模拟一个I2C。 嗯,现在就去看第五章,
再次感谢的热心指点! 问题似乎找到了,解决了
把放面的
#define Twi_Stop() (TWCR=(1<<TWSTO)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE))
改成
#define Twi_Stop() (TWCR==(1<<TWEA)|(1<<TWSTO)|(1<<TWINT)|(1<<TWEN)(1<<TWIE))
现在就不会有,先后上电会有通讯不正常的了,
试了几个片子都没有问题了,,,
自己感觉现在应该算是解决问题了,, 我是刚学AVR的新手,刚好也是用本身作为从机的单片机(atmega48)将主机送的数传给带I2C接口的DAC6574(TI公司的)进行DA转换,但在进行调试时发出地址后却总是不应答,敬请各位高手能否指点一下?(急!!!!!!!!!!)在此谢过!!!!!!!!!! 泰山还真神奇-----把SPI接口的DS1302 硬是用IIC驱动,变成名副其实的[带I2C的从器件(DS1302)]。
不过后来驱动的是带I2C接口的DAC6574。
参考MAXIM/DALLAS的DS1302手册,DS1302的接口是Simple 3-Wire Interface。
Interfacing the DS1302 with a microprocessor is simplified by using synchronous serial communication. Only three wires are required to communicate with the clock/RAM: CE, I/O (data line), and SCLK (serial clock). Data can be transferred to and from the clock/RAM 1 byte at a time or in a burst of up to 31 bytes. The DS1302 is designed to operate on very low power and retain data and clock information on less than 1uW. 我是刚学AVR的新手,刚好也是用本身作为从机的单片机(atmega48)将主机送的数传给带I2C接口的DAC6574(TI公司的)进行DA转换,但在进行调试时发出地址后却总是不应答,敬请网友泰山能否将你的源程序传上来借阅一下?(急!!!!!!!!!!)在此谢过!!!!!!!!!! 我也是发送地址后不应答,不知道为什么?郁闷了 在我的书中第16章有若干个I2C的应用例子,采用I/O模拟和使用TWI硬件口的都有.希望仔细学习和参考. ds1302不是I2C接口吧.应该是SPI才对吧.CS,SCLK,DI,DOUT ds1302是3线接口,但也不是标准的SPI,需要用I/O模拟. CVAVR中有操作的函数,可以直接使用.参考我编写书的最后一章,里面的例子使用的就是DS1302. mark
1111!!!!! 本栏目是有价值的古墓,深入挖掘可以获得许多金银财宝的。只需要踏实认真的态度。 留爪,学习 mark!
页:
[1]