tarzar 发表于 2005-7-26 09:08:50

我用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

machao 发表于 2005-7-26 12:12:16

首先注意,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?

tarzar 发表于 2005-7-26 14:29:02

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;                                                       

        }

}

machao 发表于 2005-7-26 22:34:51

请参考《M128》书的第五章,AVR的I2C本身硬件有总线仲裁的功能。



使用I2C多主通信,需要你对I2C协议有比较深的了解,然后才能编写自己的程序。



如果你对I2C不是非常了解,只能采取你原来的设计,用I/O模拟一个I2C。

tarzar 发表于 2005-7-27 08:19:10

嗯,现在就去看第五章,



再次感谢的热心指点!

tarzar 发表于 2005-8-14 16:51:21

问题似乎找到了,解决了

把放面的

#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))



现在就不会有,先后上电会有通讯不正常的了,



试了几个片子都没有问题了,,,



自己感觉现在应该算是解决问题了,,

aladyang 发表于 2006-3-27 14:58:20

我是刚学AVR的新手,刚好也是用本身作为从机的单片机(atmega48)将主机送的数传给带I2C接口的DAC6574(TI公司的)进行DA转换,但在进行调试时发出地址后却总是不应答,敬请各位高手能否指点一下?(急!!!!!!!!!!)在此谢过!!!!!!!!!!

HJJourAVR 发表于 2006-3-27 15:10:38

泰山还真神奇-----把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.

aladyang 发表于 2006-3-27 15:42:52

我是刚学AVR的新手,刚好也是用本身作为从机的单片机(atmega48)将主机送的数传给带I2C接口的DAC6574(TI公司的)进行DA转换,但在进行调试时发出地址后却总是不应答,敬请网友泰山能否将你的源程序传上来借阅一下?(急!!!!!!!!!!)在此谢过!!!!!!!!!!

150571671 发表于 2008-4-26 23:15:09

我也是发送地址后不应答,不知道为什么?郁闷了

machao 发表于 2008-4-27 09:07:48

在我的书中第16章有若干个I2C的应用例子,采用I/O模拟和使用TWI硬件口的都有.希望仔细学习和参考.

liubinghui 发表于 2008-4-28 08:53:52

ds1302不是I2C接口吧.应该是SPI才对吧.CS,SCLK,DI,DOUT

machao 发表于 2008-4-28 16:40:37

ds1302是3线接口,但也不是标准的SPI,需要用I/O模拟. CVAVR中有操作的函数,可以直接使用.参考我编写书的最后一章,里面的例子使用的就是DS1302.

liyanlong55 发表于 2013-1-22 10:20:05

mark      
1111!!!!!

machao 发表于 2013-1-22 10:38:11

本栏目是有价值的古墓,深入挖掘可以获得许多金银财宝的。只需要踏实认真的态度。

w492901074 发表于 2013-3-11 19:05:39

留爪,学习

fengye7251 发表于 2013-4-9 12:25:09

mark!                  
页: [1]
查看完整版本: 我用avr的IO口来模拟I2C,是不是一定要不断地改变输入输出方向啊(DDRx)