搜索
bottom↓
回复: 16

我用avr的IO口来模拟I2C,是不是一定要不断地改变输入输出方向啊(DDRx)

[复制链接]

出0入4汤圆

发表于 2005-7-26 09:08:50 | 显示全部楼层 |阅读模式
马老师:

cpu:atmega8



因为现在内部的TWI被占用了,而又要去访问一个带I2C的从器件(DS1302)

所以只能用模拟的,,在仿真的过程中,发现在如果没有改变DDRx的方向则运行不能正常,

如果加上改变输入输出方向,就正常了,



令我不解的是:在读取从机的响应时,我是通过读PINx的,



不是说,不管方向寄存器为何值(0,或 1),都可以读取外部引脚的实际电平吗???

????,即然无关还为什么要加,不加又不行,这到底是为什么?????道理何在,作何解释?







还有一个一小问题:我就是不PINx复位时的值,为N/A,它是什么意思????



如图:

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 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?

出0入4汤圆

 楼主| 发表于 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[Mem_Adr] );

                                          Twi_ACK();

                                           break;

                                

                case 0xC0:        Twi_ACK();

                                        break;



                default:        Twi_State = TWI_NONE;

                                        Twi_Stop();

                                        break;                                                       

        }

}

出0入0汤圆

发表于 2005-7-26 22:34:51 | 显示全部楼层
请参考《M128》书的第五章,AVR的I2C本身硬件有总线仲裁的功能。



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



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

出0入4汤圆

 楼主| 发表于 2005-7-27 08:19:10 | 显示全部楼层
嗯,现在就去看第五章,



再次感谢的热心指点!

出0入4汤圆

 楼主| 发表于 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))



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



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



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

出0入0汤圆

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

出0入0汤圆

发表于 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.

出0入0汤圆

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

出0入0汤圆

发表于 2008-4-26 23:15:09 | 显示全部楼层
我也是发送地址后不应答,不知道为什么?郁闷了

出0入0汤圆

发表于 2008-4-27 09:07:48 | 显示全部楼层
在我的书中第16章有若干个I2C的应用例子,采用I/O模拟和使用TWI硬件口的都有.希望仔细学习和参考.

出0入0汤圆

发表于 2008-4-28 08:53:52 | 显示全部楼层
ds1302不是I2C接口吧.应该是SPI才对吧.CS,SCLK,DI,DOUT

出0入0汤圆

发表于 2008-4-28 16:40:37 | 显示全部楼层
ds1302是3线接口,但也不是标准的SPI,需要用I/O模拟. CVAVR中有操作的函数,可以直接使用.参考我编写书的最后一章,里面的例子使用的就是DS1302.

出0入0汤圆

发表于 2013-1-22 10:20:05 | 显示全部楼层
mark      
1111!!!!!

出0入0汤圆

发表于 2013-1-22 10:38:11 | 显示全部楼层
本栏目是有价值的古墓,深入挖掘可以获得许多金银财宝的。只需要踏实认真的态度。

出0入0汤圆

发表于 2013-3-11 19:05:39 | 显示全部楼层
留爪,学习

出0入0汤圆

发表于 2013-4-9 12:25:09 | 显示全部楼层
mark!                  
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 20:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表